Merge remote-tracking branch 'origin/dev' into feature/new-sms-command

This commit is contained in:
piotrek 2022-12-11 22:46:51 +01:00
commit 5485792801
128 changed files with 1488 additions and 956 deletions

View file

@ -11,7 +11,6 @@ interface NsClient : Sync {
val version: Version val version: Version
val address: String val address: String
val nsClientService: NSClientService?
fun pause(newState: Boolean) fun pause(newState: Boolean)
fun resend(reason: String) fun resend(reason: String)
@ -24,9 +23,6 @@ interface NsClient : Sync {
fun resetToFullSync() fun resetToFullSync()
interface NSClientService { fun dbAdd(collection: String, data: JSONObject, originalObject: Any, progress: String)
fun dbUpdate(collection: String, _id: String?, data: JSONObject?, originalObject: Any, progress: String)
fun dbAdd(collection: String, data: JSONObject, originalObject: Any, progress: String)
fun dbUpdate(collection: String, _id: String?, data: JSONObject?, originalObject: Any, progress: String)
}
} }

View file

@ -3,12 +3,16 @@ package info.nightscout.sdk
import android.content.Context import android.content.Context
import info.nightscout.sdk.exceptions.DateHeaderOutOfToleranceException import info.nightscout.sdk.exceptions.DateHeaderOutOfToleranceException
import info.nightscout.sdk.exceptions.InvalidAccessTokenException import info.nightscout.sdk.exceptions.InvalidAccessTokenException
import info.nightscout.sdk.exceptions.InvalidFormatNightscoutException
import info.nightscout.sdk.exceptions.TodoNightscoutException import info.nightscout.sdk.exceptions.TodoNightscoutException
import info.nightscout.sdk.exceptions.UnknownResponseNightscoutException
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.entry.NSSgvV3 import info.nightscout.sdk.localmodel.entry.NSSgvV3
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.toRemoteTreatment
import info.nightscout.sdk.mapper.toSgv import info.nightscout.sdk.mapper.toSgv
import info.nightscout.sdk.mapper.toTreatment import info.nightscout.sdk.mapper.toTreatment
import info.nightscout.sdk.networking.NetworkStackBuilder import info.nightscout.sdk.networking.NetworkStackBuilder
@ -58,6 +62,8 @@ class NSAndroidClientImpl(
accessToken = accessToken, accessToken = accessToken,
logging = logging logging = logging
) )
override var lastStatus: Status? = null
private set
/* /*
* TODO: how should our result look like? * TODO: how should our result look like?
@ -81,7 +87,7 @@ class NSAndroidClientImpl(
} }
override suspend fun getStatus(): Status = callWrapper(dispatcher) { override suspend fun getStatus(): Status = callWrapper(dispatcher) {
api.statusSimple().result!!.toLocal() api.statusSimple().result!!.toLocal().also { lastStatus = it }
} }
// TODO: return something better than a String // TODO: return something better than a String
@ -152,6 +158,22 @@ class NSAndroidClientImpl(
} }
} }
override suspend fun createTreatment(nsTreatment: NSTreatment): CreateUpdateResponse = callWrapper(dispatcher) {
val remoteTreatment = nsTreatment.toRemoteTreatment() ?: throw InvalidFormatNightscoutException()
val response = api.createTreatment(remoteTreatment)
if (response.isSuccessful) {
return@callWrapper CreateUpdateResponse(
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 TodoNightscoutException() // TODO: react to response errors (offline, ...)
}
}
private suspend fun <T> callWrapper(dispatcher: CoroutineDispatcher, block: suspend () -> T): T = private suspend fun <T> callWrapper(dispatcher: CoroutineDispatcher, block: suspend () -> T): T =
withContext(dispatcher) { withContext(dispatcher) {
retry( retry(

View file

@ -0,0 +1,3 @@
package info.nightscout.sdk.exceptions
class InvalidFormatNightscoutException : NightscoutException()

View file

@ -0,0 +1,3 @@
package info.nightscout.sdk.exceptions
class UnknownResponseNightscoutException : NightscoutException()

View file

@ -2,12 +2,14 @@ package info.nightscout.sdk.interfaces
import info.nightscout.sdk.localmodel.Status import info.nightscout.sdk.localmodel.Status
import info.nightscout.sdk.localmodel.entry.NSSgvV3 import info.nightscout.sdk.localmodel.entry.NSSgvV3
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 info.nightscout.sdk.remotemodel.RemoteDeviceStatus
interface NSAndroidClient { interface NSAndroidClient {
val lastStatus: Status?
suspend fun getVersion(): String suspend fun getVersion(): String
suspend fun getStatus(): Status suspend fun getStatus(): Status
suspend fun getEntries(): String suspend fun getEntries(): String
@ -18,4 +20,5 @@ interface NSAndroidClient {
suspend fun getSgvsNewerThan(from: Long, limit: Long): List<NSSgvV3> suspend fun getSgvsNewerThan(from: Long, limit: Long): List<NSSgvV3>
suspend fun getTreatmentsModifiedSince(from: Long, limit: Long): List<NSTreatment> suspend fun getTreatmentsModifiedSince(from: Long, limit: Long): List<NSTreatment>
suspend fun getDeviceStatusModifiedSince(from: Long): List<RemoteDeviceStatus> suspend fun getDeviceStatusModifiedSince(from: Long): List<RemoteDeviceStatus>
suspend fun createTreatment(NsTreatment: NSTreatment): CreateUpdateResponse
} }

View file

@ -7,4 +7,7 @@ data class ApiPermissions(
val profile: ApiPermission, val profile: ApiPermission,
val settings: ApiPermission, val settings: ApiPermission,
val treatments: ApiPermission val treatments: ApiPermission
) ) {
fun isFull() = deviceStatus.full && entries.full && food.full && profile.full && settings.full && treatments.full
fun isRead() = deviceStatus.read && entries.read && food.read && profile.read && settings.read && treatments.read
}

View file

@ -0,0 +1,8 @@
package info.nightscout.sdk.localmodel.treatment
class CreateUpdateResponse(
val identifier: String?,
val isDeduplication: Boolean? = false,
val deduplicatedIdentifier: String? = null,
val lastModified: Long? = null
)

View file

@ -7,8 +7,8 @@ data class NSBolus(
override val device: String?, override val device: String?,
override val identifier: String, override val identifier: String,
override val units: NsUnits?, override val units: NsUnits?,
override val srvModified: Long, override val srvModified: Long?,
override val srvCreated: Long, override val srvCreated: Long?,
override val utcOffset: Long, override val utcOffset: Long,
override val subject: String?, override val subject: String?,
override var isReadOnly: Boolean, override var isReadOnly: Boolean,

View file

@ -8,8 +8,8 @@ data class NSBolusWizard(
override val device: String?, override val device: String?,
override val identifier: String, override val identifier: String,
override val units: NsUnits?, override val units: NsUnits?,
override val srvModified: Long, override val srvModified: Long?,
override val srvCreated: Long, override val srvCreated: Long?,
override val utcOffset: Long, override val utcOffset: Long,
override val subject: String?, override val subject: String?,
override var isReadOnly: Boolean, override var isReadOnly: Boolean,

View file

@ -7,8 +7,8 @@ data class NSCarbs(
override val device: String?, override val device: String?,
override val identifier: String, override val identifier: String,
override val units: NsUnits?, override val units: NsUnits?,
override val srvModified: Long, override val srvModified: Long?,
override val srvCreated: Long, override val srvCreated: Long?,
override val utcOffset: Long, override val utcOffset: Long,
override val subject: String?, override val subject: String?,
override var isReadOnly: Boolean, override var isReadOnly: Boolean,

View file

@ -8,8 +8,8 @@ data class NSEffectiveProfileSwitch(
override val device: String?, override val device: String?,
override val identifier: String, override val identifier: String,
override val units: NsUnits?, override val units: NsUnits?,
override val srvModified: Long, override val srvModified: Long?,
override val srvCreated: Long, override val srvCreated: Long?,
override val utcOffset: Long, override val utcOffset: Long,
override val subject: String?, override val subject: String?,
override var isReadOnly: Boolean, override var isReadOnly: Boolean,

View file

@ -7,8 +7,8 @@ data class NSExtendedBolus(
override val device: String?, override val device: String?,
override val identifier: String, override val identifier: String,
override val units: NsUnits?, override val units: NsUnits?,
override val srvModified: Long, override val srvModified: Long?,
override val srvCreated: Long, override val srvCreated: Long?,
override val utcOffset: Long, override val utcOffset: Long,
override val subject: String?, override val subject: String?,
override var isReadOnly: Boolean, override var isReadOnly: Boolean,
@ -21,5 +21,5 @@ data class NSExtendedBolus(
override val pumpSerial: String?, override val pumpSerial: String?,
val duration: Long, val duration: Long,
val enteredinsulin: Double, val enteredinsulin: Double,
val isEmulatingTempbasal: Boolean val isEmulatingTempBasal: Boolean?
) : NSTreatment ) : NSTreatment

View file

@ -7,8 +7,8 @@ data class NSOfflineEvent(
override val device: String?, override val device: String?,
override val identifier: String, override val identifier: String,
override val units: NsUnits?, override val units: NsUnits?,
override val srvModified: Long, override val srvModified: Long?,
override val srvCreated: Long, override val srvCreated: Long?,
override val utcOffset: Long, override val utcOffset: Long,
override val subject: String?, override val subject: String?,
override var isReadOnly: Boolean, override var isReadOnly: Boolean,

View file

@ -8,8 +8,8 @@ data class NSProfileSwitch(
override val device: String?, override val device: String?,
override val identifier: String, override val identifier: String,
override val units: NsUnits?, override val units: NsUnits?,
override val srvModified: Long, override val srvModified: Long?,
override val srvCreated: Long, override val srvCreated: Long?,
override val utcOffset: Long, override val utcOffset: Long,
override val subject: String?, override val subject: String?,
override var isReadOnly: Boolean, override var isReadOnly: Boolean,

View file

@ -8,8 +8,8 @@ data class NSTemporaryBasal(
override val device: String?, override val device: String?,
override val identifier: String, override val identifier: String,
override val units: NsUnits?, override val units: NsUnits?,
override val srvModified: Long, override val srvModified: Long?,
override val srvCreated: Long, override val srvCreated: Long?,
override val utcOffset: Long, override val utcOffset: Long,
override val subject: String?, override val subject: String?,
override var isReadOnly: Boolean, override var isReadOnly: Boolean,
@ -21,9 +21,11 @@ data class NSTemporaryBasal(
override val pumpType: String?, override val pumpType: String?,
override val pumpSerial: String?, override val pumpSerial: String?,
val duration: Long, val duration: Long,
val rate: Double, val rate: Double, // when sending to NS always convertedToAbsolute(timestamp, profile)
val isAbsolute: Boolean, val isAbsolute: Boolean,
val type: Type val type: Type,
val percent: Double? = null, // when sending to NS (rate - 100)
val absolute: Double? = null // when sending to NS (rate)
) : NSTreatment { ) : NSTreatment {
enum class Type { enum class Type {

View file

@ -7,8 +7,8 @@ data class NSTemporaryTarget(
override val device: String?, override val device: String?,
override val identifier: String, override val identifier: String,
override val units: NsUnits?, override val units: NsUnits?,
override val srvModified: Long, override val srvModified: Long?,
override val srvCreated: Long, override val srvCreated: Long?,
override val utcOffset: Long, override val utcOffset: Long,
override val subject: String?, override val subject: String?,
override var isReadOnly: Boolean, override var isReadOnly: Boolean,

View file

@ -8,8 +8,8 @@ data class NSTherapyEvent(
override val device: String?, override val device: String?,
override val identifier: String, override val identifier: String,
override val units: NsUnits?, override val units: NsUnits?,
override val srvModified: Long, override val srvModified: Long?,
override val srvCreated: Long, override val srvCreated: Long?,
override val utcOffset: Long, override val utcOffset: Long,
override val subject: String?, override val subject: String?,
override var isReadOnly: Boolean, override var isReadOnly: Boolean,

View file

@ -8,8 +8,8 @@ interface NSTreatment {
val identifier: String val identifier: String
val units: NsUnits? val units: NsUnits?
val eventType: EventType val eventType: EventType
val srvModified: Long val srvModified: Long?
val srvCreated: Long val srvCreated: Long?
val utcOffset: Long val utcOffset: Long
val subject: String? val subject: String?
var isReadOnly: Boolean var isReadOnly: Boolean

View file

@ -117,7 +117,7 @@ internal fun RemoteTreatment.toTreatment(): NSTreatment? {
pumpSerial = extendedEmulated.pumpSerial, pumpSerial = extendedEmulated.pumpSerial,
enteredinsulin = extendedEmulated.enteredinsulin ?: 0.0, enteredinsulin = extendedEmulated.enteredinsulin ?: 0.0,
duration = extendedEmulated.durationInMilliseconds ?: TimeUnit.MINUTES.toMillis(extendedEmulated.duration ?: 0L), duration = extendedEmulated.durationInMilliseconds ?: TimeUnit.MINUTES.toMillis(extendedEmulated.duration ?: 0L),
isEmulatingTempbasal = extendedEmulated.isEmulatingTempBasal isEmulatingTempBasal = extendedEmulated.isEmulatingTempBasal
) )
} }
@ -329,10 +329,270 @@ internal fun RemoteTreatment.toTreatment(): NSTreatment? {
pumpSerial = this.pumpSerial, pumpSerial = this.pumpSerial,
enteredinsulin = this.enteredinsulin, enteredinsulin = this.enteredinsulin,
duration = this.durationInMilliseconds ?: TimeUnit.MINUTES.toMillis(this.duration ?: 0L), duration = this.durationInMilliseconds ?: TimeUnit.MINUTES.toMillis(this.duration ?: 0L),
isEmulatingTempbasal = this.isEmulatingTempBasal isEmulatingTempBasal = this.isEmulatingTempBasal
) )
} }
} }
return null return null
} }
internal fun NSTreatment.toRemoteTreatment(): RemoteTreatment? =
when (this) {
is NSBolus -> RemoteTreatment(
date = date,
device = device,
identifier = identifier,
units = units?.value,
utcOffset = utcOffset,
subject = subject,
isReadOnly = isReadOnly,
isValid = isValid,
eventType = eventType,
notes = notes,
pumpId = pumpId,
endId = endId,
pumpType = pumpType,
pumpSerial = pumpSerial,
insulin = insulin,
type = type.name
)
is NSCarbs -> RemoteTreatment(
date = date,
device = device,
identifier = identifier,
units = units?.value,
utcOffset = utcOffset,
subject = subject,
isReadOnly = isReadOnly,
isValid = isValid,
eventType = eventType,
notes = notes,
pumpId = pumpId,
endId = endId,
pumpType = pumpType,
pumpSerial = pumpSerial,
carbs = carbs,
duration = duration
)
is NSTemporaryTarget -> RemoteTreatment(
date = date,
device = device,
identifier = identifier,
units = units?.value,
srvModified = srvModified,
srvCreated = srvCreated,
utcOffset = utcOffset,
subject = subject,
isReadOnly = isReadOnly,
isValid = isValid,
eventType = eventType,
notes = notes,
pumpId = pumpId,
endId = endId,
pumpType = pumpType,
pumpSerial = pumpSerial,
duration = TimeUnit.MILLISECONDS.toMinutes(duration),
durationInMilliseconds = duration,
targetBottom = targetBottom,
targetTop = targetTop,
reason = reason.text
)
/*
// Convert back emulated TBR -> EB
eventType == EventType.TEMPORARY_BASAL && extendedEmulated != null ->
return RemoteTreatment(
date = treatmentTimestamp,
device = device,
identifier = identifier,
units = NsUnits.fromString(extendedEmulated.units),
srvModified = srvModified,
srvCreated = srvCreated,
utcOffset = utcOffset ?: 0,
subject = subject,
isReadOnly = extendedEmulated.isReadOnly ?: false,
isValid = extendedEmulated.isValid ?: true,
eventType = extendedEmulated.eventType,
notes = extendedEmulated.notes,
pumpId = extendedEmulated.pumpId,
endId = extendedEmulated.endId,
pumpType = extendedEmulated.pumpType,
pumpSerial = extendedEmulated.pumpSerial,
enteredinsulin = extendedEmulated.enteredinsulin ?: 0.0,
duration = extendedEmulated.durationInMilliseconds ?: TimeUnit.MINUTES.toMillis(extendedEmulated.duration ?: 0L),
isEmulatingTempbasal = extendedEmulated.isEmulatingTempBasal
)
}
*/
is NSTemporaryBasal -> RemoteTreatment(
date = date,
device = device,
identifier = identifier,
units = units?.value,
srvModified = srvModified,
srvCreated = srvCreated,
utcOffset = utcOffset,
subject = subject,
isReadOnly = isReadOnly,
isValid = isValid,
eventType = eventType,
notes = notes,
pumpId = pumpId,
endId = endId,
pumpType = pumpType,
pumpSerial = pumpSerial,
duration = TimeUnit.MILLISECONDS.toMinutes(duration),
durationInMilliseconds = duration,
absolute = absolute,
percent = percent,
rate = absolute,
type = type.name
)
is NSEffectiveProfileSwitch -> RemoteTreatment(
date = date,
device = device,
identifier = identifier,
units = units?.value,
srvModified = srvModified,
srvCreated = srvCreated,
utcOffset = utcOffset,
subject = subject,
isReadOnly = isReadOnly,
isValid = isValid,
eventType = eventType,
notes = notes,
pumpId = pumpId,
endId = endId,
pumpType = pumpType,
pumpSerial = pumpSerial,
profileJson = profileJson.toString(),
originalProfileName = originalProfileName,
originalCustomizedName = originalCustomizedName,
originalTimeshift = originalTimeshift,
originalPercentage = originalPercentage,
originalDuration = originalDuration,
originalEnd = originalEnd
)
is NSProfileSwitch -> RemoteTreatment(
date = date,
device = device,
identifier = identifier,
units = units?.value,
srvModified = srvModified,
srvCreated = srvCreated,
utcOffset = utcOffset,
subject = subject,
isReadOnly = isReadOnly,
isValid = isValid,
eventType = eventType,
notes = notes,
pumpId = pumpId,
endId = endId,
pumpType = pumpType,
pumpSerial = pumpSerial,
profileJson = profileJson.toString(), // must be de-customized
profile = profileName,
originalProfileName = originalProfileName,
originalDuration = originalDuration,
duration = duration,
timeshift = timeShift,
percentage = percentage,
)
is NSBolusWizard -> RemoteTreatment(
date = date,
device = device,
identifier = identifier,
units = units?.value,
srvModified = srvModified,
srvCreated = srvCreated,
utcOffset = utcOffset,
subject = subject,
isReadOnly = isReadOnly,
isValid = isValid,
eventType = eventType,
notes = notes,
pumpId = pumpId,
endId = endId,
pumpType = pumpType,
pumpSerial = pumpSerial,
bolusCalculatorResult = bolusCalculatorResult,
glucose = glucose
)
is NSTherapyEvent -> RemoteTreatment(
date = date,
device = device,
identifier = identifier,
units = units?.value,
srvModified = srvModified,
srvCreated = srvCreated,
utcOffset = utcOffset,
subject = subject,
isReadOnly = isReadOnly,
isValid = isValid,
eventType = eventType,
notes = notes,
pumpId = pumpId,
endId = endId,
pumpType = pumpType,
pumpSerial = pumpSerial,
duration = TimeUnit.MILLISECONDS.toMinutes(duration),
durationInMilliseconds = duration,
glucose = glucose,
enteredBy = enteredBy,
glucoseType = glucoseType?.text
)
is NSOfflineEvent -> RemoteTreatment(
date = date,
device = device,
identifier = identifier,
units = units?.value,
srvModified = srvModified,
srvCreated = srvCreated,
utcOffset = utcOffset,
subject = subject,
isReadOnly = isReadOnly,
isValid = isValid,
eventType = eventType,
notes = notes,
pumpId = pumpId,
endId = endId,
pumpType = pumpType,
pumpSerial = pumpSerial,
duration = TimeUnit.MILLISECONDS.toMinutes(duration),
durationInMilliseconds = duration,
reason = reason.name
)
is NSExtendedBolus -> RemoteTreatment(
date = date,
device = device,
identifier = identifier,
units = units?.value,
srvModified = srvModified,
srvCreated = srvCreated,
utcOffset = utcOffset,
subject = subject,
isReadOnly = isReadOnly,
isValid = isValid,
eventType = eventType,
notes = notes,
pumpId = pumpId,
endId = endId,
pumpType = pumpType,
pumpSerial = pumpSerial,
enteredinsulin = enteredinsulin,
duration = TimeUnit.MILLISECONDS.toMinutes(duration),
durationInMilliseconds = duration,
isEmulatingTempBasal = isEmulatingTempBasal
)
else -> null
}

View file

@ -4,11 +4,17 @@ import com.google.gson.JsonElement
import info.nightscout.sdk.remotemodel.LastModified import info.nightscout.sdk.remotemodel.LastModified
import info.nightscout.sdk.remotemodel.RemoteDeviceStatus import info.nightscout.sdk.remotemodel.RemoteDeviceStatus
import info.nightscout.sdk.remotemodel.NSResponse import info.nightscout.sdk.remotemodel.NSResponse
import info.nightscout.sdk.remotemodel.RemoteCreateUpdateResponse
import info.nightscout.sdk.remotemodel.RemoteEntry import info.nightscout.sdk.remotemodel.RemoteEntry
import info.nightscout.sdk.remotemodel.RemoteStatusResponse import info.nightscout.sdk.remotemodel.RemoteStatusResponse
import info.nightscout.sdk.remotemodel.RemoteTreatment import info.nightscout.sdk.remotemodel.RemoteTreatment
import okhttp3.RequestBody
import retrofit2.Call
import retrofit2.Response import retrofit2.Response
import retrofit2.http.Body
import retrofit2.http.GET import retrofit2.http.GET
import retrofit2.http.Header
import retrofit2.http.POST
import retrofit2.http.Path import retrofit2.http.Path
import retrofit2.http.Query import retrofit2.http.Query
@ -48,4 +54,8 @@ internal interface NightscoutRemoteService {
@GET("v3/devicestatus/history/{from}") @GET("v3/devicestatus/history/{from}")
suspend fun getDeviceStatusModifiedSince(@Path("from") from: Long): Response<NSResponse<List<RemoteDeviceStatus>>> suspend fun getDeviceStatusModifiedSince(@Path("from") from: Long): Response<NSResponse<List<RemoteDeviceStatus>>>
@POST("v3/treatments")
fun createTreatment(@Body remoteTreatment: RemoteTreatment): Response<NSResponse<RemoteCreateUpdateResponse>>
} }

View file

@ -17,6 +17,13 @@ internal data class RemoteStorage(
@SerializedName("version") val version: String @SerializedName("version") val version: String
) )
internal data class RemoteCreateUpdateResponse(
@SerializedName("identifier") val identifier: String?,
@SerializedName("isDeduplication") val isDeduplication: Boolean?,
@SerializedName("deduplicatedIdentifier") val deduplicatedIdentifier: String?,
@SerializedName("lastModified") val lastModified: Long?
)
internal data class RemoteApiPermissions( internal data class RemoteApiPermissions(
@SerializedName("devicestatus") val deviceStatus: RemoteApiPermission, @SerializedName("devicestatus") val deviceStatus: RemoteApiPermission,
@SerializedName("entries") val entries: RemoteApiPermission, @SerializedName("entries") val entries: RemoteApiPermission,

View file

@ -18,72 +18,71 @@ import org.json.JSONObject
* */ * */
internal data class RemoteTreatment( internal data class RemoteTreatment(
@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("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("date") val date: Long?, // integer($int64) or string required timestamp when the record or event occurred, you can choose from three input formats Unix epoch in milliseconds (1525383610088), Unix epoch in seconds (1525383610), ISO 8601 with optional timezone ('2018-05-03T21:40:10.088Z' or '2018-05-03T23:40:10.088+02:00') @SerializedName("date") val date: Long? = null, // integer($int64) or string required timestamp when the record or event occurred, you can choose from three input formats Unix epoch in milliseconds (1525383610088), Unix epoch in seconds (1525383610), ISO 8601 with optional timezone ('2018-05-03T21:40:10.088Z' or '2018-05-03T23:40:10.088+02:00')
@SerializedName("mills") val mills: Long?, // integer($int64) or string required timestamp when the record or event occurred, you can choose from three input formats Unix @SerializedName("mills") val mills: Long? = null, // integer($int64) or string required timestamp when the record or event occurred, you can choose from three input formats Unix
@SerializedName("timestamp") val timestamp: Long?, // integer($int64) or string required timestamp when the record or event occurred, you can choose from three input formats Unix epoch in milliseconds (1525383610088), Unix epoch in seconds (1525383610), ISO 8601 with optional timezone ('2018-05-03T21:40:10.088Z' or '2018-05-03T23:40:10.088+02:00') @SerializedName("timestamp") val timestamp: Long? = null, // integer($int64) or string required timestamp when the record or event occurred, you can choose from three input formats Unix epoch in milliseconds (1525383610088), Unix epoch in seconds (1525383610), ISO 8601 with optional timezone ('2018-05-03T21:40:10.088Z' or '2018-05-03T23:40:10.088+02:00')
@SerializedName("created_at") val created_at: String, // integer($int64) 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("created_at") val created_at: String? = null, // integer($int64) 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("utcOffset") val utcOffset: Long?, // integer Local UTC offset (timezone) of the event in minutes. This field can be set either directly by the client (in the incoming @SerializedName("utcOffset") val utcOffset: Long? = null, // integer Local UTC offset (timezone) of the event in minutes. This field can be set either directly by the client (in the incoming document) or it is automatically parsed from the date field.
// document) or it is automatically parsed from the date field.
// @SerializedName("app") val app : String, // TODO required ? Application or system in which the record was entered by human or device for the first time. // @SerializedName("app") val app : String, // TODO required ? Application or system in which the record was entered by human or device for the first time.
@SerializedName("device") val device: String?, // string The device from which the data originated (including serial number of the device, if it is relevant and safe). @SerializedName("device") val device: String? = null, // string The device from which the data originated (including serial number of the device, if it is relevant and safe).
@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("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("subject") val subject: String?, // string Name of the security subject (within Nightscout scope) which has created the document. This field is automatically set by the server from the passed token or JWT. @SerializedName("subject") val subject: String? = null, // string Name of the security subject (within Nightscout scope) which has created the document. This field is automatically set by the server from the passed token or JWT.
@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("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("modifiedBy") val modifiedBy: String?, // string Name of the security subject (within Nightscout scope) which has patched or deleted the document for the last time. This field is automatically set by the server. @SerializedName("modifiedBy") val modifiedBy: String? = null, // string Name of the security subject (within Nightscout scope) which has patched or deleted the document for the last time. This field is automatically set by the server.
@SerializedName("isValid") val isValid: Boolean?, // boolean A flag set by the server only for deleted documents. This field appears only within history operation and for documents which were deleted by API v3 (and they always have a false value) @SerializedName("isValid") val isValid: Boolean? = null, // boolean A flag set by the server only for deleted documents. This field appears only within history operation and for documents which were deleted by API v3 (and they always have a false value)
@SerializedName("isReadOnly") val isReadOnly: Boolean?, // boolean A flag set by client that locks the document from any changes. Every document marked with isReadOnly=true is forever immutable and cannot even be deleted. @SerializedName("isReadOnly") val isReadOnly: Boolean? = null, // boolean A flag set by client that locks the document from any changes. Every document marked with isReadOnly=true is forever immutable and cannot even be deleted.
@SerializedName("eventType") val eventType: EventType, // string "BG Check", "Snack Bolus", "Meal Bolus", "Correction Bolus", "Carb Correction", "Combo Bolus", "Announcement", "Note", "Question", "Exercise", "Site Change", "Sensor Start", "Sensor Change", "Pump Battery Change", "Insulin Change", "Temp Basal", "Profile Switch", "D.A.D. Alert", "Temporary Target", "OpenAPS Offline", "Bolus Wizard" @SerializedName("eventType") val eventType: EventType, // string "BG Check", "Snack Bolus", "Meal Bolus", "Correction Bolus", "Carb Correction", "Combo Bolus", "Announcement", "Note", "Question", "Exercise", "Site Change", "Sensor Start", "Sensor Change", "Pump Battery Change", "Insulin Change", "Temp Basal", "Profile Switch", "D.A.D. Alert", "Temporary Target", "OpenAPS Offline", "Bolus Wizard"
@SerializedName("glucose") val glucose: Double?, // double Current glucose @SerializedName("glucose") val glucose: Double? = null, // double Current glucose
@SerializedName("glucoseType") val glucoseType: String?, // string example: "Sensor", "Finger", "Manual" @SerializedName("glucoseType") val glucoseType: String? = null, // string example: "Sensor", "Finger", "Manual"
@SerializedName("units") val units: String?, // string The units for the glucose value, mg/dl or mmol/l. It is strongly recommended to fill in this field. @SerializedName("units") val units: String? = null, // string The units for the glucose value, mg/dl or mmol/l. It is strongly recommended to fill in this field.
@SerializedName("carbs") val carbs: Double?, // number... Amount of carbs given. @SerializedName("carbs") val carbs: Double? = null, // number... Amount of carbs given.
@SerializedName("protein") val protein: Int?, // number... Amount of protein given. @SerializedName("protein") val protein: Int? = null, // number... Amount of protein given.
@SerializedName("fat") val fat: Int?, // number... Amount of fat given. @SerializedName("fat") val fat: Int? = null, // number... Amount of fat given.
@SerializedName("insulin") val insulin: Double?, // number... Amount of insulin, if any. @SerializedName("insulin") val insulin: Double? = null, // number... Amount of insulin, if any.
@SerializedName("duration") val duration: Long?, // number... Duration in minutes. @SerializedName("duration") val duration: Long? = null, // number... Duration in minutes.
@SerializedName("durationInMilliseconds") val durationInMilliseconds: Long?, // number... Duration in milliseconds. @SerializedName("durationInMilliseconds") val durationInMilliseconds: Long? = null, // number... Duration in milliseconds.
@SerializedName("preBolus") val preBolus: Int?, // number... How many minutes the bolus was given before the meal started. @SerializedName("preBolus") val preBolus: Int? = null, // number... How many minutes the bolus was given before the meal started.
@SerializedName("splitNow") val splitNow: Int?, // number... Immediate part of combo bolus (in percent). @SerializedName("splitNow") val splitNow: Int? = null, // number... Immediate part of combo bolus (in percent).
@SerializedName("splitExt") val splitExt: Int?, // number... Extended part of combo bolus (in percent). @SerializedName("splitExt") val splitExt: Int? = null, // number... Extended part of combo bolus (in percent).
@SerializedName("percent") val percent: Double?, // number... Eventual basal change in percent. @SerializedName("percent") val percent: Double? = null, // number... Eventual basal change in percent.
@SerializedName("absolute") val absolute: Double?, // number... Eventual basal change in absolute value (insulin units per hour). @SerializedName("absolute") val absolute: Double? = null, // number... Eventual basal change in absolute value (insulin units per hour).
@SerializedName("targetTop") val targetTop: Double?, // number... Top limit of temporary target. @SerializedName("targetTop") val targetTop: Double? = null, // number... Top limit of temporary target.
@SerializedName("targetBottom") val targetBottom: Double?, // number... Bottom limit of temporary target. @SerializedName("targetBottom") val targetBottom: Double? = null, // number... Bottom limit of temporary target.
@SerializedName("profile") val profile: String?, // string Name of the profile to which the pump has been switched. @SerializedName("profile") val profile: String? = null, // string Name of the profile to which the pump has been switched.
@SerializedName("reason") val reason: String?, // string For example the reason why the profile has been switched or why the temporary target has been set. @SerializedName("reason") val reason: String? = null, // string For example the reason why the profile has been switched or why the temporary target has been set.
@SerializedName("notes") val notes: String?, // string Description/notes of treatment. @SerializedName("notes") val notes: String? = null, // string Description/notes of treatment.
@SerializedName("enteredBy") val enteredBy: String?, // string Who entered the treatment. @SerializedName("enteredBy") val enteredBy: String? = null, // string Who entered the treatment.
@SerializedName("endId") val endId: Long?, // long id of record which ended this @SerializedName("endId") val endId: Long? = null, // long id of record which ended this
@SerializedName("pumpId") val pumpId: Long?, // long or "Meal Bolus", "Correction Bolus", "Combo Bolus" ex 4102 not sure if long or int @SerializedName("pumpId") val pumpId: Long? = null, // long or "Meal Bolus", "Correction Bolus", "Combo Bolus" ex 4102 not sure if long or int
@SerializedName("pumpType") val pumpType: String?, // string "Meal Bolus", "Correction Bolus", "Combo Bolus" ex "ACCU_CHEK_INSIGHT_BLUETOOTH", @SerializedName("pumpType") val pumpType: String? = null, // string "Meal Bolus", "Correction Bolus", "Combo Bolus" ex "ACCU_CHEK_INSIGHT_BLUETOOTH",
@SerializedName("pumpSerial") val pumpSerial: String?, // string "Meal Bolus", "Correction Bolus", "Combo Bolus" "33013206", @SerializedName("pumpSerial") val pumpSerial: String? = null, // string "Meal Bolus", "Correction Bolus", "Combo Bolus" "33013206",
// other fields found in examples but not in documentation // other fields found in examples but not in documentation
@SerializedName("profileJson") val profileJson: String?, // string "Profile Switch" ex json toString "{\"units\":\"mg\\/dl\",\"dia\":5,\"timezone\":\"Africa\\/Cairo\", @SerializedName("profileJson") val profileJson: String? = null, // string "Profile Switch" ex json toString "{\"units\":\"mg\\/dl\",\"dia\":5,\"timezone\":\"Africa\\/Cairo\",
// \"sens\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":60},{\"time\":\"07:00\",\"timeAsSeconds\":25200,\"value\":60},{\"time\":\"08:00\",\"timeAsSeconds\":28800,\"value\":61.33333333333333},{\"time\":\"09:00\",\"timeAsSeconds\":32400,\"value\":65.33333333333333},{\"time\":\"10:00\",\"timeAsSeconds\":36000,\"value\":69.33333333333333},{\"time\":\"11:00\",\"timeAsSeconds\":39600,\"value\":73.33333333333333},{\"time\":\"13:00\",\"timeAsSeconds\":46800,\"value\":72},{\"time\":\"14:00\",\"timeAsSeconds\":50400,\"value\":68},{\"time\":\"15:00\",\"timeAsSeconds\":54000,\"value\":65.33333333333333},{\"time\":\"16:00\",\"timeAsSeconds\":57600,\"value\":65.33333333333333}],\"carbratio\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":5.7333333333333325},{\"time\":\"11:00\",\"timeAsSeconds\":39600,\"value\":7.333333333333333},{\"time\":\"16:00\",\"timeAsSeconds\":57600,\"value\":6.666666666666666}],\"basal\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":0.5249999999999999},{\"time\":\"01:00\",\"timeAsSeconds\":3600,\"value\":0.585},{\"time\":\"02:00\",\"timeAsSeconds\":7200,\"value\":0.6375},{\"time\":\"03:00\",\"timeAsSeconds\":10800,\"value\":0.5625},{\"time\":\"04:00\",\"timeAsSeconds\":14400,\"value\":0.4575},{\"time\":\"05:00\",\"timeAsSeconds\":18000,\"value\":0.5175},{\"time\":\"06:00\",\"timeAsSeconds\":21600,\"value\":0.48},{\"time\":\"07:00\",\"timeAsSeconds\":25200,\"value\":0.51},{\"time\":\"08:00\",\"timeAsSeconds\":28800,\"value\":0.48750000000000004},{\"time\":\"09:00\",\"timeAsSeconds\":32400,\"value\":0.48},{\"time\":\"10:00\",\"timeAsSeconds\":36000,\"value\":0.48750000000000004},{\"time\":\"11:00\",\"timeAsSeconds\":39600,\"value\":0.5025000000000001},{\"time\":\"12:00\",\"timeAsSeconds\":43200,\"value\":0.5549999999999999},{\"time\":\"13:00\",\"timeAsSeconds\":46800,\"value\":0.5700000000000001},{\"time\":\"14:00\",\"timeAsSeconds\":50400,\"value\":0.5700000000000001},{\"time\":\"15:00\",\"timeAsSeconds\":54000,\"value\":0.5775},{\"time\":\"16:00\",\"timeAsSeconds\":57600,\"value\":0.51},{\"time\":\"17:00\",\"timeAsSeconds\":61200,\"value\":0.54},{\"time\":\"18:00\",\"timeAsSeconds\":64800,\"value\":0.48750000000000004},{\"time\":\"19:00\",\"timeAsSeconds\":68400,\"value\":0.5249999999999999},{\"time\":\"20:00\",\"timeAsSeconds\":72000,\"value\":0.46499999999999997},{\"time\":\"21:00\",\"timeAsSeconds\":75600,\"value\":0.46499999999999997},{\"time\":\"22:00\",\"timeAsSeconds\":79200,\"value\":0.43499999999999994},{\"time\":\"23:00\",\"timeAsSeconds\":82800,\"value\":0.41250000000000003}],\"target_low\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":100},{\"time\":\"06:00\",\"timeAsSeconds\":21600,\"value\":90},{\"time\":\"09:00\",\"timeAsSeconds\":32400,\"value\":100},{\"time\":\"11:00\",\"timeAsSeconds\":39600,\"value\":90},{\"time\":\"14:00\",\"timeAsSeconds\":50400,\"value\":100},{\"time\":\"18:00\",\"timeAsSeconds\":64800,\"value\":90},{\"time\":\"21:00\",\"timeAsSeconds\":75600,\"value\":100}],\"target_high\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":100},{\"time\":\"06:00\",\"timeAsSeconds\":21600,\"value\":90},{\"time\":\"09:00\",\"timeAsSeconds\":32400,\"value\":100},{\"time\":\"11:00\",\"timeAsSeconds\":39600,\"value\":90},{\"time\":\"14:00\",\"timeAsSeconds\":50400,\"value\":100},{\"time\":\"18:00\",\"timeAsSeconds\":64800,\"value\":90},{\"time\":\"21:00\",\"timeAsSeconds\":75600,\"value\":100}]}", // \"sens\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":60},{\"time\":\"07:00\",\"timeAsSeconds\":25200,\"value\":60},{\"time\":\"08:00\",\"timeAsSeconds\":28800,\"value\":61.33333333333333},{\"time\":\"09:00\",\"timeAsSeconds\":32400,\"value\":65.33333333333333},{\"time\":\"10:00\",\"timeAsSeconds\":36000,\"value\":69.33333333333333},{\"time\":\"11:00\",\"timeAsSeconds\":39600,\"value\":73.33333333333333},{\"time\":\"13:00\",\"timeAsSeconds\":46800,\"value\":72},{\"time\":\"14:00\",\"timeAsSeconds\":50400,\"value\":68},{\"time\":\"15:00\",\"timeAsSeconds\":54000,\"value\":65.33333333333333},{\"time\":\"16:00\",\"timeAsSeconds\":57600,\"value\":65.33333333333333}],\"carbratio\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":5.7333333333333325},{\"time\":\"11:00\",\"timeAsSeconds\":39600,\"value\":7.333333333333333},{\"time\":\"16:00\",\"timeAsSeconds\":57600,\"value\":6.666666666666666}],\"basal\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":0.5249999999999999},{\"time\":\"01:00\",\"timeAsSeconds\":3600,\"value\":0.585},{\"time\":\"02:00\",\"timeAsSeconds\":7200,\"value\":0.6375},{\"time\":\"03:00\",\"timeAsSeconds\":10800,\"value\":0.5625},{\"time\":\"04:00\",\"timeAsSeconds\":14400,\"value\":0.4575},{\"time\":\"05:00\",\"timeAsSeconds\":18000,\"value\":0.5175},{\"time\":\"06:00\",\"timeAsSeconds\":21600,\"value\":0.48},{\"time\":\"07:00\",\"timeAsSeconds\":25200,\"value\":0.51},{\"time\":\"08:00\",\"timeAsSeconds\":28800,\"value\":0.48750000000000004},{\"time\":\"09:00\",\"timeAsSeconds\":32400,\"value\":0.48},{\"time\":\"10:00\",\"timeAsSeconds\":36000,\"value\":0.48750000000000004},{\"time\":\"11:00\",\"timeAsSeconds\":39600,\"value\":0.5025000000000001},{\"time\":\"12:00\",\"timeAsSeconds\":43200,\"value\":0.5549999999999999},{\"time\":\"13:00\",\"timeAsSeconds\":46800,\"value\":0.5700000000000001},{\"time\":\"14:00\",\"timeAsSeconds\":50400,\"value\":0.5700000000000001},{\"time\":\"15:00\",\"timeAsSeconds\":54000,\"value\":0.5775},{\"time\":\"16:00\",\"timeAsSeconds\":57600,\"value\":0.51},{\"time\":\"17:00\",\"timeAsSeconds\":61200,\"value\":0.54},{\"time\":\"18:00\",\"timeAsSeconds\":64800,\"value\":0.48750000000000004},{\"time\":\"19:00\",\"timeAsSeconds\":68400,\"value\":0.5249999999999999},{\"time\":\"20:00\",\"timeAsSeconds\":72000,\"value\":0.46499999999999997},{\"time\":\"21:00\",\"timeAsSeconds\":75600,\"value\":0.46499999999999997},{\"time\":\"22:00\",\"timeAsSeconds\":79200,\"value\":0.43499999999999994},{\"time\":\"23:00\",\"timeAsSeconds\":82800,\"value\":0.41250000000000003}],\"target_low\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":100},{\"time\":\"06:00\",\"timeAsSeconds\":21600,\"value\":90},{\"time\":\"09:00\",\"timeAsSeconds\":32400,\"value\":100},{\"time\":\"11:00\",\"timeAsSeconds\":39600,\"value\":90},{\"time\":\"14:00\",\"timeAsSeconds\":50400,\"value\":100},{\"time\":\"18:00\",\"timeAsSeconds\":64800,\"value\":90},{\"time\":\"21:00\",\"timeAsSeconds\":75600,\"value\":100}],\"target_high\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":100},{\"time\":\"06:00\",\"timeAsSeconds\":21600,\"value\":90},{\"time\":\"09:00\",\"timeAsSeconds\":32400,\"value\":100},{\"time\":\"11:00\",\"timeAsSeconds\":39600,\"value\":90},{\"time\":\"14:00\",\"timeAsSeconds\":50400,\"value\":100},{\"time\":\"18:00\",\"timeAsSeconds\":64800,\"value\":90},{\"time\":\"21:00\",\"timeAsSeconds\":75600,\"value\":100}]}",
@SerializedName("originalProfileName") val originalProfileName: String?, // string "Effective Profile Switch" @SerializedName("originalProfileName") val originalProfileName: String? = null, // string "Effective Profile Switch"
@SerializedName("originalCustomizedName") val originalCustomizedName: String?, // string "Effective Profile Switch" @SerializedName("originalCustomizedName") val originalCustomizedName: String? = null, // string "Effective Profile Switch"
@SerializedName("originalTimeshift") val originalTimeshift: Long?, // long "Effective Profile Switch" @SerializedName("originalTimeshift") val originalTimeshift: Long? = null, // long "Effective Profile Switch"
@SerializedName("originalPercentage") val originalPercentage: Int?, // int "Effective Profile Switch" @SerializedName("originalPercentage") val originalPercentage: Int? = null, // int "Effective Profile Switch"
@SerializedName("originalDuration") val originalDuration: Long?, // long "Effective Profile Switch" @SerializedName("originalDuration") val originalDuration: Long? = null, // long "Effective Profile Switch"
@SerializedName("originalEnd") val originalEnd: Long?, // long "Effective Profile Switch" @SerializedName("originalEnd") val originalEnd: Long? = null, // long "Effective Profile Switch"
@SerializedName("bolusCalculatorResult") val bolusCalculatorResult: String?, // string "Bolus Wizard" json toString ex "bolusCalculatorResult": "{\"basalIOB\":-0.247,\"bolusIOB\":-1.837,\"carbs\":45.0,\"carbsInsulin\":9.0,\"cob\":0.0,\"cobInsulin\":0.0,\"dateCreated\":1626202788810,\"glucoseDifference\":44.0,\"glucoseInsulin\":0.8979591836734694,\"glucoseTrend\":5.5,\"glucoseValue\":134.0,\"ic\":5.0,\"id\":331,\"interfaceIDs_backing\":{\"nightscoutId\":\"60ede2a4c574da0004a3869d\"},\"isValid\":true,\"isf\":49.0,\"note\":\"\",\"otherCorrection\":0.0,\"percentageCorrection\":90,\"profileName\":\"Tuned 13/01 90%Lyum\",\"superbolusInsulin\":0.0,\"targetBGHigh\":90.0,\"targetBGLow\":90.0,\"timestamp\":1626202783325,\"totalInsulin\":7.34,\"trendInsulin\":0.336734693877551,\"utcOffset\":7200000,\"version\":1,\"wasBasalIOBUsed\":true,\"wasBolusIOBUsed\":true,\"wasCOBUsed\":true,\"wasGlucoseUsed\":true,\"wasSuperbolusUsed\":false,\"wasTempTargetUsed\":false,\"wasTrendUsed\":true,\"wereCarbsUsed\":false}", @SerializedName("bolusCalculatorResult") val bolusCalculatorResult: String? = null, // string "Bolus Wizard" json toString ex "bolusCalculatorResult": "{\"basalIOB\":-0.247,\"bolusIOB\":-1.837,\"carbs\":45.0,\"carbsInsulin\":9.0,\"cob\":0.0,\"cobInsulin\":0.0,\"dateCreated\":1626202788810,\"glucoseDifference\":44.0,\"glucoseInsulin\":0.8979591836734694,\"glucoseTrend\":5.5,\"glucoseValue\":134.0,\"ic\":5.0,\"id\":331,\"interfaceIDs_backing\":{\"nightscoutId\":\"60ede2a4c574da0004a3869d\"},\"isValid\":true,\"isf\":49.0,\"note\":\"\",\"otherCorrection\":0.0,\"percentageCorrection\":90,\"profileName\":\"Tuned 13/01 90%Lyum\",\"superbolusInsulin\":0.0,\"targetBGHigh\":90.0,\"targetBGLow\":90.0,\"timestamp\":1626202783325,\"totalInsulin\":7.34,\"trendInsulin\":0.336734693877551,\"utcOffset\":7200000,\"version\":1,\"wasBasalIOBUsed\":true,\"wasBolusIOBUsed\":true,\"wasCOBUsed\":true,\"wasGlucoseUsed\":true,\"wasSuperbolusUsed\":false,\"wasTempTargetUsed\":false,\"wasTrendUsed\":true,\"wereCarbsUsed\":false}",
@SerializedName("type") val type: String?, // string "Meal Bolus", "Correction Bolus", "Combo Bolus", "Temp Basal" type of bolus "NORMAL", "SMB", "FAKE_EXTENDED" @SerializedName("type") val type: String? = null, // string "Meal Bolus", "Correction Bolus", "Combo Bolus", "Temp Basal" type of bolus "NORMAL", "SMB", "FAKE_EXTENDED"
@SerializedName("isSMB") val isSMB: Boolean, // boolean "Meal Bolus", "Correction Bolus", "Combo Bolus" @SerializedName("isSMB") val isSMB: Boolean? = null, // boolean "Meal Bolus", "Correction Bolus", "Combo Bolus"
@SerializedName("enteredinsulin") val enteredinsulin: Double?, // number... "Combo Bolus" insulin is missing only enteredinsulin field found @SerializedName("enteredinsulin") val enteredinsulin: Double? = null, // number... "Combo Bolus" insulin is missing only enteredinsulin field found
@SerializedName("relative") val relative: Double?, // number... "Combo Bolus", "extendedEmulated" (not in doc see below) @SerializedName("relative") val relative: Double? = null, // number... "Combo Bolus", "extendedEmulated" (not in doc see below)
@SerializedName("isEmulatingTempBasal") val isEmulatingTempBasal: Boolean, // boolean "Combo Bolus", "extendedEmulated" (not in doc see below) @SerializedName("isEmulatingTempBasal") val isEmulatingTempBasal: Boolean? = null, // boolean "Combo Bolus", "extendedEmulated" (not in doc see below)
@SerializedName("isAnnouncement") val isAnnouncement: Boolean, // boolean "Announcement" @SerializedName("isAnnouncement") val isAnnouncement: Boolean? = null, // boolean "Announcement"
@SerializedName("rate") val rate: Double?, // Double "Temp Basal" absolute rate (could be calculated with percent and profile information...) @SerializedName("rate") val rate: Double? = null, // Double "Temp Basal" absolute rate (could be calculated with percent and profile information...)
@SerializedName("extendedEmulated") val extendedEmulated: RemoteTreatment?, // Gson of emulated EB @SerializedName("extendedEmulated") val extendedEmulated: RemoteTreatment? = null, // Gson of emulated EB
@SerializedName("timeshift") val timeshift: Long, // integer "Profile Switch" @SerializedName("timeshift") val timeshift: Long? = null, // integer "Profile Switch"
@SerializedName("percentage") val percentage: Int?, // integer "Profile Switch" @SerializedName("percentage") val percentage: Int? = null // integer "Profile Switch"
) { ) {
fun timestamp(): Long { fun timestamp(): Long {
return date ?: mills ?: timestamp ?: fromISODateString(created_at) return date ?: mills ?: timestamp ?: created_at?. let { fromISODateString(created_at) } ?: 0L
} }
private fun fromISODateString(isoDateString: String): Long = private fun fromISODateString(isoDateString: String): Long =

View file

@ -1,4 +1,4 @@
package info.nightscout.androidaps.utils.extensions package info.nightscout.core.ui.extensions
import android.widget.RadioGroup import android.widget.RadioGroup
import androidx.appcompat.widget.AppCompatRadioButton import androidx.appcompat.widget.AppCompatRadioButton

View file

@ -14,6 +14,7 @@
<string name="pump_base_basal_rate">%1$.2f U/h</string> <string name="pump_base_basal_rate">%1$.2f U/h</string>
<string name="pump_not_initialized_profile_not_set">Pompe non initialisée, profil non défini !</string> <string name="pump_not_initialized_profile_not_set">Pompe non initialisée, profil non défini !</string>
<string name="failed_update_basal_profile">La mise à jour du profil basal a échouée</string> <string name="failed_update_basal_profile">La mise à jour du profil basal a échouée</string>
<string name="bolus_delivered_successfully">Bolus de %1$.2f U délivré avec succès</string>
<string name="no_valid_basal_rate">Aucun débit basal valide lu depuis la pompe</string> <string name="no_valid_basal_rate">Aucun débit basal valide lu depuis la pompe</string>
<string name="limiting_iob">Limiter lIA %1$.1f U en raison de la %2$s</string> <string name="limiting_iob">Limiter lIA %1$.1f U en raison de la %2$s</string>
<string name="loop_disabled">BOUCLE DÉSACTIVÉE PAR RESTRICTIONS</string> <string name="loop_disabled">BOUCLE DÉSACTIVÉE PAR RESTRICTIONS</string>
@ -161,6 +162,8 @@
<string name="dia">DAI</string> <string name="dia">DAI</string>
<string name="ic_short">G/I</string> <string name="ic_short">G/I</string>
<string name="isf_short">SI</string> <string name="isf_short">SI</string>
<string name="canceling_tbr_failed">Echec de l\'annulation du basal temporaire</string>
<string name="canceling_eb_failed">Échec de l\'annulation du Bolus étendu</string>
<string name="virtualpump_uploadstatus_title">Remontée des informations vers NS</string> <string name="virtualpump_uploadstatus_title">Remontée des informations vers NS</string>
<string name="suspendloop_label">Boucle désactivée/suspendue</string> <string name="suspendloop_label">Boucle désactivée/suspendue</string>
<string name="iob_label">Insuline Active (IA)</string> <string name="iob_label">Insuline Active (IA)</string>
@ -246,6 +249,7 @@
<!-- CarbsReq--> <!-- CarbsReq-->
<string name="carbsreq">%1$dg de glucides requis dans %2$d min.</string> <string name="carbsreq">%1$dg de glucides requis dans %2$d min.</string>
<!-- TDDStatsActivity--> <!-- TDDStatsActivity-->
<string name="cumulative_tdd">DTQ cumulée</string>
<string name="expweight">DTQ avec Pondération Exponentielle</string> <string name="expweight">DTQ avec Pondération Exponentielle</string>
<string name="basalrate">Basal</string> <string name="basalrate">Basal</string>
<string name="bolus">Bolus</string> <string name="bolus">Bolus</string>

View file

@ -419,7 +419,7 @@
<string name="autotune_warning">Aviso :</string> <string name="autotune_warning">Aviso :</string>
<string name="autotune_select_profile">Selecione o perfil para ajustar</string> <string name="autotune_select_profile">Selecione o perfil para ajustar</string>
<string name="autotune_ic_warning">O perfil selecionado tem %1$d valores de IC. Autotune vai usar %2$.2f g/U</string> <string name="autotune_ic_warning">O perfil selecionado tem %1$d valores de IC. Autotune vai usar %2$.2f g/U</string>
<string name="autotune_isf_warning">O perfil selecionado tem %1$d valores de ISF. Autotune vai usar %2$.1f g/U</string> <string name="autotune_isf_warning">O perfil selecionado tem %1$d valores de ISF. Autotune usará %2$.1f %3$s/U</string>
<string name="autotune_error">Erro nos dados de entrada, tente executar novamente autotune ou reduza o número de dias</string> <string name="autotune_error">Erro nos dados de entrada, tente executar novamente autotune ou reduza o número de dias</string>
<string name="autotune_warning_during_run">Cálculos do Autotune iniciados, por favor aguarde</string> <string name="autotune_warning_during_run">Cálculos do Autotune iniciados, por favor aguarde</string>
<string name="autotune_warning_after_run">Verifique os resultados cuidadosamente antes de usá-los!</string> <string name="autotune_warning_after_run">Verifique os resultados cuidadosamente antes de usá-los!</string>

View file

@ -162,6 +162,8 @@
<string name="dia">Время действия инсулина DIA</string> <string name="dia">Время действия инсулина DIA</string>
<string name="ic_short">IC углкоэф ГУ/инс</string> <string name="ic_short">IC углкоэф ГУ/инс</string>
<string name="isf_short">ISF (чувствительность к инсулину)</string> <string name="isf_short">ISF (чувствительность к инсулину)</string>
<string name="canceling_tbr_failed">Отмена врем базала не состоялась</string>
<string name="canceling_eb_failed">Сбой отмены пролонгированного болюса</string>
<string name="virtualpump_uploadstatus_title">статус передачи данных в NS</string> <string name="virtualpump_uploadstatus_title">статус передачи данных в NS</string>
<string name="suspendloop_label">Отключенный/приостановленный цикл</string> <string name="suspendloop_label">Отключенный/приостановленный цикл</string>
<string name="iob_label">Активный инсулин (IOB)</string> <string name="iob_label">Активный инсулин (IOB)</string>
@ -426,7 +428,6 @@
<string name="autotune_param">Парам</string> <string name="autotune_param">Парам</string>
<string name="autotune_percent">%</string> <string name="autotune_percent">%</string>
<string name="autotune_missing">Отсутствует</string> <string name="autotune_missing">Отсутствует</string>
<string name="autotune_profile_name">Профиль авто тюн</string>
<string name="autotune_run">Выполнить Autotune</string> <string name="autotune_run">Выполнить Autotune</string>
<string name="autotune_check_input_profile_button">Проверьте профиль ввода</string> <string name="autotune_check_input_profile_button">Проверьте профиль ввода</string>
<string name="autotune_compare_profile">Сравнить профили</string> <string name="autotune_compare_profile">Сравнить профили</string>

View file

@ -483,7 +483,7 @@
<!-- Constraints--> <!-- Constraints-->
<string name="limitingbasalratio">最大基础率被限定为 %1$.2f U/h 由于 %2$s</string> <string name="limitingbasalratio">最大基础率被限定为 %1$.2f U/h 由于 %2$s</string>
<string name="pumplimit">泵限制</string> <string name="pumplimit">泵限制</string>
<string name="limitingpercentrate">由于 %2$s, 将最大百分比限制为 %1$d%</string> <string name="limitingpercentrate">由于 %2$s, 将最大百分比限制为 %1$d%%</string>
<string name="itmustbepositivevalue">它必须是正数</string> <string name="itmustbepositivevalue">它必须是正数</string>
<string name="limitingbolus">由于 %2$s, 将大剂量限制为 %1$.1f U</string> <string name="limitingbolus">由于 %2$s, 将大剂量限制为 %1$.1f U</string>
<!-- Locale --> <!-- Locale -->

View file

@ -1,4 +1,4 @@
package info.nightscout.core.extensions package info.nightscout.core.utils.extensions
import androidx.annotation.StringRes import androidx.annotation.StringRes
import info.nightscout.shared.interfaces.ResourceHelper import info.nightscout.shared.interfaces.ResourceHelper

View file

@ -165,7 +165,7 @@ class AutotuneCore @Inject constructor(
for (i in 0..23) { for (i in 0..23) {
newHourlyBasalProfile[i] = hourlyBasalProfile[i] newHourlyBasalProfile[i] = hourlyBasalProfile[i]
} }
val basalUnTuned = previousAutotune.basalUntuned val basalUnTuned = previousAutotune.basalUnTuned
//autotune-core (lib/autotune/index.js) #210-#266 //autotune-core (lib/autotune/index.js) #210-#266
// look at net deviations for each hour // look at net deviations for each hour
@ -484,7 +484,7 @@ class AutotuneCore @Inject constructor(
previousAutotune.basal = basalProfile previousAutotune.basal = basalProfile
previousAutotune.isf = isf previousAutotune.isf = isf
previousAutotune.ic = Round.roundTo(carbRatio, 0.001) previousAutotune.ic = Round.roundTo(carbRatio, 0.001)
previousAutotune.basalUntuned = basalUnTuned previousAutotune.basalUnTuned = basalUnTuned
previousAutotune.dia = newDia previousAutotune.dia = newDia
previousAutotune.peak = newPeak previousAutotune.peak = newPeak
val localInsulin = LocalInsulin("Ins_$newPeak-$newDia", newPeak, newDia) val localInsulin = LocalInsulin("Ins_$newPeak-$newDia", newPeak, newDia)

View file

@ -89,14 +89,14 @@ class AutotuneFS @Inject constructor(
} }
fun exportPumpProfile(profile: ATProfile) { fun exportPumpProfile(profile: ATProfile) {
createAutotunefile(PUMPPROFILE, profile.profiletoOrefJSON(), true) createAutotunefile(PUMPPROFILE, profile.profileToOrefJSON(), true)
createAutotunefile(PUMPPROFILE, profile.profiletoOrefJSON()) createAutotunefile(PUMPPROFILE, profile.profileToOrefJSON())
} }
fun exportTunedProfile(tunedProfile: ATProfile) { fun exportTunedProfile(tunedProfile: ATProfile) {
createAutotunefile(TUNEDPROFILE + formatDate(tunedProfile.from) + ".json", tunedProfile.profiletoOrefJSON()) createAutotunefile(TUNEDPROFILE + formatDate(tunedProfile.from) + ".json", tunedProfile.profileToOrefJSON())
try { try {
createAutotunefile(rh.gs(info.nightscout.core.ui.R.string.autotune_tunedprofile_name) + ".json", tunedProfile.profiletoOrefJSON(), true) createAutotunefile(rh.gs(info.nightscout.core.ui.R.string.autotune_tunedprofile_name) + ".json", tunedProfile.profileToOrefJSON(), true)
} catch (e: JSONException) { } catch (e: JSONException) {
} }
} }

View file

@ -28,9 +28,9 @@ import info.nightscout.interfaces.Constants
import info.nightscout.interfaces.GlucoseUnit import info.nightscout.interfaces.GlucoseUnit
import info.nightscout.interfaces.logging.UserEntryLogger import info.nightscout.interfaces.logging.UserEntryLogger
import info.nightscout.interfaces.plugin.ActivePlugin import info.nightscout.interfaces.plugin.ActivePlugin
import info.nightscout.interfaces.profile.Instantiator
import info.nightscout.interfaces.profile.Profile import info.nightscout.interfaces.profile.Profile
import info.nightscout.interfaces.profile.ProfileFunction import info.nightscout.interfaces.profile.ProfileFunction
import info.nightscout.interfaces.profile.Instantiator
import info.nightscout.interfaces.profile.ProfileStore import info.nightscout.interfaces.profile.ProfileStore
import info.nightscout.interfaces.ui.UiInteraction import info.nightscout.interfaces.ui.UiInteraction
import info.nightscout.interfaces.utils.MidnightTime import info.nightscout.interfaces.utils.MidnightTime
@ -149,12 +149,12 @@ class AutotuneFragment : DaggerFragment() {
} }
binding.autotuneUpdateProfile.setOnClickListener { binding.autotuneUpdateProfile.setOnClickListener {
val localName = autotunePlugin.pumpProfile.profilename val localName = autotunePlugin.pumpProfile.profileName
OKDialog.showConfirmation(requireContext(), OKDialog.showConfirmation(requireContext(),
rh.gs(info.nightscout.core.ui.R.string.autotune_update_input_profile_button), rh.gs(info.nightscout.core.ui.R.string.autotune_update_input_profile_button),
rh.gs(info.nightscout.core.ui.R.string.autotune_update_local_profile_message, localName), rh.gs(info.nightscout.core.ui.R.string.autotune_update_local_profile_message, localName),
Runnable { Runnable {
autotunePlugin.tunedProfile?.profilename = localName autotunePlugin.tunedProfile?.profileName = localName
autotunePlugin.updateProfile(autotunePlugin.tunedProfile) autotunePlugin.updateProfile(autotunePlugin.tunedProfile)
autotunePlugin.updateButtonVisibility = View.GONE autotunePlugin.updateButtonVisibility = View.GONE
autotunePlugin.saveLastRun() autotunePlugin.saveLastRun()
@ -169,12 +169,12 @@ class AutotuneFragment : DaggerFragment() {
} }
binding.autotuneRevertProfile.setOnClickListener { binding.autotuneRevertProfile.setOnClickListener {
val localName = autotunePlugin.pumpProfile.profilename val localName = autotunePlugin.pumpProfile.profileName
OKDialog.showConfirmation(requireContext(), OKDialog.showConfirmation(requireContext(),
rh.gs(info.nightscout.core.ui.R.string.autotune_revert_input_profile_button), rh.gs(info.nightscout.core.ui.R.string.autotune_revert_input_profile_button),
rh.gs(info.nightscout.core.ui.R.string.autotune_revert_local_profile_message, localName), rh.gs(info.nightscout.core.ui.R.string.autotune_revert_local_profile_message, localName),
Runnable { Runnable {
autotunePlugin.tunedProfile?.profilename = "" autotunePlugin.tunedProfile?.profileName = ""
autotunePlugin.updateProfile(autotunePlugin.pumpProfile) autotunePlugin.updateProfile(autotunePlugin.pumpProfile)
autotunePlugin.updateButtonVisibility = View.VISIBLE autotunePlugin.updateButtonVisibility = View.VISIBLE
autotunePlugin.saveLastRun() autotunePlugin.saveLastRun()
@ -192,11 +192,11 @@ class AutotuneFragment : DaggerFragment() {
val pumpProfile = profileFunction.getProfile()?.let { currentProfile -> val pumpProfile = profileFunction.getProfile()?.let { currentProfile ->
profileStore.getSpecificProfile(profileName)?.let { specificProfile -> profileStore.getSpecificProfile(profileName)?.let { specificProfile ->
ATProfile(ProfileSealed.Pure(specificProfile), LocalInsulin(""), injector).also { ATProfile(ProfileSealed.Pure(specificProfile), LocalInsulin(""), injector).also {
it.profilename = profileName it.profileName = profileName
} }
} }
?: ATProfile(currentProfile, LocalInsulin(""), injector).also { ?: ATProfile(currentProfile, LocalInsulin(""), injector).also {
it.profilename = profileFunction.getProfileName() it.profileName = profileFunction.getProfileName()
} }
} }
pumpProfile?.let { pumpProfile?.let {
@ -205,7 +205,7 @@ class AutotuneFragment : DaggerFragment() {
time = dateUtil.now(), time = dateUtil.now(),
mode = UiInteraction.Mode.CUSTOM_PROFILE, mode = UiInteraction.Mode.CUSTOM_PROFILE,
customProfile = pumpProfile.profile.toPureNsJson(dateUtil).toString(), customProfile = pumpProfile.profile.toPureNsJson(dateUtil).toString(),
customProfileName = pumpProfile.profilename customProfileName = pumpProfile.profileName
) )
} }
} }
@ -219,7 +219,7 @@ class AutotuneFragment : DaggerFragment() {
time = dateUtil.now(), time = dateUtil.now(),
mode = UiInteraction.Mode.PROFILE_COMPARE, mode = UiInteraction.Mode.PROFILE_COMPARE,
customProfile = pumpProfile.profile.toPureNsJson(dateUtil).toString(), customProfile = pumpProfile.profile.toPureNsJson(dateUtil).toString(),
customProfileName = pumpProfile.profilename + "\n" + rh.gs(info.nightscout.core.ui.R.string.autotune_tunedprofile_name), customProfileName = pumpProfile.profileName + "\n" + rh.gs(info.nightscout.core.ui.R.string.autotune_tunedprofile_name),
customProfile2 = tunedProfile?.toPureNsJson(dateUtil).toString() customProfile2 = tunedProfile?.toPureNsJson(dateUtil).toString()
) )
} }
@ -231,17 +231,17 @@ class AutotuneFragment : DaggerFragment() {
tunedProfile?.let { tunedP -> tunedProfile?.let { tunedP ->
tunedP.profileStore(circadian)?.let { tunedP.profileStore(circadian)?.let {
OKDialog.showConfirmation(requireContext(), OKDialog.showConfirmation(requireContext(),
rh.gs(info.nightscout.core.ui.R.string.activate_profile) + ": " + tunedP.profilename + " ?", rh.gs(info.nightscout.core.ui.R.string.activate_profile) + ": " + tunedP.profileName + " ?",
{ {
uel.log( uel.log(
UserEntry.Action.STORE_PROFILE, UserEntry.Action.STORE_PROFILE,
UserEntry.Sources.Autotune, UserEntry.Sources.Autotune,
ValueWithUnit.SimpleString(tunedP.profilename) ValueWithUnit.SimpleString(tunedP.profileName)
) )
val now = dateUtil.now() val now = dateUtil.now()
if (profileFunction.createProfileSwitch( if (profileFunction.createProfileSwitch(
it, it,
profileName = tunedP.profilename, profileName = tunedP.profileName,
durationInMinutes = 0, durationInMinutes = 0,
percentage = 100, percentage = 100,
timeShiftInHours = 0, timeShiftInHours = 0,
@ -252,7 +252,7 @@ class AutotuneFragment : DaggerFragment() {
UserEntry.Action.PROFILE_SWITCH, UserEntry.Action.PROFILE_SWITCH,
UserEntry.Sources.Autotune, UserEntry.Sources.Autotune,
"Autotune AutoSwitch", "Autotune AutoSwitch",
ValueWithUnit.SimpleString(autotunePlugin.tunedProfile!!.profilename) ValueWithUnit.SimpleString(autotunePlugin.tunedProfile!!.profileName)
) )
} }
rxBus.send(EventLocalProfileChanged()) rxBus.send(EventLocalProfileChanged())
@ -472,7 +472,7 @@ class AutotuneFragment : DaggerFragment() {
val time = df.format(h.toLong()) + ":00" val time = df.format(h.toLong()) + ":00"
totalPump += autotunePlugin.pumpProfile.basal[h] totalPump += autotunePlugin.pumpProfile.basal[h]
totalTuned += tuned.basal[h] totalTuned += tuned.basal[h]
layout.addView(toTableRowValue(context, time, autotunePlugin.pumpProfile.basal[h], tuned.basal[h], "%.3f", tuned.basalUntuned[h].toString())) layout.addView(toTableRowValue(context, time, autotunePlugin.pumpProfile.basal[h], tuned.basal[h], "%.3f", tuned.basalUnTuned[h].toString()))
} }
layout.addView(toTableRowValue(context, "", totalPump, totalTuned, "%.3f", " ")) layout.addView(toTableRowValue(context, "", totalPump, totalTuned, "%.3f", " "))
} }

View file

@ -14,9 +14,9 @@ import info.nightscout.interfaces.plugin.ActivePlugin
import info.nightscout.interfaces.plugin.PluginBase import info.nightscout.interfaces.plugin.PluginBase
import info.nightscout.interfaces.plugin.PluginDescription import info.nightscout.interfaces.plugin.PluginDescription
import info.nightscout.interfaces.plugin.PluginType import info.nightscout.interfaces.plugin.PluginType
import info.nightscout.interfaces.profile.Instantiator
import info.nightscout.interfaces.profile.Profile import info.nightscout.interfaces.profile.Profile
import info.nightscout.interfaces.profile.ProfileFunction import info.nightscout.interfaces.profile.ProfileFunction
import info.nightscout.interfaces.profile.Instantiator
import info.nightscout.interfaces.utils.JsonHelper import info.nightscout.interfaces.utils.JsonHelper
import info.nightscout.interfaces.utils.MidnightTime import info.nightscout.interfaces.utils.MidnightTime
import info.nightscout.plugins.aps.R import info.nightscout.plugins.aps.R
@ -131,10 +131,10 @@ class AutotunePlugin @Inject constructor(
val starttime = endTime - daysBack * 24 * 60 * 60 * 1000L val starttime = endTime - daysBack * 24 * 60 * 60 * 1000L
autotuneFS.exportSettings(settings(lastRun, daysBack, starttime, endTime)) autotuneFS.exportSettings(settings(lastRun, daysBack, starttime, endTime))
tunedProfile = ATProfile(profile, localInsulin, injector).also { tunedProfile = ATProfile(profile, localInsulin, injector).also {
it.profilename = rh.gs(info.nightscout.core.ui.R.string.autotune_tunedprofile_name) it.profileName = rh.gs(info.nightscout.core.ui.R.string.autotune_tunedprofile_name)
} }
pumpProfile = ATProfile(profile, localInsulin, injector).also { pumpProfile = ATProfile(profile, localInsulin, injector).also {
it.profilename = selectedProfile it.profileName = selectedProfile
} }
autotuneFS.exportPumpProfile(pumpProfile) autotuneFS.exportPumpProfile(pumpProfile)
@ -195,31 +195,31 @@ class AutotunePlugin @Inject constructor(
if (autoSwitch) { if (autoSwitch) {
val circadian = sp.getBoolean(info.nightscout.core.utils.R.string.key_autotune_circadian_ic_isf, false) val circadian = sp.getBoolean(info.nightscout.core.utils.R.string.key_autotune_circadian_ic_isf, false)
tunedProfile?.let { tunedP -> tunedProfile?.let { tunedP ->
tunedP.profilename = pumpProfile.profilename tunedP.profileName = pumpProfile.profileName
updateProfile(tunedP) updateProfile(tunedP)
uel.log( uel.log(
UserEntry.Action.STORE_PROFILE, UserEntry.Action.STORE_PROFILE,
UserEntry.Sources.Automation, UserEntry.Sources.Automation,
rh.gs(info.nightscout.core.ui.R.string.autotune), rh.gs(info.nightscout.core.ui.R.string.autotune),
ValueWithUnit.SimpleString(tunedP.profilename) ValueWithUnit.SimpleString(tunedP.profileName)
) )
updateButtonVisibility = View.GONE updateButtonVisibility = View.GONE
tunedP.profileStore(circadian)?.let { profilestore -> tunedP.profileStore(circadian)?.let { profilestore ->
if (profileFunction.createProfileSwitch( if (profileFunction.createProfileSwitch(
profilestore, profilestore,
profileName = tunedP.profilename, profileName = tunedP.profileName,
durationInMinutes = 0, durationInMinutes = 0,
percentage = 100, percentage = 100,
timeShiftInHours = 0, timeShiftInHours = 0,
timestamp = dateUtil.now() timestamp = dateUtil.now()
) )
) { ) {
log("Profile Switch succeed ${tunedP.profilename}") log("Profile Switch succeed ${tunedP.profileName}")
uel.log( uel.log(
UserEntry.Action.PROFILE_SWITCH, UserEntry.Action.PROFILE_SWITCH,
UserEntry.Sources.Automation, UserEntry.Sources.Automation,
rh.gs(info.nightscout.core.ui.R.string.autotune), rh.gs(info.nightscout.core.ui.R.string.autotune),
ValueWithUnit.SimpleString(tunedP.profilename) ValueWithUnit.SimpleString(tunedP.profileName)
) )
} }
rxBus.send(EventLocalProfileChanged()) rxBus.send(EventLocalProfileChanged())
@ -262,7 +262,7 @@ class AutotunePlugin @Inject constructor(
totalBasal += pumpProfile.basal[i] totalBasal += pumpProfile.basal[i]
totalTuned += tunedProfile.basal[i] totalTuned += tunedProfile.basal[i]
val percentageChangeValue = tunedProfile.basal[i] / pumpProfile.basal[i] * 100 - 100 val percentageChangeValue = tunedProfile.basal[i] / pumpProfile.basal[i] * 100 - 100
strResult += rh.gs(info.nightscout.core.ui.R.string.autotune_log_basal, i.toDouble(), pumpProfile.basal[i], tunedProfile.basal[i], tunedProfile.basalUntuned[i], percentageChangeValue) strResult += rh.gs(info.nightscout.core.ui.R.string.autotune_log_basal, i.toDouble(), pumpProfile.basal[i], tunedProfile.basal[i], tunedProfile.basalUnTuned[i], percentageChangeValue)
} }
strResult += line strResult += line
strResult += rh.gs(info.nightscout.core.ui.R.string.autotune_log_sum_basal, totalBasal, totalTuned) strResult += rh.gs(info.nightscout.core.ui.R.string.autotune_log_sum_basal, totalBasal, totalTuned)
@ -329,10 +329,10 @@ class AutotunePlugin @Inject constructor(
val profileList: ArrayList<CharSequence> = profileStore.getProfileList() val profileList: ArrayList<CharSequence> = profileStore.getProfileList()
var indexLocalProfile = -1 var indexLocalProfile = -1
for (p in profileList.indices) for (p in profileList.indices)
if (profileList[p] == newProfile.profilename) if (profileList[p] == newProfile.profileName)
indexLocalProfile = p indexLocalProfile = p
if (indexLocalProfile == -1) { if (indexLocalProfile == -1) {
profilePlugin.addProfile(profilePlugin.copyFrom(newProfile.getProfile(circadian), newProfile.profilename)) profilePlugin.addProfile(profilePlugin.copyFrom(newProfile.getProfile(circadian), newProfile.profileName))
return return
} }
profilePlugin.currentProfileIndex = indexLocalProfile profilePlugin.currentProfileIndex = indexLocalProfile
@ -348,17 +348,17 @@ class AutotunePlugin @Inject constructor(
json.put("lastNbDays", lastNbDays) json.put("lastNbDays", lastNbDays)
json.put("lastRun", lastRun) json.put("lastRun", lastRun)
json.put("pumpProfile", pumpProfile.profile.toPureNsJson(dateUtil)) json.put("pumpProfile", pumpProfile.profile.toPureNsJson(dateUtil))
json.put("pumpProfileName", pumpProfile.profilename) json.put("pumpProfileName", pumpProfile.profileName)
json.put("pumpPeak", pumpProfile.peak) json.put("pumpPeak", pumpProfile.peak)
json.put("pumpDia", pumpProfile.dia) json.put("pumpDia", pumpProfile.dia)
tunedProfile?.let { atProfile -> tunedProfile?.let { atProfile ->
json.put("tunedProfile", atProfile.profile.toPureNsJson(dateUtil)) json.put("tunedProfile", atProfile.profile.toPureNsJson(dateUtil))
json.put("tunedCircadianProfile", atProfile.circadianProfile.toPureNsJson(dateUtil)) json.put("tunedCircadianProfile", atProfile.circadianProfile.toPureNsJson(dateUtil))
json.put("tunedProfileName", atProfile.profilename) json.put("tunedProfileName", atProfile.profileName)
json.put("tunedPeak", atProfile.peak) json.put("tunedPeak", atProfile.peak)
json.put("tunedDia", atProfile.dia) json.put("tunedDia", atProfile.dia)
for (i in 0..23) { for (i in 0..23) {
json.put("missingDays_$i", atProfile.basalUntuned[i]) json.put("missingDays_$i", atProfile.basalUnTuned[i])
} }
} }
json.put("result", result) json.put("result", result)
@ -379,7 +379,7 @@ class AutotunePlugin @Inject constructor(
selectedProfile = JsonHelper.safeGetString(json, "pumpProfileName", "") selectedProfile = JsonHelper.safeGetString(json, "pumpProfileName", "")
val profile = JsonHelper.safeGetJSONObject(json, "pumpProfile", null)?.let { pureProfileFromJson(it, dateUtil) } val profile = JsonHelper.safeGetJSONObject(json, "pumpProfile", null)?.let { pureProfileFromJson(it, dateUtil) }
?: return ?: return
pumpProfile = ATProfile(ProfileSealed.Pure(profile), localInsulin, injector).also { it.profilename = selectedProfile } pumpProfile = ATProfile(ProfileSealed.Pure(profile), localInsulin, injector).also { it.profileName = selectedProfile }
val tunedPeak = JsonHelper.safeGetInt(json, "tunedPeak") val tunedPeak = JsonHelper.safeGetInt(json, "tunedPeak")
val tunedDia = JsonHelper.safeGetDouble(json, "tunedDia") val tunedDia = JsonHelper.safeGetDouble(json, "tunedDia")
localInsulin = LocalInsulin("PumpInsulin", tunedPeak, tunedDia) localInsulin = LocalInsulin("PumpInsulin", tunedPeak, tunedDia)
@ -389,10 +389,10 @@ class AutotunePlugin @Inject constructor(
val circadianTuned = JsonHelper.safeGetJSONObject(json, "tunedCircadianProfile", null)?.let { pureProfileFromJson(it, dateUtil) } val circadianTuned = JsonHelper.safeGetJSONObject(json, "tunedCircadianProfile", null)?.let { pureProfileFromJson(it, dateUtil) }
?: return ?: return
tunedProfile = ATProfile(ProfileSealed.Pure(tuned), localInsulin, injector).also { atProfile -> tunedProfile = ATProfile(ProfileSealed.Pure(tuned), localInsulin, injector).also { atProfile ->
atProfile.profilename = tunedProfileName atProfile.profileName = tunedProfileName
atProfile.circadianProfile = ProfileSealed.Pure(circadianTuned) atProfile.circadianProfile = ProfileSealed.Pure(circadianTuned)
for (i in 0..23) { for (i in 0..23) {
atProfile.basalUntuned[i] = JsonHelper.safeGetInt(json, "missingDays_$i") atProfile.basalUnTuned[i] = JsonHelper.safeGetInt(json, "missingDays_$i")
} }
} }
result = JsonHelper.safeGetString(json, "result", "") result = JsonHelper.safeGetString(json, "result", "")

View file

@ -10,13 +10,15 @@ import info.nightscout.interfaces.Config
import info.nightscout.interfaces.GlucoseUnit import info.nightscout.interfaces.GlucoseUnit
import info.nightscout.interfaces.insulin.Insulin import info.nightscout.interfaces.insulin.Insulin
import info.nightscout.interfaces.plugin.ActivePlugin import info.nightscout.interfaces.plugin.ActivePlugin
import info.nightscout.interfaces.profile.Instantiator
import info.nightscout.interfaces.profile.Profile import info.nightscout.interfaces.profile.Profile
import info.nightscout.interfaces.profile.ProfileFunction import info.nightscout.interfaces.profile.ProfileFunction
import info.nightscout.interfaces.profile.Instantiator
import info.nightscout.interfaces.profile.ProfileStore import info.nightscout.interfaces.profile.ProfileStore
import info.nightscout.interfaces.profile.PureProfile import info.nightscout.interfaces.profile.PureProfile
import info.nightscout.interfaces.utils.Round import info.nightscout.interfaces.utils.Round
import info.nightscout.rx.bus.RxBus import info.nightscout.rx.bus.RxBus
import info.nightscout.rx.logging.AAPSLogger
import info.nightscout.rx.logging.LTag
import info.nightscout.shared.SafeParse import info.nightscout.shared.SafeParse
import info.nightscout.shared.interfaces.ResourceHelper import info.nightscout.shared.interfaces.ResourceHelper
import info.nightscout.shared.sharedPreferences.SP import info.nightscout.shared.sharedPreferences.SP
@ -28,6 +30,7 @@ import org.json.JSONObject
import java.text.DecimalFormat import java.text.DecimalFormat
import java.util.TimeZone import java.util.TimeZone
import javax.inject.Inject import javax.inject.Inject
import kotlin.math.min
class ATProfile(profile: Profile, var localInsulin: LocalInsulin, val injector: HasAndroidInjector) { class ATProfile(profile: Profile, var localInsulin: LocalInsulin, val injector: HasAndroidInjector) {
@ -39,30 +42,31 @@ class ATProfile(profile: Profile, var localInsulin: LocalInsulin, val injector:
@Inject lateinit var rxBus: RxBus @Inject lateinit var rxBus: RxBus
@Inject lateinit var rh: ResourceHelper @Inject lateinit var rh: ResourceHelper
@Inject lateinit var instantiator: Instantiator @Inject lateinit var instantiator: Instantiator
@Inject lateinit var aapsLogger: AAPSLogger
var profile: ProfileSealed var profile: ProfileSealed
var circadianProfile: ProfileSealed var circadianProfile: ProfileSealed
lateinit var pumpProfile: ProfileSealed private lateinit var pumpProfile: ProfileSealed
var profilename: String = "" var profileName: String = ""
var basal = DoubleArray(24) var basal = DoubleArray(24)
var basalUntuned = IntArray(24) var basalUnTuned = IntArray(24)
var ic = 0.0 var ic = 0.0
var isf = 0.0 var isf = 0.0
var dia = 0.0 var dia = 0.0
var peak = 0 var peak = 0
var isValid: Boolean = false var isValid: Boolean = false
var from: Long = 0 var from: Long = 0
var pumpProfileAvgISF = 0.0 private var pumpProfileAvgISF = 0.0
var pumpProfileAvgIC = 0.0 private var pumpProfileAvgIC = 0.0
val icSize: Int val icSize: Int
get() = profile.getIcsValues().size get() = profile.getIcsValues().size
val isfSize: Int val isfSize: Int
get() = profile.getIsfsMgdlValues().size get() = profile.getIsfsMgdlValues().size
val avgISF: Double private val avgISF: Double
get() = if (profile.getIsfsMgdlValues().size == 1) profile.getIsfsMgdlValues().get(0).value else Round.roundTo(averageProfileValue(profile.getIsfsMgdlValues()), 0.01) get() = if (profile.getIsfsMgdlValues().size == 1) profile.getIsfsMgdlValues()[0].value else Round.roundTo(averageProfileValue(profile.getIsfsMgdlValues()), 0.01)
val avgIC: Double private val avgIC: Double
get() = if (profile.getIcsValues().size == 1) profile.getIcsValues().get(0).value else Round.roundTo(averageProfileValue(profile.getIcsValues()), 0.01) get() = if (profile.getIcsValues().size == 1) profile.getIcsValues()[0].value else Round.roundTo(averageProfileValue(profile.getIcsValues()), 0.01)
fun getBasal(timestamp: Long): Double = basal[MidnightUtils.secondsFromMidnight(timestamp) / 3600] fun getBasal(timestamp: Long): Double = basal[MidnightUtils.secondsFromMidnight(timestamp) / 3600]
@ -94,12 +98,12 @@ class ATProfile(profile: Profile, var localInsulin: LocalInsulin, val injector:
//Export json string with oref0 format used for autotune //Export json string with oref0 format used for autotune
// Include min_5m_carbimpact, insulin type, single value for carb_ratio and isf // Include min_5m_carbimpact, insulin type, single value for carb_ratio and isf
fun profiletoOrefJSON(): String { fun profileToOrefJSON(): String {
var jsonString = "" var jsonString = ""
val json = JSONObject() val json = JSONObject()
val insulinInterface: Insulin = activePlugin.activeInsulin val insulinInterface: Insulin = activePlugin.activeInsulin
try { try {
json.put("name", profilename) json.put("name", profileName)
json.put("min_5m_carbimpact", sp.getDouble("openapsama_min_5m_carbimpact", 3.0)) json.put("min_5m_carbimpact", sp.getDouble("openapsama_min_5m_carbimpact", 3.0))
json.put("dia", dia) json.put("dia", dia)
if (insulinInterface.id === Insulin.InsulinType.OREF_ULTRA_RAPID_ACTING) json.put( if (insulinInterface.id === Insulin.InsulinType.OREF_ULTRA_RAPID_ACTING) json.put(
@ -110,32 +114,31 @@ class ATProfile(profile: Profile, var localInsulin: LocalInsulin, val injector:
json.put("useCustomPeakTime", true) json.put("useCustomPeakTime", true)
json.put("insulinPeakTime", 45) json.put("insulinPeakTime", 45)
} else if (insulinInterface.id === Insulin.InsulinType.OREF_FREE_PEAK) { } else if (insulinInterface.id === Insulin.InsulinType.OREF_FREE_PEAK) {
val peaktime: Int = sp.getInt(rh.gs(info.nightscout.core.utils.R.string.key_insulin_oref_peak), 75) val peakTime: Int = sp.getInt(rh.gs(info.nightscout.core.utils.R.string.key_insulin_oref_peak), 75)
json.put("curve", if (peaktime > 50) "rapid-acting" else "ultra-rapid") json.put("curve", if (peakTime > 50) "rapid-acting" else "ultra-rapid")
json.put("useCustomPeakTime", true) json.put("useCustomPeakTime", true)
json.put("insulinPeakTime", peaktime) json.put("insulinPeakTime", peakTime)
} }
val basals = JSONArray() val basals = JSONArray()
for (h in 0..23) { for (h in 0..23) {
val secondfrommidnight = h * 60 * 60 val secondFromMidnight = h * 60 * 60
var time: String val time: String = DecimalFormat("00").format(h) + ":00:00"
time = DecimalFormat("00").format(h) + ":00:00"
basals.put( basals.put(
JSONObject() JSONObject()
.put("start", time) .put("start", time)
.put("minutes", h * 60) .put("minutes", h * 60)
.put( .put(
"rate", profile.getBasalTimeFromMidnight(secondfrommidnight) "rate", profile.getBasalTimeFromMidnight(secondFromMidnight)
) )
) )
} }
json.put("basalprofile", basals) json.put("basalprofile", basals)
val isfvalue = Round.roundTo(avgISF, 0.001) val isfValue = Round.roundTo(avgISF, 0.001)
json.put( json.put(
"isfProfile", "isfProfile",
JSONObject().put( JSONObject().put(
"sensitivities", "sensitivities",
JSONArray().put(JSONObject().put("i", 0).put("start", "00:00:00").put("sensitivity", isfvalue).put("offset", 0).put("x", 0).put("endoffset", 1440)) JSONArray().put(JSONObject().put("i", 0).put("start", "00:00:00").put("sensitivity", isfValue).put("offset", 0).put("x", 0).put("endoffset", 1440))
) )
) )
json.put("carb_ratio", avgIC) json.put("carb_ratio", avgIC)
@ -145,6 +148,7 @@ class ATProfile(profile: Profile, var localInsulin: LocalInsulin, val injector:
json.put("timezone", TimeZone.getDefault().id) json.put("timezone", TimeZone.getDefault().id)
jsonString = json.toString(2).replace("\\/", "/") jsonString = json.toString(2).replace("\\/", "/")
} catch (e: JSONException) { } catch (e: JSONException) {
aapsLogger.error(LTag.CORE, e.stackTraceToString())
} }
return jsonString return jsonString
@ -163,6 +167,7 @@ class ATProfile(profile: Profile, var localInsulin: LocalInsulin, val injector:
} }
json.put("basal", jsonArray(basal)) json.put("basal", jsonArray(basal))
} catch (e: JSONException) { } catch (e: JSONException) {
aapsLogger.error(LTag.CORE, e.stackTraceToString())
} }
return pureProfileFromJson(json, dateUtil, profile.units.asText) return pureProfileFromJson(json, dateUtil, profile.units.asText)
} }
@ -172,36 +177,37 @@ class ATProfile(profile: Profile, var localInsulin: LocalInsulin, val injector:
val json = JSONObject() val json = JSONObject()
val store = JSONObject() val store = JSONObject()
val tunedProfile = if (circadian) circadianProfile else profile val tunedProfile = if (circadian) circadianProfile else profile
if (profilename.isEmpty()) if (profileName.isEmpty())
profilename = rh.gs(info.nightscout.core.ui.R.string.autotune_tunedprofile_name) profileName = rh.gs(info.nightscout.core.ui.R.string.autotune_tunedprofile_name)
try { try {
store.put(profilename, tunedProfile.toPureNsJson(dateUtil)) store.put(profileName, tunedProfile.toPureNsJson(dateUtil))
json.put("defaultProfile", profilename) json.put("defaultProfile", profileName)
json.put("store", store) json.put("store", store)
json.put("startDate", dateUtil.toISOAsUTC(dateUtil.now())) json.put("startDate", dateUtil.toISOAsUTC(dateUtil.now()))
profileStore = instantiator.provideProfileStore(json) profileStore = instantiator.provideProfileStore(json)
} catch (e: JSONException) { } catch (e: JSONException) {
aapsLogger.error(LTag.CORE, e.stackTraceToString())
} }
return profileStore return profileStore
} }
fun jsonArray(values: DoubleArray): JSONArray { private fun jsonArray(values: DoubleArray): JSONArray {
val json = JSONArray() val json = JSONArray()
for (h in 0..23) { for (h in 0..23) {
val secondfrommidnight = h * 60 * 60 val secondFromMidnight = h * 60 * 60
val df = DecimalFormat("00") val df = DecimalFormat("00")
val time = df.format(h.toLong()) + ":00" val time = df.format(h.toLong()) + ":00"
json.put( json.put(
JSONObject() JSONObject()
.put("time", time) .put("time", time)
.put("timeAsSeconds", secondfrommidnight) .put("timeAsSeconds", secondFromMidnight)
.put("value", values[h]) .put("value", values[h])
) )
} }
return json return json
} }
fun jsonArray(value: Double) = private fun jsonArray(value: Double): JSONArray =
JSONArray().put( JSONArray().put(
JSONObject() JSONObject()
.put("time", "00:00") .put("time", "00:00")
@ -209,7 +215,7 @@ class ATProfile(profile: Profile, var localInsulin: LocalInsulin, val injector:
.put("value", value) .put("value", value)
) )
fun jsonArray(values: List<Block>, multiplier: Double = 1.0): JSONArray { private fun jsonArray(values: List<Block>, multiplier: Double = 1.0): JSONArray {
val json = JSONArray() val json = JSONArray()
var elapsedHours = 0L var elapsedHours = 0L
values.forEach { values.forEach {
@ -249,7 +255,7 @@ class ATProfile(profile: Profile, var localInsulin: LocalInsulin, val injector:
var minBasal = 1.0 var minBasal = 1.0
for (h in 0..23) { for (h in 0..23) {
basal[h] = Round.roundTo(profile.basalBlocks.blockValueBySeconds(T.hours(h.toLong()).secs().toInt(), 1.0, 0), 0.001) basal[h] = Round.roundTo(profile.basalBlocks.blockValueBySeconds(T.hours(h.toLong()).secs().toInt(), 1.0, 0), 0.001)
minBasal = Math.min(minBasal, basal[h]) minBasal = min(minBasal, basal[h])
} }
ic = avgIC ic = avgIC
isf = avgISF isf = avgISF

View file

@ -127,5 +127,6 @@
<string name="saturday_short">S</string> <string name="saturday_short">S</string>
<string name="sunday_short">D</string> <string name="sunday_short">D</string>
<!-- Reminders--> <!-- Reminders-->
<string name="time_to_eat">Il est temps de manger !\nExécutez l\'assistant Bolus et refaites le calcul.</string>
<string name="time_to_bolus">Il est temps de faire le bolus !\nExécutez l\'Assistant et faites de nouveau le calcul.</string> <string name="time_to_bolus">Il est temps de faire le bolus !\nExécutez l\'Assistant et faites de nouveau le calcul.</string>
</resources> </resources>

View file

@ -127,5 +127,6 @@
<string name="saturday_short">Сб</string> <string name="saturday_short">Сб</string>
<string name="sunday_short">Вс</string> <string name="sunday_short">Вс</string>
<!-- Reminders--> <!-- Reminders-->
<string name="time_to_eat">Пора есть!\n Запустите помощник болюса снова для подсчета.</string>
<string name="time_to_bolus">Пора дать болюс!\nЗапустите помощник болюса и повторите расчет.</string> <string name="time_to_bolus">Пора дать болюс!\nЗапустите помощник болюса и повторите расчет.</string>
</resources> </resources>

View file

@ -1,12 +1,12 @@
package info.nightscout.plugins.constraints.safety package info.nightscout.plugins.constraints.safety
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.core.extensions.putDouble import info.nightscout.core.utils.extensions.putDouble
import info.nightscout.core.extensions.putInt import info.nightscout.core.utils.extensions.putInt
import info.nightscout.core.extensions.putString import info.nightscout.core.utils.extensions.putString
import info.nightscout.core.extensions.storeDouble import info.nightscout.core.utils.extensions.storeDouble
import info.nightscout.core.extensions.storeInt import info.nightscout.core.utils.extensions.storeInt
import info.nightscout.core.extensions.storeString import info.nightscout.core.utils.extensions.storeString
import info.nightscout.interfaces.Config import info.nightscout.interfaces.Config
import info.nightscout.interfaces.ApsMode import info.nightscout.interfaces.ApsMode
import info.nightscout.interfaces.constraints.Constraint import info.nightscout.interfaces.constraints.Constraint

View file

@ -1,145 +1,68 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="dia_whatmeansdia">¿Qué es cierto acerca de DIA?</string> <string name="dia_whatmeansdia">¿Qué es cierto acerca de DAI?</string>
<string name="dia_label_exam">Duración de la acción de insulina (DIA)</string> <string name="dia_label_exam">Duración de la acción de insulina (DAI)</string>
<string name="dia_profile">Debes establecer el valor de DIA en tu perfil.</string> <string name="dia_profile">Debes establecer el valor de DAI en tu perfil.</string>
<string name="dia_minimumis5h">El valor mínimo permitido es 5 horas.</string> <string name="dia_minimumis5h">El valor mínimo permitido es de 5 horas.</string>
<string name="dia_hint1">https://androidaps.readthedocs.io/en/latest/EN/Configuration/Config-Builder.html?#insulin</string> <string name="dia_meaningisequaltodiapump">Si estás satisfecho con el valor de DAI que utilizas en tu bomba antes de utilizar AAPS y te funcionó bien, no hay necesidad de cambiarlo cuando empieces a usar el bucle cerrado.</string>
<string name="dia_meaningisequaltodiapump">Si estás satisfecho con el valor de DIA que utilizaste en tu bomba antes de utilizar AAPS y te funcionó bien, no hay necesidad de cambarlo cuando empieces a cerrar el lazo.</string> <string name="dia_valuemustbedetermined">Deberás determinar por ti mismo el valor apropiado para DAI.</string>
<string name="dia_valuemustbedetermined">Deberías determinar por ti mismo el valor apropiado para DIA.</string> <string name="pumpdisconnect_missinginsulin">Evita que AAPS considere la insulina que no se suministró cuando la bomba estaba físicamente desconectada</string>
<string name="hypott_label">Objetivo temporal ante Hipoglucemia</string> <string name="pumpdisconnect_openloop">Se activará el modo de bucle abierto en AAPS.</string>
<string name="hypott_whenhypott">¿Cuál es la razón principal para establecer un objetivo temporal por hipoglucemia?</string>
<string name="hypott_wrongbasal">Para corregir hipoglucemias causadas por ajustes incorrectos de la tasa basal.</string>
<string name="hypott_preventoversmb">Para evitar que AAPS corrija de forma excesiva ante un aumento rápido de la glucosa por tomar carbohidratos rápidos para recuperarse de una hipoglucemia.</string>
<string name="hypott_exercise">Para corregir una hipoglucemia que sucedió como resultando del ejercicio.</string>
<string name="hypott_0basal">Para evitar que la glucosa sanguínea continue bajando si ya hay una tasa basal temporal igual a 0% en funcionamiento.</string>
<string name="hypott_hint1">https://androidaps.readthedocs.io/en/latest/EN/Usage/temptarget.html</string>
<string name="offlineprofile_whatprofile">¿Qué perfil puede ser usado y configurado estando desconectado?</string>
<string name="offlineprofile_label">Tema: Perfil desconectado</string>
<string name="offlineprofile_nsprofile">El perfil que proviene de Nightscout (NS) puede ser utilizado, pero no configurado.</string>
<string name="offlineprofile_hint1">https://androidaps.readthedocs.io/en/latest/EN/Configuration/Config-Builder.html#profile</string>
<string name="pumpdisconnect_label">Razones para aplicar \"Desconectar bomba\" en AAPS</string>
<string name="pumpdisconnect_whattodo">¿Qué se debe hacer al desconectar la bomba?</string>
<string name="pumpdisconnect_unnecessary">Esto es innecesario, ya que no se entregará insulina si la bomba está físicamente desconectada.</string>
<string name="pumpdisconnect_missinginsulin">Evita que AAPS tenga en cuenta la insulina que no se administró cuando la bomba estaba físicamente desconectada</string>
<string name="pumpdisconnect_notstop">Si la bomba permanece conectada, no se detendrá el suministro de insulina.</string>
<string name="pumpdisconnect_openloop">Pasará AAPS a modo de lazo abierto</string>
<string name="pumpdisconnect_hint1">https://androidaps.readthedocs.io/en/latest/EN/Getting-Started/FAQ.html#other-settings</string> <string name="pumpdisconnect_hint1">https://androidaps.readthedocs.io/en/latest/EN/Getting-Started/FAQ.html#other-settings</string>
<string name="objectives_label">Ajustes de AAPS</string> <string name="objectives_notesettings">No necesita exportar sus configuraciones siempre que haga las tenga anotadas.</string>
<string name="objectives2_label">Ajustes de AAPS</string> <string name="objectives_afterobjective">Exportar tu configuración después de completar un objetivo.</string>
<string name="objectives_howtosave">¿Cuáles son las mejores prácticas para hacer copias de seguridad de sus configuraciones?</string> <string name="objectives_afterchange">Exportar las configuraciones después de cambiar cualquiera de sus ajustes.</string>
<string name="objectives_notesettings">No necesita exportar sus configuraciones siempre que haga una nota de ellos.</string> <string name="objectives_afterinitialsetup">Exportar las configuraciones una vez finalizada la configuración inicial y haber establecido sus preferencias.</string>
<string name="objectives_afterobjective">Exporta tu configuración después de completar un objetivo.</string> <string name="objectives2_cloud">Copie el archivo de preferencias a una ubicación segura fuera de su teléfono (p.e. mediante el uso del almacenamiento en la nube, conectando su teléfono con un cable a una computadora, correo electrónico, etc.)</string>
<string name="objectives_afterchange">Exportar la configuración después de cambiar cualquiera de sus ajustes.</string> <string name="objectives2_easyrestore">Si su teléfono es dañado o perdido, hay formas fáciles de recuperar remotamente su configuración sin hacer una copia de seguridad.</string>
<string name="objectives_afterinitialsetup">Exportar la configuración una vez finalizada la configuración inicial y haber establecido sus preferencias.</string> <string name="noisycgm_label">Lecturas CGM con mucha variabilidad</string>
<string name="objectives2_maintenance">Exportar la configuración localmente usando el menú de mantenimiento.</string> <string name="noisycgm_whattodo">¿Qué se debe hacer si los datos de CGM tienen mucha variabilidad?</string>
<string name="objectives2_internalstorage">El archivo de configuración se encuentra en la carpeta Almacenamiento/AAPS/preferencias en el teléfono.</string> <string name="noisycgm_pause">Deshabilitar el bucle cerrado para evitar posibles sobredosis o subdosis.</string>
<string name="objectives2_cloud">Copie el archivo de preferencias a una ubicación segura fuera de su teléfono (p.e. mediante el uso del alamacenamiento en la nube, conectándose con un cable a una computadora, correo electrónico, etc.)</string> <string name="noisycgm_replacesensor">Sustituya el sensor con valores muy variables o inexactos.</string>
<string name="objectives2_easyrestore">Si su teléfono está dañado o perdido, hay formas fáciles de recuperar remotamente su configuración sin hacer una copia de seguridad.</string> <string name="exerciseprofile_whattodo">¿Cómo puede usar los perfiles para mejorar el sistema durante el ejercicio aeróbico?</string>
<string name="objectives_hint1">https://androidaps.readthedocs.io/en/latest/EN/Usage/ExportImportSettings.html</string> <string name="exerciseprofile_switchprofilebelow100">Cambie el perfil por un valor menor a 100%.</string>
<string name="objectives_hint2">https://androidaps.readthedocs.io/en/latest/EN/Getting-Started/FAQ.html#what-emergency-equipment-is-recommended-to-take-with-me</string> <string name="exerciseprofile_switchprofileabove100">Cambie el perfil por un valor mayor a 100%.</string>
<string name="noisycgm_label">Lecturas CGM ruidosas</string> <string name="exerciseprofile_suspendloop">Suspender el bucle.</string>
<string name="noisycgm_whattodo">¿Qué se debe hacer si los datos de CGM tienen ruido?</string> <string name="exercise_whattodo">¿Cómo se puede usar el objetivo temporal de glucosa para ayudar al sistema durante los ejercicios aeróbicos?</string>
<string name="noisycgm_nothing">No hacer nada: AAPS se ocupará de ello.</string> <string name="exercise_settt">Establezca el objetivo de tipo actividad antes de comenzar el ejercicio, considerando un tiempo razonable antes de la actividad.</string>
<string name="noisycgm_pause">Deshabilita el lazo cerrado para evitar posibles sobredosis o subdosis.</string> <string name="exercise_setfinished">Establezca un objetivo de tipo actividad después de finalizar el ejercicio.</string>
<string name="noisycgm_replacesensor">Sustituya los sensores con valores ruidosos o inexactos.</string> <string name="exercise_setunchanged">Deja tu objetivo de glucosa sin cambios.</string>
<string name="noisycgm_checksmoothing">Comprueba que tu aplicación del CGM proporciona datos suavizados.</string> <string name="exercise_15g">Espere hasta que los valores de glucosa se encuentren por debajo del valor definido en el objetivo de tipo hipoglicemia. Luego consuma 15 g de carbohidratos de rápida absorción.</string>
<string name="noisycgm_hint1">https://androidaps.readthedocs.io/en/latest/EN/Usage/Smoothing-Blood-Glucose-Data-in-xDrip.html#smoothing-blood-glucose-data</string> <string name="suspendloop_doigetinsulin">¿Puedo recibir insulina cuando el bucle está desactivado/suspendido?</string>
<string name="exerciseprofile_label">Ejercicio y perfiles</string> <string name="suspendloop_yes">Sí, la insulina basal sigue siendo suministrada.</string>
<string name="exerciseprofile_whattodo">¿Cómo puede usar perfiles para ayudar mejor al sistema a hacer frente al ejercicio aeróbico?</string> <string name="suspendloop_no">No, la administración de la insulina se detiene.</string>
<string name="exerciseprofile_switchprofilebelow100">Haga un cambio de perfil a menos de 100%.</string> <string name="basaltest_label">Pruebas para basales, I:C y FSI</string>
<string name="exerciseprofile_switchprofileabove100">Haga un cambio de perfil a más de 100%.</string> <string name="basaltest_beforeloop">Antes de empezar cualquier bucle.</string>
<string name="exerciseprofile_leaveat100">Dejar el perfil configurado al 100%.</string> <string name="basaltest_havingregularhighlow">Cuando los valores de glucosa son muy altos o bajos de manera frecuente.</string>
<string name="exerciseprofile_suspendloop">Suspender el lazo</string> <string name="basaltest_fixed">Una vez establecidos y validados, estos valores no deberían cambiar a lo largo del tiempo.</string>
<string name="exerciseprofile_hint1">https://androidaps.readthedocs.io/en/latest/EN/Usage/temptarget.html#activity-temp-target</string> <string name="prerequisites_determinedcorrectprofile">Información de perfil previamente validada (Basal, IC, FSI, DAI).</string>
<string name="exercise_label">Ejercicios y objetivos temporales</string> <string name="prerequisites_computer">Una computadora con Android Studio instalado y configurado.</string>
<string name="exercise_whattodo">¿Cómo se puede usar objetivos temporales para ayudar mejor al sistema a hacer frente al ejercicio aeróbico?</string> <string name="prerequisites_pump">Una bomba de insulina compatible, si planeas usar el sistema en modo bucle cerrado.</string>
<string name="exercise_settt">Establece un objetivo de glucosa en la sangre actividad que comienza un tiempo adecuado antes de comenzar el ejercicio.</string> <string name="prerequisites2_internet">AAPS requiere una conexión a Internet para funcionar con el modo bucle cerrado.</string>
<string name="exercise_setfinished">Establece un objetivo de glucosa en la sangre actividad después de finalizar el ejercicio.</string> <string name="whatistrue">Seleccione todas las respuestas correctas.</string>
<string name="exercise_setunchanged">Deja tu objetivo de glucosa sanguíneo sin cambios.</string> <string name="update_git">Es necesario tener Git instalado y configurado en la computadora.</string>
<string name="exercise_15g">Espere hasta que la glucosa en sangre caiga por debajo de su objetivo de hipo temp y luego coma 15 g de hidratos de carbono de actividad rápida.</string> <string name="update_asap">Cuando esté disponible una versión más reciente de AAPS, las funciones de las versiones anteriores pueden ser limitadas de forma remota después de una fecha especifica.</string>
<string name="exercise_hint1">https://androidaps.readthedocs.io/en/latest/EN/Usage/temptarget.html#activity-temp-target</string> <string name="update_keys">Se debe guardar en un lugar seguro de su computadora la \"keystore\" (archivo.jks) que se ha empleado previamente y usar la misma \"keystore\" para futuras actualizaciones.</string>
<string name="suspendloop_doigetinsulin">¿Recibo insulina cuando el lazo está desactivado/suspendido?</string> <string name="update_neverupdate">Nunca se debe actualizar AAPS si el sistema está funcionando bien.</string>
<string name="suspendloop_yes">Sí, la insulina basal sigue siendo entregada.</string> <string name="troubleshooting_gitter">Puedes solicitar asesoramiento y registrar problemas técnicos o incidencias en el grupo de Discord de AAPS.</string>
<string name="suspendloop_no">No, la administración de la insulina está detenida.</string> <string name="troubleshooting_yourendo">Debes preguntar a tu endocrinólogo o educador en diabetes.</string>
<string name="basaltest_label">Pruebas basales, ISF, e I:C</string> <string name="sensitivity_which">Seleccione todas las respuestas correctas.</string>
<string name="basaltest_when">¿Cuándo se deben validar estos valores?</string> <string name="sensitivity_edit">Los plugins de sensibilidad sugieren al usuario cambios en la cantidad de insulina basal a suministrar, en el factor de sensibilidad a la insulina (ISF) y en el ratio I:C y pueden ser incorporados al perfil definido.</string>
<string name="basaltest_beforeloop">Antes de empezar el lazo</string> <string name="sensitivity_cannula">Registrar el cámbio de cánula reinicia Autosens, volviendo de nuevo al 100%.</string>
<string name="basaltest_havingregularhighlow">Cuando se tienen valores de glucosa altos o bajos frecuentemente.</string> <string name="wrongcarbs_label">Error de ingreso de Carbohidratos</string>
<string name="basaltest_weekly">Al menos una vez a la semana.</string> <string name="wrongcarbs_whattodo">¿Qué deberías hacer si has cometido un error al ingresar carbohidratos?</string>
<string name="basaltest_fixed">Una vez fijados y validados, estos valores no debrían cambiar a lo largo del tiempo.</string> <string name="wrongcarbs_treatmentstab">Elimina la entrada incorrecta en pestaña de tratamientos e introduce el valor correcto.</string>
<string name="basaltest_hint1">https://androidaps.readthedocs.io/en/latest/EN/Getting-Started/FAQ.html#androidaps-settings</string> <string name="wrongcarbs_addinsulin">Darse un bolo desde el menú de llenado de la infusión.</string>
<string name="prerequisites_label">Requisitos previos</string> <string name="wrongcarbs_donothing">No hacer nada - AAPS realizará los ajustes necesarios.</string>
<string name="prerequisites_what">¿Qué es esencial para configurar y utilizar AAPS?</string> <string name="wrongcarbs_bolus">Darse un bolo usando el botón de Insulina (bolus) en página general.</string>
<string name="prerequisites_determinedcorrectprofile">Información de perfil validada (Basal, IC, ISF, DIA).</string> <string name="wronginsulin_careportal">Elimina los valores de insulina del portal de Nightscout o Careportal para eliminarlos del historial de la bomba.</string>
<string name="prerequisites_computer">Un ordenador con Android Studio instalado y configurado.</string> <string name="wronginsulin_compare">Comparar valores en AAPS con el historial de la bomba (si la bomba los registra).</string>
<string name="prerequisites_phone">Un teléfono compatible.</string> <string name="wronginsulin_prime">Bolo una proporción de la insulina calculada “perdida” por jeringa/pluma o usando menú de Insulina.</string>
<string name="prerequisites_pump">Una bomba de insulina compatible, si planeas usar el sistema en modo \"lazo cerrado\".</string> <string name="wronginsulin_donothing">No hacer nada y permite que AAPS corrija cualquier resultado de nivel alto de glucosa.</string>
<string name="prerequisites_nightscout">Nightscout, para tener un registro de los datos y revisar los parámetros de configuración.</string> <string name="cob_question">¿Cómo afecta el cambio del valor FSI al cálculo de COB?</string>
<string name="prerequisites_tidepoolaccount">Una cuenta de Tidepool.</string> <string name="cob_longer">Incrementar el FSI hará que los carbohidratos se absorban más lentamente</string>
<string name="prerequisites_googleaccount">Una cuenta de Google.</string> <string name="cob_shorter">Incrementar el FSI hará que los carbohidratos se absorban más rápidamente</string>
<string name="prerequisites_githubaccount">Una cuenta de Github.</string> <string name="cob_no_effect">Incrementar el FSI no afectará la absorción calculada de carbohidratos</string>
<string name="prerequisites_beanandroiddeveloper">Experiencia programando o editando código.</string>
<string name="prerequisites_own670g">Una bomba MiniMed 670G.</string>
<string name="prerequisites_hint1">https://androidaps.readthedocs.io/en/latest/EN/Module/module.html</string>
<string name="prerequisites_smartwatch">Un Smartwatch.</string>
<string name="prerequisites_supportedcgm">Un MCG soportado.</string>
<string name="prerequisites2_label">Requisitos previos</string>
<string name="prerequisites2_what">¿Qué es esencial para configurar y utilizar AAPS?</string>
<string name="prerequisites2_profile">Parámetros validados para poder configurar un perfil (ISF, I:C ratio, perfil basal, DIA etc.).</string>
<string name="prerequisites2_device">Un dispositivo Android compatible (e.j. un móvil, un smartwatch Android compatible o una tablet).</string>
<string name="prerequisites2_internet">AAPS requiere una conexión a Internet para funcionar en modo lazo cerrado.</string>
<string name="prerequisites2_supportedcgm">Un medidor continuo de glucosa (MCG) y una aplicación capaz de recibir los valores proporcionados por el medidor en el móvil o tablet.</string>
<string name="prerequisites2_hint1">https://androidaps.readthedocs.io/en/latest/EN/Module/module.html</string>
<string name="update_label">Actualizando AAPS</string>
<string name="whatistrue">Compruebe todas las respuestas correctas.</string>
<string name="update_git">Es necesario tener Git instalado y configurado en el ordenador.</string>
<string name="update_asap">Cuando esté disponible una versión más reciente de AAPS, las funciones de las versiones anteriores pueden ser limitadas de forma remota después de una fecha determinada.</string>
<string name="update_keys">Se debe guardar en un lugar seguro la \"keystore\" que se ha empleado y usar la misma\"key\" para futuras actulizaciones.</string>
<string name="update_neverupdate">Nunca actualice si el sistema está funcionando bien.</string>
<string name="update_askfriend">Si tienes problemas construyendo la aplicación (. apk), puedes instalar el mismo archivo. apk compilado por un amigo.</string>
<string name="update_hint1">https://androidaps.readthedocs.io/en/latest/EN/Installing-AndroidAPS/Update-to-new-version.html#update-to-a-new-version-or-branch</string>
<string name="troubleshooting_label">Solución de problemas</string>
<string name="troubleshooting_wheretoask">¿Dónde puedes buscar ayuda con AAPS?</string>
<string name="troubleshooting_fb">Puede solicitar asesoramiento en el grupo de usuarios de AAPS en Facebook.</string>
<string name="troubleshooting_wiki">Deberías leer (y volver a leer) la documentación de AAPS.</string>
<string name="troubleshooting_gitter">Puedes solicitar asesoramiento y registrar problemas técnicos o indidencias en el grupo de Discord de AAPS.</string>
<string name="troubleshooting_yourendo">Debes preguntar a tu endocrino o educador diabetológico.</string>
<string name="troubleshooting_hint1">https://androidaps.readthedocs.io/en/latest/EN/Installing-AndroidAPS/Update-to-new-version.html#troubleshooting</string>
<string name="troubleshooting_hint2">https://www.facebook.com/groups/AndroidAPSUsers/</string>
<string name="troubleshooting_hint3">https://discord.gg/4fQUWHZ4Mw</string>
<string name="insulin_plugins">Plugins de insulina</string>
<string name="insulin_ultrarapid">¿Qué insulina debes usar con el plugin Ultra-Rapid Oref?</string>
<string name="insulin_fiasp">Fiasp®</string>
<string name="insulin_novorapid">NovoRapid®/Novolog®</string>
<string name="insulin_humalog">Humalog®</string>
<string name="insulin_actrapid">Actrapid®/Humalin R®/\"insulina humana estándar\".</string>
<string name="insulin_hint1">https://androidaps.readthedocs.io/en/latest/EN/Configuration/Config-Builder.html#insulin</string>
<string name="sensitivity_label">Plugins de sensibilidad</string>
<string name="sensitivity_which">Compruebe todas las respuestas correctas.</string>
<string name="sensitivity_adjust">Los plugins de sensibilidad permiten a AAPS ajustarse para cambios temporales o de corta duración en la sensibilidad a la insulina (por ejemplo, cambios hormonales o problemas con la absorción en el sitio de infusión).</string>
<string name="sensitivity_edit">Los plugins de sensibilidad sugieren al usuario cambios en la cantidad de insulina basal a suministrar, en el factor de sensibiliad a la insulina (ISF) y en el ratio I:C y pueden ser incorporados al perfil definido.</string>
<string name="sensitivity_cannula">Registrar el cámbio de cánula reseteará Autosens, dejándolo de nuevo al 100%.</string>
<string name="sensitivity_time">Algunas de las opciones del plugin tienen rangos de tiempo configurables que pueden ser definidos por el usuario.</string>
<string name="sensitivity_hint1">https://androidaps.readthedocs.io/en/latest/EN/Configuration/Sensitivity-detection-and-COB.html</string>
<string name="sensitivity_hint2">https://androidaps.readthedocs.io/es/latest/Usage/Open-APS-features.html?highlight=Autosens#autosens</string>
<string name="wrongcarbs_label">Error de entrada de Carbohidratos</string>
<string name="wrongcarbs_whattodo">¿Qué deberías hacer si has hecho una entrada incorrecta de carbohidratos?</string>
<string name="wrongcarbs_treatmentstab">Elimina la entrada incorrecta en los tratamientos e introduce el valor correcto de carbohidratos.</string>
<string name="wrongcarbs_addinsulin">Bolo con insulina usando el menú de llenado de la infusión.</string>
<string name="wrongcarbs_donothing">No hacer nada - AAPS realizará los ajustes apropiados.</string>
<string name="wrongcarbs_bolus">Bolo con insulina usando el botón de Insulina (bolus) en página general.</string>
<string name="wronginsulin_label">Errores de entrega/entrada de insulina</string>
<string name="wronginsulin_whattodo">¿Qué debes hacer si recibiste menos insulina de la que sugiere la historia de la bomba p.ej. debido a una oclusión, una cánula fallida o olvidarse de reponer la bomba después de una ducha?</string>
<string name="wronginsulin_careportal">Elimina los datos de insulina del portal de Nightscout Careportal para eliminarlos del historial de la bomba.</string>
<string name="wronginsulin_compare">Comparar valores en AAPS con el historial de la bomba (si la bomba lo soporta).</string>
<string name="wronginsulin_prime">Bolo una proporción de la insulina calculada “perdida” por jeringa/pluma o usando menú de llenado.</string>
<string name="wronginsulin_donothing">No hacer nada y permite que AAPS corrija cualquier resultado de nivel alto de glucosa en sangre.</string>
<string name="cob_label">Carbohidratos activos (COB)</string>
<string name="cob_question">¿Cómo afecta el cambio del valor ISF al cálculo de COB?</string>
<string name="cob_longer">Incrementar el ISF hará que los carbohidratos se absorban más lentamente</string>
<string name="cob_shorter">Incrementar el ISF hará que los carbohidratos se absorban más rápidamente</string>
<string name="cob_no_effect">Incrementar el ISF no afectará la absorción calculada de carbohidratos</string>
<string name="cob2_question">¿Cómo afecta cambiar los valores de IC a los cálculos de COB?</string> <string name="cob2_question">¿Cómo afecta cambiar los valores de IC a los cálculos de COB?</string>
<string name="cob2_longer">Incrementar el IC hará que los carbohidratos se absorban más lentamente</string> <string name="cob2_longer">Incrementar el IC hará que los carbohidratos se absorban más lentamente</string>
<string name="cob2_shorter">Incrementar el IC hará que los carbohidratos se absorban más rápidamente</string> <string name="cob2_shorter">Incrementar el IC hará que los carbohidratos se absorban más rápidamente</string>

View file

@ -2,12 +2,27 @@
<resources> <resources>
<!-- PhoneChecker --> <!-- PhoneChecker -->
<!-- DST Helper --> <!-- DST Helper -->
<string name="dst_in_24h_warning">Changement d\'heure dans moins de 24 heures</string>
<string name="dst_loop_disabled_warning">Changement d\'heure dans moins de 3 heures - Boucle fermée désactivée</string>
<!-- Storage constraint --> <!-- Storage constraint -->
<string name="disk_full">Boucle désactivée ! Libérez au moins %1$d Mo du stockage interne !</string>
<!-- Version Checker --> <!-- Version Checker -->
<string name="old_version">ancienne version</string>
<string name="very_old_version">très ancienne version</string>
<string name="application_expired">Application expirée</string>
<string name="new_version_warning">Nouvelle version disponible depuis %1$d jours ! Retour à Arrêt Glycémie Basse (AGB) dans %2$d jours, la boucle sera désactivée dans %3$d jours</string>
<string name="running_invalid_version">Nous avons détecté que vous utilisez une version invalide. Boucle désactivée !</string>
<string name="versionavailable">Version %1$s disponible</string>
<string name="version_expire">La version %1$s expire le %2$s</string>
<!-- Signature verifier --> <!-- Signature verifier -->
<!-- BG Quality --> <!-- BG Quality -->
<string name="recalculated_data_used">Données recalculées utilisées</string>
<string name="bg_too_close">Gly trop proche :\n%1$s\n%2$s</string>
<string name="a11y_bg_quality_recalculated">recalculé</string>
<string name="a11y_bg_quality_doubles">entrées doubles</string>
<string name="a11y_bg_quality_flat">Données plates. Considérées comme incorrectes</string> <string name="a11y_bg_quality_flat">Données plates. Considérées comme incorrectes</string>
<!-- Safety --> <!-- Safety -->
<string name="limitingextendedbolus">Bolus étendu limité à %1$.1f U à cause de %2$s</string>
<string name="limitingcarbs">Limiter les glucides %1$d g à cause de %2$s</string> <string name="limitingcarbs">Limiter les glucides %1$d g à cause de %2$s</string>
<string name="pumpisnottempbasalcapable">Pompe nest pas capable de basals temporaires</string> <string name="pumpisnottempbasalcapable">Pompe nest pas capable de basals temporaires</string>
<string name="closedmodedisabledinpreferences">Mode de Boucle Fermée désactivé dans les préférences</string> <string name="closedmodedisabledinpreferences">Mode de Boucle Fermée désactivé dans les préférences</string>
@ -17,7 +32,7 @@
<string name="smbnotallowedinopenloopmode">SMB non autorisé en mode boucle ouverte</string> <string name="smbnotallowedinopenloopmode">SMB non autorisé en mode boucle ouverte</string>
<string name="maxvalueinpreferences">valeur Max dans les préférences</string> <string name="maxvalueinpreferences">valeur Max dans les préférences</string>
<string name="hardlimit">limite fixée</string> <string name="hardlimit">limite fixée</string>
<string name="treatmentssafety_title">Traitements de sécurité</string> <string name="treatmentssafety_title">Sécurité des traitements</string>
<!-- Objectives --> <!-- Objectives -->
<string name="completed_well_done">Terminé, félicitations !</string> <string name="completed_well_done">Terminé, félicitations !</string>
<string name="not_completed_yet">Pas encore terminé</string> <string name="not_completed_yet">Pas encore terminé</string>

View file

@ -108,6 +108,7 @@
<string name="troubleshooting_hint1">https://androidaps.readthedocs.io/en/latest/EN/Installing-AndroidAPS/Update-to-new-version.html#troubleshooting</string> <string name="troubleshooting_hint1">https://androidaps.readthedocs.io/en/latest/EN/Installing-AndroidAPS/Update-to-new-version.html#troubleshooting</string>
<string name="troubleshooting_hint2">https://www.facebook.com/groups/AndroidAPSUsers/</string> <string name="troubleshooting_hint2">https://www.facebook.com/groups/AndroidAPSUsers/</string>
<string name="troubleshooting_hint3">https://discord.gg/4fQUWHZ4Mw</string> <string name="troubleshooting_hint3">https://discord.gg/4fQUWHZ4Mw</string>
<string name="insulin_plugins">Модули для инсулинов</string>
<string name="insulin_ultrarapid">Какой инсулин следует использовать с модулем Сверхбыстрый Oref?</string> <string name="insulin_ultrarapid">Какой инсулин следует использовать с модулем Сверхбыстрый Oref?</string>
<string name="insulin_fiasp">Fiasp®</string> <string name="insulin_fiasp">Fiasp®</string>
<string name="insulin_novorapid">Novoapid ® /Novolog ®</string> <string name="insulin_novorapid">Novoapid ® /Novolog ®</string>

View file

@ -2,11 +2,27 @@
<resources> <resources>
<!-- PhoneChecker --> <!-- PhoneChecker -->
<!-- DST Helper --> <!-- DST Helper -->
<string name="dst_in_24h_warning">Переход на летнее/зимнее время через 24 часа или менее</string>
<string name="dst_loop_disabled_warning">Изменение сезонного времени произошло меньше 3 часов назад-Закрытый цикл выключен</string>
<!-- Storage constraint --> <!-- Storage constraint -->
<string name="disk_full">Освободите по крайней мере %1$d MB из внутренней памяти! Цикл остановлен!</string>
<!-- Version Checker --> <!-- Version Checker -->
<string name="old_version">старая версия</string>
<string name="very_old_version">очень старая версия</string>
<string name="application_expired">Истек срок действия приложения</string>
<string name="new_version_warning">Новая версия доступна уже %1$d дней! По истечении %2$d дн алгоритм переходит в режим работы только с остановкой при низкой гликемии LGS, замкнутый цикл будет отключен через %3$d дн</string>
<string name="running_invalid_version">Мы обнаружили, что вы используете недопустимую версию. Цикл отключен!</string>
<string name="versionavailable">Доступна версия %1$s</string>
<string name="version_expire">Версия: %1$s истекает %2$s</string>
<!-- Signature verifier --> <!-- Signature verifier -->
<!-- BG Quality --> <!-- BG Quality -->
<string name="recalculated_data_used">Используются пересчитанные данные</string>
<string name="bg_too_close">ГК слишком близко:\n%1$s\n%2$s</string>
<string name="a11y_bg_quality_recalculated">пересчитано</string>
<string name="a11y_bg_quality_doubles">двойные записи</string>
<string name="a11y_bg_quality_flat">Неменяющиеся данные. Принимаю за неверные</string>
<!-- Safety --> <!-- Safety -->
<string name="limitingextendedbolus">Ограничиваю пролонгированный болюс до %1$.1f ед. из-за %2$s</string>
<string name="limitingcarbs">Ограничение углеводов до %1$d г. из-за %2$s</string> <string name="limitingcarbs">Ограничение углеводов до %1$d г. из-за %2$s</string>
<string name="pumpisnottempbasalcapable">Помпа не рассчитана на подачу временного базала</string> <string name="pumpisnottempbasalcapable">Помпа не рассчитана на подачу временного базала</string>
<string name="closedmodedisabledinpreferences">Режим замкнутого цикла отключен в настройках</string> <string name="closedmodedisabledinpreferences">Режим замкнутого цикла отключен в настройках</string>
@ -18,6 +34,7 @@
<string name="hardlimit">жесткий предел</string> <string name="hardlimit">жесткий предел</string>
<string name="treatmentssafety_title">Безопасность терапии</string> <string name="treatmentssafety_title">Безопасность терапии</string>
<!-- Objectives --> <!-- Objectives -->
<string name="completed_well_done">Завершено, отлично!</string>
<string name="not_completed_yet">Не завершено</string> <string name="not_completed_yet">Не завершено</string>
<string name="time_elapsed">Прошло времени</string> <string name="time_elapsed">Прошло времени</string>
<string name="maxiobset">Максимум активного инсулина IOB установлен правильно</string> <string name="maxiobset">Максимум активного инсулина IOB установлен правильно</string>

View file

@ -1,8 +1,8 @@
package info.nightscout.insulin package info.nightscout.insulin
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.core.extensions.putInt import info.nightscout.core.utils.extensions.putInt
import info.nightscout.core.extensions.storeInt import info.nightscout.core.utils.extensions.storeInt
import info.nightscout.interfaces.Config import info.nightscout.interfaces.Config
import info.nightscout.interfaces.insulin.Insulin import info.nightscout.interfaces.insulin.Insulin
import info.nightscout.interfaces.profile.ProfileFunction import info.nightscout.interfaces.profile.ProfileFunction

View file

@ -1,8 +1,18 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<!-- Insulin --> <!-- Insulin -->
<string name="lyumjev">Lyumjev</string>
<string name="description_insulin_rapid">Réglages pour les insulines Humalog et NovoRapid / NovoLog</string>
<string name="description_insulin_ultra_rapid">Réglages pour l\'insuline Fiasp</string>
<string name="description_insulin_lyumjev">Réglages pour l\'insuline Lyumjev</string>
<string name="description_insulin_free_peak">Permet de définir le pic de lactivité de linsuline et ne doit être utilisé que par les utilisateurs avancés</string>
<string name="insulin_shortname">INS</string>
<string name="insulin_oref_peak">Délai du pic de la courbe IA</string>
<string name="insulin_peak_time">Délai du pic [min]</string>
<string name="free_peak_oref">Profil d\'insuline ajustable Oref</string> <string name="free_peak_oref">Profil d\'insuline ajustable Oref</string>
<string name="rapid_acting_oref">Insuline à Action Rapide Oref </string> <string name="rapid_acting_oref">Insuline à Action Rapide Oref </string>
<string name="ultra_rapid_oref">Insuline Ultra Rapide Oref</string> <string name="ultra_rapid_oref">Insuline Ultra Rapide Oref</string>
<string name="dia_too_short">Durée dAction pour %1$f trop courte - utiliser %2$f à la place !</string> <string name="dia_too_short">Durée dAction pour %1$f trop courte - utiliser %2$f à la place !</string>
<string name="fast_acting_insulin_comment">Novorapid, Novolog, Humalog</string>
<string name="ultra_fast_acting_insulin_comment">Fiasp</string>
</resources> </resources>

View file

@ -1,11 +1,14 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-feature
android:name="android.hardware.telephony"
android:required="false" />
<uses-permission android:name="android.permission.RECEIVE_SMS" /> <uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.RECEIVE_MMS" /> <uses-permission android:name="android.permission.RECEIVE_MMS" />
<uses-permission android:name="android.permission.SEND_SMS" /> <uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.SEND_MMS" />
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<application> <application>

View file

@ -7,14 +7,14 @@ import androidx.preference.SwitchPreference
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.core.events.EventIobCalculationProgress import info.nightscout.core.events.EventIobCalculationProgress
import info.nightscout.core.events.EventNewNotification import info.nightscout.core.events.EventNewNotification
import info.nightscout.core.extensions.putDouble
import info.nightscout.core.extensions.putInt
import info.nightscout.core.extensions.putString
import info.nightscout.core.extensions.storeDouble
import info.nightscout.core.extensions.storeInt
import info.nightscout.core.extensions.storeString
import info.nightscout.core.graph.OverviewData import info.nightscout.core.graph.OverviewData
import info.nightscout.core.ui.dialogs.OKDialog import info.nightscout.core.ui.dialogs.OKDialog
import info.nightscout.core.utils.extensions.putDouble
import info.nightscout.core.utils.extensions.putInt
import info.nightscout.core.utils.extensions.putString
import info.nightscout.core.utils.extensions.storeDouble
import info.nightscout.core.utils.extensions.storeInt
import info.nightscout.core.utils.extensions.storeString
import info.nightscout.core.utils.fabric.FabricPrivacy import info.nightscout.core.utils.fabric.FabricPrivacy
import info.nightscout.interfaces.Config import info.nightscout.interfaces.Config
import info.nightscout.interfaces.Overview import info.nightscout.interfaces.Overview

View file

@ -10,9 +10,9 @@ import android.view.WindowManager
import com.google.android.material.timepicker.MaterialTimePicker import com.google.android.material.timepicker.MaterialTimePicker
import com.google.android.material.timepicker.TimeFormat import com.google.android.material.timepicker.TimeFormat
import dagger.android.support.DaggerDialogFragment import dagger.android.support.DaggerDialogFragment
import info.nightscout.androidaps.utils.extensions.selectedItemPosition import info.nightscout.core.ui.extensions.selectedItemPosition
import info.nightscout.androidaps.utils.extensions.setEnableForChildren import info.nightscout.core.ui.extensions.setEnableForChildren
import info.nightscout.androidaps.utils.extensions.setSelection import info.nightscout.core.ui.extensions.setSelection
import info.nightscout.core.wizard.QuickWizard import info.nightscout.core.wizard.QuickWizard
import info.nightscout.core.wizard.QuickWizardEntry import info.nightscout.core.wizard.QuickWizardEntry
import info.nightscout.plugins.R import info.nightscout.plugins.R

View file

@ -5,9 +5,9 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import dagger.android.support.DaggerFragment import dagger.android.support.DaggerFragment
import info.nightscout.androidaps.plugins.general.wear.events.EventWearUpdateGui
import info.nightscout.core.utils.fabric.FabricPrivacy import info.nightscout.core.utils.fabric.FabricPrivacy
import info.nightscout.plugins.databinding.WearFragmentBinding import info.nightscout.plugins.databinding.WearFragmentBinding
import info.nightscout.plugins.general.wear.events.EventWearUpdateGui
import info.nightscout.rx.AapsSchedulers import info.nightscout.rx.AapsSchedulers
import info.nightscout.rx.bus.RxBus import info.nightscout.rx.bus.RxBus
import info.nightscout.rx.events.EventMobileToWear import info.nightscout.rx.events.EventMobileToWear

View file

@ -1,4 +1,4 @@
package info.nightscout.androidaps.plugins.general.wear.events package info.nightscout.plugins.general.wear.events
import info.nightscout.rx.events.Event import info.nightscout.rx.events.Event

View file

@ -15,7 +15,6 @@ import com.google.android.gms.wearable.PutDataMapRequest
import com.google.android.gms.wearable.Wearable import com.google.android.gms.wearable.Wearable
import com.google.android.gms.wearable.WearableListenerService import com.google.android.gms.wearable.WearableListenerService
import dagger.android.AndroidInjection import dagger.android.AndroidInjection
import info.nightscout.androidaps.plugins.general.wear.events.EventWearUpdateGui
import info.nightscout.core.utils.fabric.FabricPrivacy import info.nightscout.core.utils.fabric.FabricPrivacy
import info.nightscout.database.impl.AppRepository import info.nightscout.database.impl.AppRepository
import info.nightscout.interfaces.Config import info.nightscout.interfaces.Config
@ -27,6 +26,7 @@ import info.nightscout.interfaces.profile.ProfileFunction
import info.nightscout.interfaces.receivers.ReceiverStatusStore import info.nightscout.interfaces.receivers.ReceiverStatusStore
import info.nightscout.plugins.R import info.nightscout.plugins.R
import info.nightscout.plugins.general.wear.WearPlugin import info.nightscout.plugins.general.wear.WearPlugin
import info.nightscout.plugins.general.wear.events.EventWearUpdateGui
import info.nightscout.rx.AapsSchedulers import info.nightscout.rx.AapsSchedulers
import info.nightscout.rx.bus.RxBus import info.nightscout.rx.bus.RxBus
import info.nightscout.rx.events.EventMobileToWear import info.nightscout.rx.events.EventMobileToWear

View file

@ -140,7 +140,7 @@ class BGSourceFragment : DaggerFragment(), MenuProvider {
val newDay = position == 0 || !dateUtil.isSameDay(glucoseValue.timestamp, glucoseValues[position - 1].timestamp) val newDay = position == 0 || !dateUtil.isSameDay(glucoseValue.timestamp, glucoseValues[position - 1].timestamp)
holder.binding.date.visibility = newDay.toVisibility() holder.binding.date.visibility = newDay.toVisibility()
holder.binding.date.text = if (newDay) dateUtil.dateStringRelative(glucoseValue.timestamp, rh) else "" holder.binding.date.text = if (newDay) dateUtil.dateStringRelative(glucoseValue.timestamp, rh) else ""
holder.binding.time.text = dateUtil.timeString(glucoseValue.timestamp) holder.binding.time.text = dateUtil.timeStringWithSeconds(glucoseValue.timestamp)
holder.binding.value.text = glucoseValue.valueToUnitsString(profileFunction.getUnits()) holder.binding.value.text = glucoseValue.valueToUnitsString(profileFunction.getUnits())
holder.binding.direction.setImageResource(glucoseValue.trendArrow.directionToIcon()) holder.binding.direction.setImageResource(glucoseValue.trendArrow.directionToIcon())
if (position > 0) { if (position > 0) {

View file

@ -1,22 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<!-- Source --> <!-- Source -->
<string name="ns_client_bg">NSClient BG</string> <string name="eversense">Eversense App (parchada)</string>
<string name="ns_client_bg_short">NS BG</string>
<string name="description_source_ns_client">Recibir los datos de glucosa de Nightscout</string>
<string name="xdrip">xDrip+</string>
<string name="description_source_xdrip">Recibir los valores de glucosa de xDrip+</string>
<string name="dexcom_app_patched">Dexcom (BYODA)</string>
<string name="dexcom_short">BYODA</string>
<string name="description_source_dexcom">Recibir los valores de glucosa de la aplicación Dexcom \'Build Your Own Device\'</string>
<string name="eversense">Eversense App (parcheada)</string>
<string name="description_source_eversense">Recibir los valores de glucosa de la aplicación Eversense parcheada.</string>
<string name="glimp">Glimp</string>
<string name="description_source_glimp">Recibir valores de glucosa de Glimp.</string>
<string name="mm640g">MM640g</string>
<string name="description_source_mm640g">Recibir los valores de glucosa del 600SeriesAndroidUploader.</string>
<string name="poctech">Poctech</string>
<string name="description_source_poctech">Recibir los valores de glucosa de Poctech</string>
<string name="glunovo">Glunovo</string> <string name="glunovo">Glunovo</string>
<string name="description_source_glunovo">Recibir los valores de glucosa de la aplicación Glunovo</string> <string name="description_source_glunovo">Recibir los valores de glucosa de la aplicación Glunovo</string>
<string name="intelligo">Intelligo</string> <string name="intelligo">Intelligo</string>
@ -35,4 +20,5 @@
<string name="bgsource_upload">Ajuste de subida de datos de glucosa</string> <string name="bgsource_upload">Ajuste de subida de datos de glucosa</string>
<string name="dexcom_log_ns_sensor_change_title">Registro de cambio de sensor en Nightscout</string> <string name="dexcom_log_ns_sensor_change_title">Registro de cambio de sensor en Nightscout</string>
<string name="dexcom_log_ns_sensor_change_summary">Crear evento \"Cambio de sensor\" en Nightscout automáticamente al iniciar el sensor</string> <string name="dexcom_log_ns_sensor_change_summary">Crear evento \"Cambio de sensor\" en Nightscout automáticamente al iniciar el sensor</string>
<string name="direction">dirección</string>
</resources> </resources>

View file

@ -35,4 +35,5 @@
<string name="bgsource_upload">Paramètres de téléchargement des glycémies</string> <string name="bgsource_upload">Paramètres de téléchargement des glycémies</string>
<string name="dexcom_log_ns_sensor_change_title">Enreg. du changement de capteur sur NS</string> <string name="dexcom_log_ns_sensor_change_title">Enreg. du changement de capteur sur NS</string>
<string name="dexcom_log_ns_sensor_change_summary">Créer automatiquement un événement \"Changement de capteur\" dans NS au démarrage du capteur</string> <string name="dexcom_log_ns_sensor_change_summary">Créer automatiquement un événement \"Changement de capteur\" dans NS au démarrage du capteur</string>
<string name="direction">direction</string>
</resources> </resources>

View file

@ -1,6 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<!-- Source --> <!-- Source -->
<string name="ns_client_bg">ГК с клиента Nightscout</string>
<string name="ns_client_bg_short">ГК с NS</string>
<string name="description_source_ns_client">Получать данные гликемии с сайта Nightscout</string> <string name="description_source_ns_client">Получать данные гликемии с сайта Nightscout</string>
<string name="xdrip">xDrip +</string> <string name="xdrip">xDrip +</string>
<string name="description_source_xdrip">Получать данные гликемии от xDrip+.</string> <string name="description_source_xdrip">Получать данные гликемии от xDrip+.</string>
@ -9,7 +11,9 @@
<string name="description_source_dexcom">Получать данные ГК от \'Самостоятельно собранного приложения Dexcom\'.</string> <string name="description_source_dexcom">Получать данные ГК от \'Самостоятельно собранного приложения Dexcom\'.</string>
<string name="eversense">Приложение Eversense (пропатченное)</string> <string name="eversense">Приложение Eversense (пропатченное)</string>
<string name="description_source_eversense">Получать данные гликемии от пропатченного приложения Eversense.</string> <string name="description_source_eversense">Получать данные гликемии от пропатченного приложения Eversense.</string>
<string name="glimp">Glimp</string>
<string name="description_source_glimp">Получать данные гликемии от Glimp.</string> <string name="description_source_glimp">Получать данные гликемии от Glimp.</string>
<string name="mm640g">MM640g</string>
<string name="description_source_mm640g">Получать данные гликемии от 600SeriesAndroidUploader.</string> <string name="description_source_mm640g">Получать данные гликемии от 600SeriesAndroidUploader.</string>
<string name="poctech">Poctech</string> <string name="poctech">Poctech</string>
<string name="description_source_poctech">Получать данные гликемии от приложения Poctech</string> <string name="description_source_poctech">Получать данные гликемии от приложения Poctech</string>
@ -20,6 +24,7 @@
<string name="tomato">Томато (MiaoMiao)</string> <string name="tomato">Томато (MiaoMiao)</string>
<string name="tomato_short">Томато</string> <string name="tomato_short">Томато</string>
<string name="description_source_tomato">Получать значения ГК от приложения Tomato (устройство MiaoMiao)</string> <string name="description_source_tomato">Получать значения ГК от приложения Tomato (устройство MiaoMiao)</string>
<string name="aidex">Aidex GlucoRx</string>
<string name="aidex_short">Aidex </string> <string name="aidex_short">Aidex </string>
<string name="description_source_aidex">Получить значения ГК от GlucoRx Aidex</string> <string name="description_source_aidex">Получить значения ГК от GlucoRx Aidex</string>
<string name="random_bg">Случайные значения ГК</string> <string name="random_bg">Случайные значения ГК</string>
@ -30,4 +35,5 @@
<string name="bgsource_upload">Параметры загрузки СК</string> <string name="bgsource_upload">Параметры загрузки СК</string>
<string name="dexcom_log_ns_sensor_change_title">Вносить запись о замене сенсора в NS</string> <string name="dexcom_log_ns_sensor_change_title">Вносить запись о замене сенсора в NS</string>
<string name="dexcom_log_ns_sensor_change_summary">Автоматически создать событие \"Замена сенсора\" в NS при запуске сенсора</string> <string name="dexcom_log_ns_sensor_change_summary">Автоматически создать событие \"Замена сенсора\" в NS при запуске сенсора</string>
<string name="direction">направление</string>
</resources> </resources>

View file

@ -159,7 +159,7 @@ class DataSyncSelectorImplementation @Inject constructor(
} }
// without nsId = create new // without nsId = create new
bolus.first.interfaceIDs.nightscoutId == null -> bolus.first.interfaceIDs.nightscoutId == null ->
activePlugin.activeNsClient?.nsClientService?.dbAdd( activePlugin.activeNsClient?.dbAdd(
"treatments", "treatments",
bolus.first.toJson(true, dateUtil), bolus.first.toJson(true, dateUtil),
DataSyncSelector.PairBolus(bolus.first, bolus.second.id), DataSyncSelector.PairBolus(bolus.first, bolus.second.id),
@ -167,7 +167,7 @@ class DataSyncSelectorImplementation @Inject constructor(
) )
// with nsId = update if it's modified record // with nsId = update if it's modified record
bolus.first.interfaceIDs.nightscoutId != null && bolus.first.id != bolus.second.id -> bolus.first.interfaceIDs.nightscoutId != null && bolus.first.id != bolus.second.id ->
activePlugin.activeNsClient?.nsClientService?.dbUpdate( activePlugin.activeNsClient?.dbUpdate(
"treatments", "treatments",
bolus.first.interfaceIDs.nightscoutId, bolus.first.interfaceIDs.nightscoutId,
bolus.first.toJson(false, dateUtil), bolus.first.toJson(false, dateUtil),
@ -222,10 +222,10 @@ class DataSyncSelectorImplementation @Inject constructor(
} }
// without nsId = create new // without nsId = create new
carb.first.interfaceIDs.nightscoutId == null -> carb.first.interfaceIDs.nightscoutId == null ->
activePlugin.activeNsClient?.nsClientService?.dbAdd("treatments", carb.first.toJson(true, dateUtil), DataSyncSelector.PairCarbs(carb.first, carb.second.id), "$startId/$lastDbId") activePlugin.activeNsClient?.dbAdd("treatments", carb.first.toJson(true, dateUtil), DataSyncSelector.PairCarbs(carb.first, carb.second.id), "$startId/$lastDbId")
// with nsId = update if it's modified record // with nsId = update if it's modified record
carb.first.interfaceIDs.nightscoutId != null && carb.first.id != carb.second.id -> carb.first.interfaceIDs.nightscoutId != null && carb.first.id != carb.second.id ->
activePlugin.activeNsClient?.nsClientService?.dbUpdate( activePlugin.activeNsClient?.dbUpdate(
"treatments", "treatments",
carb.first.interfaceIDs.nightscoutId, carb.first.interfaceIDs.nightscoutId,
carb.first.toJson(false, dateUtil), carb.first.toJson(false, dateUtil),
@ -280,7 +280,7 @@ class DataSyncSelectorImplementation @Inject constructor(
} }
// without nsId = create new // without nsId = create new
bolusCalculatorResult.first.interfaceIDs.nightscoutId == null -> bolusCalculatorResult.first.interfaceIDs.nightscoutId == null ->
activePlugin.activeNsClient?.nsClientService?.dbAdd( activePlugin.activeNsClient?.dbAdd(
"treatments", "treatments",
bolusCalculatorResult.first.toJson(true, dateUtil, profileFunction), bolusCalculatorResult.first.toJson(true, dateUtil, profileFunction),
DataSyncSelector.PairBolusCalculatorResult(bolusCalculatorResult.first, bolusCalculatorResult.second.id), DataSyncSelector.PairBolusCalculatorResult(bolusCalculatorResult.first, bolusCalculatorResult.second.id),
@ -288,7 +288,7 @@ class DataSyncSelectorImplementation @Inject constructor(
) )
// with nsId = update if it's modified record // with nsId = update if it's modified record
bolusCalculatorResult.first.interfaceIDs.nightscoutId != null && bolusCalculatorResult.first.id != bolusCalculatorResult.second.id -> bolusCalculatorResult.first.interfaceIDs.nightscoutId != null && bolusCalculatorResult.first.id != bolusCalculatorResult.second.id ->
activePlugin.activeNsClient?.nsClientService?.dbUpdate( activePlugin.activeNsClient?.dbUpdate(
"treatments", bolusCalculatorResult.first.interfaceIDs.nightscoutId, bolusCalculatorResult.first.toJson(false, dateUtil, profileFunction), "treatments", bolusCalculatorResult.first.interfaceIDs.nightscoutId, bolusCalculatorResult.first.toJson(false, dateUtil, profileFunction),
DataSyncSelector.PairBolusCalculatorResult(bolusCalculatorResult.first, bolusCalculatorResult.second.id), "$startId/$lastDbId" DataSyncSelector.PairBolusCalculatorResult(bolusCalculatorResult.first, bolusCalculatorResult.second.id), "$startId/$lastDbId"
) )
@ -340,7 +340,7 @@ class DataSyncSelectorImplementation @Inject constructor(
} }
// without nsId = create new // without nsId = create new
tt.first.interfaceIDs.nightscoutId == null -> tt.first.interfaceIDs.nightscoutId == null ->
activePlugin.activeNsClient?.nsClientService?.dbAdd( activePlugin.activeNsClient?.dbAdd(
"treatments", "treatments",
tt.first.toJson(true, profileFunction.getUnits(), dateUtil), tt.first.toJson(true, profileFunction.getUnits(), dateUtil),
DataSyncSelector.PairTemporaryTarget(tt.first, tt.second.id), DataSyncSelector.PairTemporaryTarget(tt.first, tt.second.id),
@ -348,7 +348,7 @@ class DataSyncSelectorImplementation @Inject constructor(
) )
// existing with nsId = update // existing with nsId = update
tt.first.interfaceIDs.nightscoutId != null -> tt.first.interfaceIDs.nightscoutId != null ->
activePlugin.activeNsClient?.nsClientService?.dbUpdate( activePlugin.activeNsClient?.dbUpdate(
"treatments", "treatments",
tt.first.interfaceIDs.nightscoutId, tt.first.interfaceIDs.nightscoutId,
tt.first.toJson(false, profileFunction.getUnits(), dateUtil), tt.first.toJson(false, profileFunction.getUnits(), dateUtil),
@ -403,10 +403,10 @@ class DataSyncSelectorImplementation @Inject constructor(
} }
// without nsId = create new // without nsId = create new
food.first.interfaceIDs.nightscoutId == null -> food.first.interfaceIDs.nightscoutId == null ->
activePlugin.activeNsClient?.nsClientService?.dbAdd("food", food.first.toJson(true), DataSyncSelector.PairFood(food.first, food.second.id), "$startId/$lastDbId") activePlugin.activeNsClient?.dbAdd("food", food.first.toJson(true), DataSyncSelector.PairFood(food.first, food.second.id), "$startId/$lastDbId")
// with nsId = update // with nsId = update
food.first.interfaceIDs.nightscoutId != null -> food.first.interfaceIDs.nightscoutId != null ->
activePlugin.activeNsClient?.nsClientService?.dbUpdate( activePlugin.activeNsClient?.dbUpdate(
"food", "food",
food.first.interfaceIDs.nightscoutId, food.first.interfaceIDs.nightscoutId,
food.first.toJson(false), food.first.toJson(false),
@ -462,10 +462,10 @@ class DataSyncSelectorImplementation @Inject constructor(
} }
// without nsId = create new // without nsId = create new
gv.first.interfaceIDs.nightscoutId == null -> gv.first.interfaceIDs.nightscoutId == null ->
activePlugin.activeNsClient?.nsClientService?.dbAdd("entries", gv.first.toJson(true, dateUtil), DataSyncSelector.PairGlucoseValue(gv.first, gv.second.id), "$startId/$lastDbId") activePlugin.activeNsClient?.dbAdd("entries", gv.first.toJson(true, dateUtil), DataSyncSelector.PairGlucoseValue(gv.first, gv.second.id), "$startId/$lastDbId")
// with nsId = update // with nsId = update
else -> // gv.first.interfaceIDs.nightscoutId != null else -> // gv.first.interfaceIDs.nightscoutId != null
activePlugin.activeNsClient?.nsClientService?.dbUpdate( activePlugin.activeNsClient?.dbUpdate(
"entries", "entries",
gv.first.interfaceIDs.nightscoutId, gv.first.interfaceIDs.nightscoutId,
gv.first.toJson(false, dateUtil), gv.first.toJson(false, dateUtil),
@ -524,10 +524,10 @@ class DataSyncSelectorImplementation @Inject constructor(
} }
// without nsId = create new // without nsId = create new
te.first.interfaceIDs.nightscoutId == null -> te.first.interfaceIDs.nightscoutId == null ->
activePlugin.activeNsClient?.nsClientService?.dbAdd("treatments", te.first.toJson(true, dateUtil), DataSyncSelector.PairTherapyEvent(te.first, te.second.id), "$startId/$lastDbId") activePlugin.activeNsClient?.dbAdd("treatments", te.first.toJson(true, dateUtil), DataSyncSelector.PairTherapyEvent(te.first, te.second.id), "$startId/$lastDbId")
// nsId = update // nsId = update
te.first.interfaceIDs.nightscoutId != null -> te.first.interfaceIDs.nightscoutId != null ->
activePlugin.activeNsClient?.nsClientService?.dbUpdate( activePlugin.activeNsClient?.dbUpdate(
"treatments", "treatments",
te.first.interfaceIDs.nightscoutId, te.first.interfaceIDs.nightscoutId,
te.first.toJson(false, dateUtil), te.first.toJson(false, dateUtil),
@ -567,7 +567,7 @@ class DataSyncSelectorImplementation @Inject constructor(
when { when {
// without nsId = create new // without nsId = create new
deviceStatus.interfaceIDs.nightscoutId == null -> deviceStatus.interfaceIDs.nightscoutId == null ->
activePlugin.activeNsClient?.nsClientService?.dbAdd("devicestatus", deviceStatus.toJson(dateUtil), deviceStatus, "$startId/$lastDbId") activePlugin.activeNsClient?.dbAdd("devicestatus", deviceStatus.toJson(dateUtil), deviceStatus, "$startId/$lastDbId")
// with nsId = ignore // with nsId = ignore
deviceStatus.interfaceIDs.nightscoutId != null -> Any() deviceStatus.interfaceIDs.nightscoutId != null -> Any()
} }
@ -620,7 +620,7 @@ class DataSyncSelectorImplementation @Inject constructor(
} }
// without nsId = create new // without nsId = create new
tb.first.interfaceIDs.nightscoutId == null -> tb.first.interfaceIDs.nightscoutId == null ->
activePlugin.activeNsClient?.nsClientService?.dbAdd( activePlugin.activeNsClient?.dbAdd(
"treatments", "treatments",
tb.first.toJson(true, profile, dateUtil), tb.first.toJson(true, profile, dateUtil),
DataSyncSelector.PairTemporaryBasal(tb.first, tb.second.id), DataSyncSelector.PairTemporaryBasal(tb.first, tb.second.id),
@ -628,7 +628,7 @@ class DataSyncSelectorImplementation @Inject constructor(
) )
// with nsId = update // with nsId = update
tb.first.interfaceIDs.nightscoutId != null -> tb.first.interfaceIDs.nightscoutId != null ->
activePlugin.activeNsClient?.nsClientService?.dbUpdate( activePlugin.activeNsClient?.dbUpdate(
"treatments", "treatments",
tb.first.interfaceIDs.nightscoutId, tb.first.interfaceIDs.nightscoutId,
tb.first.toJson(false, profile, dateUtil), tb.first.toJson(false, profile, dateUtil),
@ -691,7 +691,7 @@ class DataSyncSelectorImplementation @Inject constructor(
} }
// without nsId = create new // without nsId = create new
eb.first.interfaceIDs.nightscoutId == null -> eb.first.interfaceIDs.nightscoutId == null ->
activePlugin.activeNsClient?.nsClientService?.dbAdd( activePlugin.activeNsClient?.dbAdd(
"treatments", "treatments",
eb.first.toJson(true, profile, dateUtil), eb.first.toJson(true, profile, dateUtil),
DataSyncSelector.PairExtendedBolus(eb.first, eb.second.id), DataSyncSelector.PairExtendedBolus(eb.first, eb.second.id),
@ -699,7 +699,7 @@ class DataSyncSelectorImplementation @Inject constructor(
) )
// with nsId = update // with nsId = update
eb.first.interfaceIDs.nightscoutId != null -> eb.first.interfaceIDs.nightscoutId != null ->
activePlugin.activeNsClient?.nsClientService?.dbUpdate( activePlugin.activeNsClient?.dbUpdate(
"treatments", "treatments",
eb.first.interfaceIDs.nightscoutId, eb.first.interfaceIDs.nightscoutId,
eb.first.toJson(false, profile, dateUtil), eb.first.toJson(false, profile, dateUtil),
@ -759,10 +759,10 @@ class DataSyncSelectorImplementation @Inject constructor(
} }
// without nsId = create new // without nsId = create new
ps.first.interfaceIDs.nightscoutId == null -> ps.first.interfaceIDs.nightscoutId == null ->
activePlugin.activeNsClient?.nsClientService?.dbAdd("treatments", ps.first.toJson(true, dateUtil), DataSyncSelector.PairProfileSwitch(ps.first, ps.second.id), "$startId/$lastDbId") activePlugin.activeNsClient?.dbAdd("treatments", ps.first.toJson(true, dateUtil), DataSyncSelector.PairProfileSwitch(ps.first, ps.second.id), "$startId/$lastDbId")
// with nsId = update // with nsId = update
ps.first.interfaceIDs.nightscoutId != null -> ps.first.interfaceIDs.nightscoutId != null ->
activePlugin.activeNsClient?.nsClientService?.dbUpdate( activePlugin.activeNsClient?.dbUpdate(
"treatments", "treatments",
ps.first.interfaceIDs.nightscoutId, ps.first.interfaceIDs.nightscoutId,
ps.first.toJson(false, dateUtil), ps.first.toJson(false, dateUtil),
@ -816,7 +816,7 @@ class DataSyncSelectorImplementation @Inject constructor(
} }
// without nsId = create new // without nsId = create new
ps.first.interfaceIDs.nightscoutId == null -> ps.first.interfaceIDs.nightscoutId == null ->
activePlugin.activeNsClient?.nsClientService?.dbAdd( activePlugin.activeNsClient?.dbAdd(
"treatments", "treatments",
ps.first.toJson(true, dateUtil), ps.first.toJson(true, dateUtil),
DataSyncSelector.PairEffectiveProfileSwitch(ps.first, ps.second.id), DataSyncSelector.PairEffectiveProfileSwitch(ps.first, ps.second.id),
@ -824,7 +824,7 @@ class DataSyncSelectorImplementation @Inject constructor(
) )
// with nsId = update // with nsId = update
ps.first.interfaceIDs.nightscoutId != null -> ps.first.interfaceIDs.nightscoutId != null ->
activePlugin.activeNsClient?.nsClientService?.dbUpdate( activePlugin.activeNsClient?.dbUpdate(
"treatments", "treatments",
ps.first.interfaceIDs.nightscoutId, ps.first.interfaceIDs.nightscoutId,
ps.first.toJson(false, dateUtil), ps.first.toJson(false, dateUtil),
@ -879,10 +879,10 @@ class DataSyncSelectorImplementation @Inject constructor(
} }
// without nsId = create new // without nsId = create new
oe.first.interfaceIDs.nightscoutId == null -> oe.first.interfaceIDs.nightscoutId == null ->
activePlugin.activeNsClient?.nsClientService?.dbAdd("treatments", oe.first.toJson(true, dateUtil), DataSyncSelector.PairOfflineEvent(oe.first, oe.second.id), "$startId/$lastDbId") activePlugin.activeNsClient?.dbAdd("treatments", oe.first.toJson(true, dateUtil), DataSyncSelector.PairOfflineEvent(oe.first, oe.second.id), "$startId/$lastDbId")
// existing with nsId = update // existing with nsId = update
oe.first.interfaceIDs.nightscoutId != null -> oe.first.interfaceIDs.nightscoutId != null ->
activePlugin.activeNsClient?.nsClientService?.dbUpdate( activePlugin.activeNsClient?.dbUpdate(
"treatments", "treatments",
oe.first.interfaceIDs.nightscoutId, oe.first.interfaceIDs.nightscoutId,
oe.first.toJson(false, dateUtil), oe.first.toJson(false, dateUtil),
@ -905,7 +905,7 @@ class DataSyncSelectorImplementation @Inject constructor(
if (lastChange > lastSync) { if (lastChange > lastSync) {
if (activePlugin.activeProfileSource.profile?.allProfilesValid != true) return if (activePlugin.activeProfileSource.profile?.allProfilesValid != true) return
val profileJson = activePlugin.activeProfileSource.profile?.data ?: return val profileJson = activePlugin.activeProfileSource.profile?.data ?: return
activePlugin.activeNsClient?.nsClientService?.dbAdd("profile", profileJson, DataSyncSelector.PairProfileStore(profileJson, dateUtil.now()), "") activePlugin.activeNsClient?.dbAdd("profile", profileJson, DataSyncSelector.PairProfileStore(profileJson, dateUtil.now()), "")
} }
} }
} }

View file

@ -47,6 +47,7 @@ import info.nightscout.shared.interfaces.ResourceHelper
import info.nightscout.shared.sharedPreferences.SP import info.nightscout.shared.sharedPreferences.SP
import io.reactivex.rxjava3.disposables.CompositeDisposable import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign import io.reactivex.rxjava3.kotlin.plusAssign
import org.json.JSONObject
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@ -81,7 +82,7 @@ class NSClientPlugin @Inject constructor(
private val handler = Handler(HandlerThread(this::class.simpleName + "Handler").also { it.start() }.looper) private val handler = Handler(HandlerThread(this::class.simpleName + "Handler").also { it.start() }.looper)
private val listLog: MutableList<EventNSClientNewLog> = ArrayList() private val listLog: MutableList<EventNSClientNewLog> = ArrayList()
override var status = "" override var status = ""
override var nsClientService: NSClientService? = null var nsClientService: NSClientService? = null
val isAllowed: Boolean val isAllowed: Boolean
get() = nsClientReceiverDelegate.allowed get() = nsClientReceiverDelegate.allowed
val blockingReason: String val blockingReason: String
@ -235,4 +236,12 @@ class NSClientPlugin @Inject constructor(
override fun resetToFullSync() { override fun resetToFullSync() {
dataSyncSelector.resetToNextFullSync() dataSyncSelector.resetToNextFullSync()
} }
override fun dbAdd(collection: String, data: JSONObject, originalObject: Any, progress: String) {
nsClientService?.dbAdd(collection, data, originalObject, progress)
}
override fun dbUpdate(collection: String, _id: String?, data: JSONObject?, originalObject: Any, progress: String) {
nsClientService?.dbUpdate(collection, _id, data, originalObject, progress)
}
} }

View file

@ -5,6 +5,7 @@ import info.nightscout.core.extensions.getCustomizedName
import info.nightscout.core.extensions.pureProfileFromJson import info.nightscout.core.extensions.pureProfileFromJson
import info.nightscout.core.profile.ProfileSealed import info.nightscout.core.profile.ProfileSealed
import info.nightscout.database.entities.ProfileSwitch import info.nightscout.database.entities.ProfileSwitch
import info.nightscout.database.entities.TherapyEvent
import info.nightscout.database.entities.embedments.InterfaceIDs import info.nightscout.database.entities.embedments.InterfaceIDs
import info.nightscout.interfaces.plugin.ActivePlugin import info.nightscout.interfaces.plugin.ActivePlugin
import info.nightscout.interfaces.utils.JsonHelper import info.nightscout.interfaces.utils.JsonHelper
@ -23,7 +24,7 @@ fun ProfileSwitch.toJson(isAdd: Boolean, dateUtil: DateUtil): JSONObject =
.put("created_at", dateUtil.toISOString(timestamp)) .put("created_at", dateUtil.toISOString(timestamp))
.put("enteredBy", "openaps://" + "AndroidAPS") .put("enteredBy", "openaps://" + "AndroidAPS")
.put("isValid", isValid) .put("isValid", isValid)
.put("eventType", info.nightscout.database.entities.TherapyEvent.Type.PROFILE_SWITCH.text) .put("eventType", TherapyEvent.Type.PROFILE_SWITCH.text)
.also { // remove customization to store original profileJson in toPureNsJson call .also { // remove customization to store original profileJson in toPureNsJson call
timeshift = 0 timeshift = 0
percentage = 100 percentage = 100

View file

@ -25,7 +25,6 @@ import info.nightscout.interfaces.notifications.Notification
import info.nightscout.interfaces.nsclient.NSAlarm import info.nightscout.interfaces.nsclient.NSAlarm
import info.nightscout.interfaces.nsclient.NSSettingsStatus import info.nightscout.interfaces.nsclient.NSSettingsStatus
import info.nightscout.interfaces.sync.DataSyncSelector import info.nightscout.interfaces.sync.DataSyncSelector
import info.nightscout.interfaces.sync.NsClient
import info.nightscout.interfaces.ui.UiInteraction import info.nightscout.interfaces.ui.UiInteraction
import info.nightscout.interfaces.utils.JsonHelper.safeGetString import info.nightscout.interfaces.utils.JsonHelper.safeGetString
import info.nightscout.interfaces.utils.JsonHelper.safeGetStringAllowNull import info.nightscout.interfaces.utils.JsonHelper.safeGetStringAllowNull
@ -72,7 +71,7 @@ import java.net.URISyntaxException
import java.util.Locale import java.util.Locale
import javax.inject.Inject import javax.inject.Inject
class NSClientService : DaggerService(), NsClient.NSClientService { class NSClientService : DaggerService() {
@Inject lateinit var injector: HasAndroidInjector @Inject lateinit var injector: HasAndroidInjector
@Inject lateinit var aapsLogger: AAPSLogger @Inject lateinit var aapsLogger: AAPSLogger
@ -251,7 +250,7 @@ class NSClientService : DaggerService(), NsClient.NSClientService {
} else if (!nsEnabled) { } else if (!nsEnabled) {
rxBus.send(EventNSClientNewLog("NSCLIENT", "disabled")) rxBus.send(EventNSClientNewLog("NSCLIENT", "disabled"))
rxBus.send(EventNSClientStatus("Disabled")) rxBus.send(EventNSClientStatus("Disabled"))
} else if (nsURL != "" && (config.isEngineeringMode() || nsURL.lowercase(Locale.getDefault()).startsWith("https://"))) { } else if (nsURL != "" && (nsURL.lowercase(Locale.getDefault()).startsWith("https://"))) {
try { try {
rxBus.send(EventNSClientStatus("Connecting ...")) rxBus.send(EventNSClientStatus("Connecting ..."))
val opt = IO.Options() val opt = IO.Options()
@ -598,7 +597,7 @@ class NSClientService : DaggerService(), NsClient.NSClientService {
} }
} }
override fun dbUpdate(collection: String, _id: String?, data: JSONObject?, originalObject: Any, progress: String) { fun dbUpdate(collection: String, _id: String?, data: JSONObject?, originalObject: Any, progress: String) {
try { try {
if (_id == null) return if (_id == null) return
if (!isConnected || !hasWriteAuth) return if (!isConnected || !hasWriteAuth) return
@ -618,7 +617,7 @@ class NSClientService : DaggerService(), NsClient.NSClientService {
} }
} }
override fun dbAdd(collection: String, data: JSONObject, originalObject: Any, progress: String) { fun dbAdd(collection: String, data: JSONObject, originalObject: Any, progress: String) {
try { try {
if (!isConnected || !hasWriteAuth) return if (!isConnected || !hasWriteAuth) return
val message = JSONObject() val message = JSONObject()

View file

@ -26,7 +26,6 @@ import info.nightscout.interfaces.utils.HtmlHelper
import info.nightscout.plugins.sync.R import info.nightscout.plugins.sync.R
import info.nightscout.plugins.sync.nsShared.NSClientFragment import info.nightscout.plugins.sync.nsShared.NSClientFragment
import info.nightscout.plugins.sync.nsShared.events.EventNSClientResend import info.nightscout.plugins.sync.nsShared.events.EventNSClientResend
import info.nightscout.plugins.sync.nsShared.events.EventNSClientStatus
import info.nightscout.plugins.sync.nsShared.events.EventNSClientUpdateGUI import info.nightscout.plugins.sync.nsShared.events.EventNSClientUpdateGUI
import info.nightscout.plugins.sync.nsclient.NsClientReceiverDelegate import info.nightscout.plugins.sync.nsclient.NsClientReceiverDelegate
import info.nightscout.plugins.sync.nsclient.data.AlarmAck import info.nightscout.plugins.sync.nsclient.data.AlarmAck
@ -54,6 +53,7 @@ import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign import io.reactivex.rxjava3.kotlin.plusAssign
import kotlinx.serialization.decodeFromString import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import org.json.JSONObject
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
import kotlin.math.max import kotlin.math.max
@ -87,21 +87,30 @@ class NSClientV3Plugin @Inject constructor(
companion object { companion object {
val JOB_NAME: String = this::class.java.simpleName val JOB_NAME: String = this::class.java.simpleName
val REFRESH_INTERVAL = T.mins(5).msecs()
} }
private val disposable = CompositeDisposable() private val disposable = CompositeDisposable()
private lateinit var runLoop: Runnable
private val handler = Handler(HandlerThread(this::class.simpleName + "Handler").also { it.start() }.looper) private val handler = Handler(HandlerThread(this::class.simpleName + "Handler").also { it.start() }.looper)
private val listLog: MutableList<EventNSClientNewLog> = ArrayList() private val listLog: MutableList<EventNSClientNewLog> = ArrayList()
override var status = "" override val status
override val nsClientService: NSClientService? = null // service not needed get() =
when {
sp.getBoolean(R.string.key_ns_client_paused, false) -> rh.gs(info.nightscout.core.ui.R.string.paused)
isAllowed.not() -> blockingReason
nsAndroidClient.lastStatus == null -> rh.gs(R.string.not_connected)
workIsRunning(arrayOf(JOB_NAME)) -> rh.gs(R.string.working)
nsAndroidClient.lastStatus?.apiPermissions?.isFull() == true -> rh.gs(info.nightscout.shared.R.string.connected)
nsAndroidClient.lastStatus?.apiPermissions?.isRead() == true -> rh.gs(R.string.read_only)
else -> rh.gs(info.nightscout.core.ui.R.string.unknown)
}
internal lateinit var nsAndroidClient: NSAndroidClient internal lateinit var nsAndroidClient: NSAndroidClient
// private lateinit var nsAndroidRxClient: NSAndroidRxClient // private lateinit var nsAndroidRxClient: NSAndroidRxClient
val isAllowed: Boolean val isAllowed get() = nsClientReceiverDelegate.allowed
get() = nsClientReceiverDelegate.allowed val blockingReason get() = nsClientReceiverDelegate.blockingReason
val blockingReason: String
get() = nsClientReceiverDelegate.blockingReason
private val maxAge = T.days(77).msecs() private val maxAge = T.days(77).msecs()
internal var lastModified: LastModified? = null // timestamp of last modification for every collection internal var lastModified: LastModified? = null // timestamp of last modification for every collection
@ -133,31 +142,24 @@ class NSClientV3Plugin @Inject constructor(
lastFetched.collections.profile = max(dateUtil.now() - maxAge, lastFetched.collections.profile) lastFetched.collections.profile = max(dateUtil.now() - maxAge, lastFetched.collections.profile)
lastFetched.collections.devicestatus = max(dateUtil.now() - maxAge, lastFetched.collections.devicestatus) lastFetched.collections.devicestatus = max(dateUtil.now() - maxAge, lastFetched.collections.devicestatus)
nsAndroidClient = NSAndroidClientImpl( setClient()
baseUrl = sp.getString(info.nightscout.core.utils.R.string.key_nsclientinternal_url, "").lowercase().replace("https://", ""),
accessToken = sp.getString(R.string.key_ns_client_token, ""),
context = context,
logging = true
)
nsClientReceiverDelegate.grabReceiversState() nsClientReceiverDelegate.grabReceiversState()
disposable += rxBus
.toObservable(EventNSClientStatus::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({ event ->
status = event.getStatus(context)
rxBus.send(EventNSClientUpdateGUI())
// Pass to setup wizard
rxBus.send(EventSWSyncStatus(event.getStatus(context)))
}, fabricPrivacy::logException)
disposable += rxBus disposable += rxBus
.toObservable(EventNetworkChange::class.java) .toObservable(EventNetworkChange::class.java)
.observeOn(aapsSchedulers.io) .observeOn(aapsSchedulers.io)
.subscribe({ ev -> nsClientReceiverDelegate.onStatusEvent(ev) }, fabricPrivacy::logException) .subscribe({ ev ->
nsClientReceiverDelegate.onStatusEvent(ev)
setClient()
}, fabricPrivacy::logException)
disposable += rxBus disposable += rxBus
.toObservable(EventPreferenceChange::class.java) .toObservable(EventPreferenceChange::class.java)
.observeOn(aapsSchedulers.io) .observeOn(aapsSchedulers.io)
.subscribe({ ev -> nsClientReceiverDelegate.onStatusEvent(ev) }, fabricPrivacy::logException) .subscribe({ ev ->
nsClientReceiverDelegate.onStatusEvent(ev)
if (ev.isChanged(rh.gs(R.string.key_ns_client_token)) || ev.isChanged(rh.gs(info.nightscout.core.utils.R.string.key_nsclientinternal_url)))
setClient()
}, fabricPrivacy::logException)
// disposable += rxBus // disposable += rxBus
// .toObservable(EventAppExit::class.java) // .toObservable(EventAppExit::class.java)
// .observeOn(aapsSchedulers.io) // .observeOn(aapsSchedulers.io)
@ -177,10 +179,18 @@ class NSClientV3Plugin @Inject constructor(
.toObservable(EventNSClientResend::class.java) .toObservable(EventNSClientResend::class.java)
.observeOn(aapsSchedulers.io) .observeOn(aapsSchedulers.io)
.subscribe({ event -> resend(event.reason) }, fabricPrivacy::logException) .subscribe({ event -> resend(event.reason) }, fabricPrivacy::logException)
runLoop = Runnable {
executeLoop()
handler.postDelayed(runLoop, REFRESH_INTERVAL)
}
handler.postDelayed(runLoop, REFRESH_INTERVAL)
executeLoop()
} }
override fun onStop() { override fun onStop() {
// context.applicationContext.unbindService(mConnection) // context.applicationContext.unbindService(mConnection)
handler.removeCallbacksAndMessages(null)
disposable.clear() disposable.clear()
super.onStop() super.onStop()
} }
@ -196,8 +206,8 @@ class NSClientV3Plugin @Inject constructor(
preferenceFragment.findPreference<SwitchPreference>(rh.gs(R.string.key_ns_receive_tbr_eb))?.isVisible = config.isEngineeringMode() preferenceFragment.findPreference<SwitchPreference>(rh.gs(R.string.key_ns_receive_tbr_eb))?.isVisible = config.isEngineeringMode()
} }
override val hasWritePermission: Boolean get() = nsClientService?.hasWriteAuth ?: false override val hasWritePermission: Boolean get() = nsAndroidClient.lastStatus?.apiPermissions?.isFull() ?: false
override val connected: Boolean get() = nsClientService?.isConnected ?: false override val connected: Boolean get() = nsAndroidClient.lastStatus != null
override fun clearLog() { override fun clearLog() {
handler.post { handler.post {
@ -206,6 +216,16 @@ class NSClientV3Plugin @Inject constructor(
} }
} }
private fun setClient() {
nsAndroidClient = NSAndroidClientImpl(
baseUrl = sp.getString(info.nightscout.core.utils.R.string.key_nsclientinternal_url, "").lowercase().replace("https://", ""),
accessToken = sp.getString(R.string.key_ns_client_token, ""),
context = context,
logging = true
)
rxBus.send(EventSWSyncStatus(status))
}
private fun addToLog(ev: EventNSClientNewLog) { private fun addToLog(ev: EventNSClientNewLog) {
synchronized(listLog) { synchronized(listLog) {
listLog.add(ev) listLog.add(ev)
@ -231,7 +251,7 @@ class NSClientV3Plugin @Inject constructor(
} }
override fun resend(reason: String) { override fun resend(reason: String) {
nsClientService?.resend(reason) // nsClientService?.resend(reason)
} }
override fun pause(newState: Boolean) { override fun pause(newState: Boolean) {
@ -239,8 +259,7 @@ class NSClientV3Plugin @Inject constructor(
rxBus.send(EventPreferenceChange(rh.gs(R.string.key_ns_client_paused))) rxBus.send(EventPreferenceChange(rh.gs(R.string.key_ns_client_paused)))
} }
override val version: NsClient.Version override val version: NsClient.Version get() = NsClient.Version.V3
get() = NsClient.Version.V3
override val address: String get() = sp.getString(info.nightscout.core.utils.R.string.key_nsclientinternal_url, "") override val address: String get() = sp.getString(info.nightscout.core.utils.R.string.key_nsclientinternal_url, "")
@ -250,12 +269,12 @@ class NSClientV3Plugin @Inject constructor(
aapsLogger.debug(LTag.NSCLIENT, "Upload disabled. Message dropped") aapsLogger.debug(LTag.NSCLIENT, "Upload disabled. Message dropped")
return return
} }
nsClientService?.sendAlarmAck( // nsClientService?.sendAlarmAck(
AlarmAck().also { ack -> // AlarmAck().also { ack ->
ack.level = originalAlarm.level() // ack.level = originalAlarm.level()
ack.group = originalAlarm.group() // ack.group = originalAlarm.group()
ack.silenceTime = silenceTimeInMilliseconds // ack.silenceTime = silenceTimeInMilliseconds
}) // })
} }
override fun updateLatestBgReceivedIfNewer(latestReceived: Long) { override fun updateLatestBgReceivedIfNewer(latestReceived: Long) {
@ -282,11 +301,39 @@ class NSClientV3Plugin @Inject constructor(
storeLastFetched() storeLastFetched()
} }
override fun dbAdd(collection: String, data: JSONObject, originalObject: Any, progress: String) {
TODO("Not yet implemented")
}
override fun dbUpdate(collection: String, _id: String?, data: JSONObject?, originalObject: Any, progress: String) {
TODO("Not yet implemented")
}
private fun storeLastFetched() { private fun storeLastFetched() {
sp.putString(R.string.key_ns_client_v3_last_modified, Json.encodeToString(LastModified.serializer(), lastFetched)) sp.putString(R.string.key_ns_client_v3_last_modified, Json.encodeToString(LastModified.serializer(), lastFetched))
} }
fun test() { fun test() {
executeLoop()
}
fun scheduleNewExecution() {
val toTime = lastFetched.collections.entries + T.mins(6).plus(T.secs(0)).msecs()
if (toTime > dateUtil.now()) {
handler.postDelayed({ executeLoop() }, toTime - dateUtil.now())
rxBus.send(EventNSClientNewLog("NEXT", dateUtil.dateAndTimeAndSecondsString(toTime)))
}
}
private fun executeLoop() {
if (sp.getBoolean(R.string.key_ns_client_paused, false)) {
rxBus.send(EventNSClientNewLog("NSCLIENT", "paused"))
return
}
if (!isAllowed) {
rxBus.send(EventNSClientNewLog("NSCLIENT", blockingReason))
return
}
if (workIsRunning(arrayOf(JOB_NAME))) if (workIsRunning(arrayOf(JOB_NAME)))
rxBus.send(EventNSClientNewLog("RUN", "Already running")) rxBus.send(EventNSClientNewLog("RUN", "Already running"))
else { else {

View file

@ -11,6 +11,6 @@ fun NSExtendedBolus.toExtendedBolus(): ExtendedBolus =
utcOffset = utcOffset, utcOffset = utcOffset,
amount = enteredinsulin, amount = enteredinsulin,
duration = duration, duration = duration,
isEmulatingTempBasal = isEmulatingTempbasal, isEmulatingTempBasal = isEmulatingTempBasal ?: false,
interfaceIDs_backing = InterfaceIDs(nightscoutId = identifier, pumpId = pumpId, pumpType = InterfaceIDs.PumpType.fromString(pumpType), pumpSerial = pumpSerial, endId = endId) interfaceIDs_backing = InterfaceIDs(nightscoutId = identifier, pumpId = pumpId, pumpType = InterfaceIDs.PumpType.fromString(pumpType), pumpSerial = pumpSerial, endId = endId)
) )

View file

@ -76,6 +76,7 @@ class LoadBgWorker(
} }
else { else {
rxBus.send(EventNSClientNewLog("END", "No new SGVs from ${dateUtil.dateAndTimeAndSecondsString(nsClientV3Plugin.lastFetched.collections.entries)}")) rxBus.send(EventNSClientNewLog("END", "No new SGVs from ${dateUtil.dateAndTimeAndSecondsString(nsClientV3Plugin.lastFetched.collections.entries)}"))
nsClientV3Plugin.scheduleNewExecution() // Idea is to run after 5 min after last BG
WorkManager.getInstance(context) WorkManager.getInstance(context)
.beginUniqueWork( .beginUniqueWork(
NSClientV3Plugin.JOB_NAME, NSClientV3Plugin.JOB_NAME,

View file

@ -97,4 +97,7 @@
<string name="remove_all">Odstranit vše</string> <string name="remove_all">Odstranit vše</string>
<string name="reset_start">Resetovat start</string> <string name="reset_start">Resetovat start</string>
<string name="upload_now">Nahrát nyní</string> <string name="upload_now">Nahrát nyní</string>
<string name="not_connected">Nepřipojeno</string>
<string name="read_only">Jen pro čtení</string>
<string name="working">Pracuji</string>
</resources> </resources>

View file

@ -97,4 +97,7 @@
<string name="remove_all">Eliminar todos</string> <string name="remove_all">Eliminar todos</string>
<string name="reset_start">Restablecer inicio</string> <string name="reset_start">Restablecer inicio</string>
<string name="upload_now">Subir ahora</string> <string name="upload_now">Subir ahora</string>
<string name="not_connected">No conectado</string>
<string name="read_only">Sólo lectura</string>
<string name="working">Funcionando</string>
</resources> </resources>

View file

@ -97,4 +97,7 @@
<string name="remove_all">Supprimer tout</string> <string name="remove_all">Supprimer tout</string>
<string name="reset_start">Réinitialiser le démarrage</string> <string name="reset_start">Réinitialiser le démarrage</string>
<string name="upload_now">Télécharger maintenant</string> <string name="upload_now">Télécharger maintenant</string>
<string name="not_connected">Non connecté</string>
<string name="read_only">Lecture seule</string>
<string name="working">Opération en cours</string>
</resources> </resources>

View file

@ -97,4 +97,7 @@
<string name="remove_all">Удалить всё</string> <string name="remove_all">Удалить всё</string>
<string name="reset_start">Перезапустить старт</string> <string name="reset_start">Перезапустить старт</string>
<string name="upload_now">Выгрузить (передать данные) сейчас</string> <string name="upload_now">Выгрузить (передать данные) сейчас</string>
<string name="not_connected">Нет подключения</string>
<string name="read_only">Только чтение</string>
<string name="working">Обработка</string>
</resources> </resources>

View file

@ -143,4 +143,8 @@
<string name="reset_start">Reset start</string> <string name="reset_start">Reset start</string>
<string name="upload_now">Upload now</string> <string name="upload_now">Upload now</string>
<string name="not_connected">Not connected</string>
<string name="read_only">Read only</string>
<string name="working">Working</string>
</resources> </resources>

View file

@ -1,4 +1,4 @@
package info.nightscout.androidaps.danars.di package info.nightscout.pump.combo.di
import dagger.Module import dagger.Module
import dagger.android.ContributesAndroidInjector import dagger.android.ContributesAndroidInjector

View file

@ -1,7 +1,6 @@
package info.nightscout.pump.combo.di package info.nightscout.pump.combo.di
import dagger.Module import dagger.Module
import info.nightscout.androidaps.danars.di.ComboActivitiesModule
@Module(includes = [ @Module(includes = [
ComboActivitiesModule::class ComboActivitiesModule::class

153
pump/combov2/README.md Normal file
View file

@ -0,0 +1,153 @@
# Overview over combov2's and ComboCtl's architecture
ComboCtl is the core driver. It uses Kotlin Multiplatform and is written in a platform agnostic
way. The code is located in `comboctl/`, and is also available in [its own separate repository]
(https://github.com/dv1/ComboCtl). That separate repository is kept in sync with the ComboCtl
copy in AndroidAPS as much as possible, with some notable changes (see below). "combov2" is the
name of the AndroidAPS driver. In short: combov2 = ComboCtl + extra AndroidAPS integration code.
## Directory structure
The directory structure of the local ComboCtl itself is:
* `comboctl/src/commonMain/` : The platform agnostic portion of ComboCtl. The vast majority of
ComboCtl's logic is contained there.
* `comboctl/src/androidMain/` : The Android specific code. This in particular contains
implementations of the Bluetooth interfaces that are defined in `commonMain/`.
* `comboctl/src/jvmTest/` : Unit tests. This subdirectory is called `jvmTest` because in the
ComboCtl repository, there is also a `jvmMain/` subdirectory, and the unit tests are run
with the JVM.
The AndroidAPS specific portion of the driver is located in `src/`. This connects ComboCtl with
AndroidAPS. In particular, this is where the `ComboV2Plugin` class is located. That's the main
entrypoint for the combov2 driver plugin.
## Basic description of how ComboCtl communicates with the pump
ComboCtl uses Kotlin coroutines. It uses [the Default dispatcher](https://kotlinlang.
org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-dispatchers/-default.html),
with [a limitedParallelism](https://kotlinlang.org/api/kotlinx.
coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-dispatcher/limited-parallelism.html)
constraint to prevent actual parallelism, that is, to not let coroutine jobs run on multiple
threads concurrently. Coroutines are used in ComboCtl to greatly simplify the communication steps,
which normally require a number of state machines to be implemented manually. Stackless coroutines
like Kotlin's essentially are automatically generated state machines under the hood, and this is
what they are used for here. Enabling parallelism is not part of such a state machine. Furthermore,
communication with the Combo does not benefit from parallelism.
The communication code in ComboCtl is split in higher level operations (in its `Pump` class) and
lower level ones (in its `PumpIO` class). `Pump` instantiates `PumpIO` internally, and focuses on
implementing functionality like reading basal profiles, setting TBRs etc. `PumpIO` implements the
building blocks for these higher level operations. In particular, `PumpIO` has an internal
coroutine scope that is used for sending data to the Combo and for running a "heartbeat" loop.
That "heartbeat" is a message that needs to be regularly sent to the Combo (unless other data is
sent to the Combo in time, like a command to press a button). If nothing is sent to a Combo for
some time, it will eventually disconnect. For this reason, that heartbeat loop is necessary.
PumpIO also contains the code for performing the pump pairing.
Going further down a level, `TransportLayer` implements the IO code to generate packets for the
Combo and parse packets coming from the Combo. This includes code for authenticating outgoing
packets and for checking incoming ones. `TransportLayer` also contains the `IO` subclass, which
actually transfers packets to and receives data from the Combo.
One important detail to keep in mind about the `IO` class is that it enforces a packet send
interval of 200 ms. That is: The time between packet transmission is never shorter than 200 ms
(it is OK to be longer). The interval is important, because the Combo has a ring buffer for the
packet it receives, and transmitting packets to the Combo too quickly causes an overflow and a
subsequent error in the Combo, which then terminates the connection.
The Combo can run in three modes. The first one is the "service" mode, which is only briefly
used for setting up the connection. Immediately after the connection is established, the pump
continues in the "command" or "remote terminal" (abbr. "RT") mode. The "command" mode is what the
remote control of the Combo uses for its direct commands (that is, delivering bolus and retrieving
the latest changes / activities from the history). The "remote terminal" mode replicates the LCD
on the pump itself along with the 4 Combo buttons.
Only a few operations are possible in the command mode. In particular, the driver uses the bolus
delivery command from the command mode, the command to retrieve a history delta, and the command
for getting the pump's current date and time. But everything else (getting basal profile, setting
TBR, getting pump status...) is done in the remote terminal mode, by emulating a user pressing
buttons. This unfortunately means that these operations are performed slowly, but there is no
other choice.
## Details about long-pressing RT buttons
As part of operations like reading the pump's profile, an emulated long RT button press is sometimes
used. Such long presses cause more rapid changes compared to multiple short button presses. A
button press is "long" when the emulated user "holds down" the button, while a short button press
equals pressing and immediately releasing the emulated button.
The greater speed of long button presses comes with a drawback though: "Overshoots" can happen. For
example, if long button pressing is used for adjusting a quantity on screen, then the quantity may
still get incremented/decremented after the emulated user "released" the button. It is therefore
necessary to check the quantity on screen, and finetune it with short button presses afterwards
if necessary.
## Idempotent and non-idempotent high level commands
A command is _idempotent_ if it can be repeated if the connection to the pump was lost. Most
commands are idempotent. For example, reading the basal profile can be repeated if during the
initial basal profile retrieval the connection was lost (for example because the user walked away
from the pump). After a few attempts to repeat the command, an error is produced (to avoid an
infinite loop).
Currently, there is only one non-idempotent command: Delivering a bolus. This one _cannot_ be
repeated, otherwise there is a high risk of infusing too much insulin. Instead, in case of a
connection failure, the delivering bolus command fails immediately and is not automatically
attempted again.
## Automatic datetime adjustments and timezone offset handling
ComboCtl automatically adjusts the date and time of the Combo. This is done through the RT mode,
since there is no command-mode command to _set_ the current datetime (but there is one for
_getting_ the current datetime). But since the Combo cannot store a timezone offset (it only stores
localtime), the timezone offset that has been used so far is stored in a dedicated field in the
pump state store that ComboCtl uses. DST changes and timezone changes can be tracked properly with
this logic.
The pump's current datetime is always retrieved (through the command mode) every time a connection
is established to it, and compared to the system's current datetime. If these two differ too much,
the pump's datetime is automatically adjusted. This keeps the pump's datetime in sync.
## Notes about how TBRs are set
TBRs are set through the remote terminal mode. The driver assumes that the Combo is configured
to use 15-minute TBR duration steps sizes and a TBR percentage maximum of 500%. There is code
in the driver to detect if the maximum is not set to 500%. If AndroidAPS tries to set a percentage
that is higher than the actually configured maximum, then eventually, an error is reported.
:warning: The duration step size cannot be detected by the driver. The user _must_ make sure that
the step size is configured to 15 minutes.
## Pairing with a Combo and the issue with pump queue connection timeouts
When pairing, the pump queue's internal timeout is likely to be reached. Essentially, the queue
tries to connect to the pump right after the driver was selected in the configuration. But
a connection cannot be established because the pump is not yet paired.
When the queue attempts to connect to the pump, it "thinks" that if the connect procedure does not
complete after 120 seconds, then the driver must be stuck somehow. The queue then hits a timeout.
The assumption about 120s is correct if the Combo is already paired (a connection should be set up
in far less time than 120s). But if it is currently being paired, the steps involved can take
about 2-3 minutes.
For this reason, the driver automatically requests a pump update - which connects to the pump -
once pairing is done.
## Changes to ComboCtl in the local copy
The code in `comboctl/` is ComboCtl minus the `jvmMain/` code, which contains code for the Linux
platform. This includes C++ glue code to the BlueZ stack. Since none of this is useful to
AndroidAPS, it is better left out, especially since it consists of almost 9000 lines of code.
Also, the original `comboctl/build.gradle.kts` files is replaced by `comboctl/build.gradle`, which
is much simpler, and builds ComboCtl as a kotlin-android project, not a Kotlin Multiplatform one.
This simplifies integration into AndroidAPS, and avoids multiplatform problems (after all,
Kotlin Multiplatform is still marked as an alpha version feature).
When updating ComboCtl, it is important to keep these differences in mind.
Differences between the copy in `comboctl/` and the original ComboCtl code must be kept as little
as possible, and preferably be transferred to the main ComboCtl project. This helps with keeping the
`comboctl/` copy and the main project in sync since transferring changes then is straightforward.

View file

@ -1,14 +0,0 @@
The code in comboctl/ is ComboCtl minus the jvmMain/ code, which contains code for the Linux platform.
This includes C++ glue code to the BlueZ stack. Since none of this is useful to AndroidAPS, it is better
left out, especially since it consists of almost 9000 lines of code.
Also, the original comboctl/build.gradle.kts files is replaced by comboctl/build.gradle, which is
much simpler, and builds ComboCtl as a kotlin-android project, not a kotlin-multiplatform one.
This simplifies integration into AndroidAPS, and avoids multiplatform problems (after all,
Kotlin Multiplatform is still marked as an alpha version feature).
When updating ComboCtl, it is important to keep these differences in mind.
Differences between the copy in comboctl/ and the original ComboCtl code must be kept as little as
possible, and preferably be transferred to the main ComboCtl project. This helps keep the comboctl/
copy and the main project in sync.

View file

@ -67,8 +67,9 @@ class AndroidBluetoothDevice(
// just yet (for example because the UI is still shown on the LCD), while // just yet (for example because the UI is still shown on the LCD), while
// the retryBlocking loop here is in place because the _Android device_ // the retryBlocking loop here is in place because the _Android device_
// may not be ready to connect right away. // may not be ready to connect right away.
// TODO: Test and define what happens when all attempts failed. // When all attempts fail, retryBlocking() lets the exception pass through.
// The user needs to be informed and given the choice to try again. // That exception is wrapped in BluetoothException, which then needs to be
// handled by the caller.
val totalNumAttempts = 5 val totalNumAttempts = 5
retryBlocking(numberOfRetries = totalNumAttempts, delayBetweenRetries = 100) { attemptNumber, previousException -> retryBlocking(numberOfRetries = totalNumAttempts, delayBetweenRetries = 100) { attemptNumber, previousException ->
if (abortConnectAttempt) if (abortConnectAttempt)

View file

@ -381,13 +381,6 @@ class AndroidBluetoothInterface(private val androidContext: Context) : Bluetooth
// instance was already processed. This check here instead // instance was already processed. This check here instead
// verifies if we have seen the same Bluetooth address on // verifies if we have seen the same Bluetooth address on
// *different* Android Bluetooth device instances. // *different* Android Bluetooth device instances.
// TODO: Test how AndroidBluetoothInterface behaves if the
// device is unpaired while discovery is ongoing (manually by
// the user for example). In theory, this should be handled
// properly by the onBondStateChanged function below.
// TODO: This check may not be necessary on all Android
// devices. On some, it seems to also work if we use the
// first offered BluetoothDevice.
if (comboctlBtAddress !in previouslyDiscoveredDevices) { if (comboctlBtAddress !in previouslyDiscoveredDevices) {
previouslyDiscoveredDevices[comboctlBtAddress] = androidBtDevice previouslyDiscoveredDevices[comboctlBtAddress] = androidBtDevice
logger(LogLevel.DEBUG) { logger(LogLevel.DEBUG) {

View file

@ -2743,8 +2743,6 @@ class Pump(
) )
} }
numObservedScreens++
val factorIndexOnScreen = parsedScreen.beginTime.hour val factorIndexOnScreen = parsedScreen.beginTime.hour
// numUnits null means the basal profile factor // numUnits null means the basal profile factor
@ -2752,6 +2750,11 @@ class Pump(
if (parsedScreen.numUnits == null) if (parsedScreen.numUnits == null)
return@longPressRTButtonUntil LongPressRTButtonsCommand.ContinuePressingButton return@longPressRTButtonUntil LongPressRTButtonsCommand.ContinuePressingButton
// Increase this _after_ checking for a blinking screen
// to not accidentally count the blinking and non-blinking
// screens as two separate ones.
numObservedScreens++
// If the factor in the profile is >= 0, // If the factor in the profile is >= 0,
// it means it was already read earlier. // it means it was already read earlier.
if (basalProfileFactors[factorIndexOnScreen] >= 0) if (basalProfileFactors[factorIndexOnScreen] >= 0)
@ -2759,14 +2762,16 @@ class Pump(
val factor = parsedScreen.numUnits val factor = parsedScreen.numUnits
basalProfileFactors[factorIndexOnScreen] = factor basalProfileFactors[factorIndexOnScreen] = factor
logger(LogLevel.DEBUG) { "Got basal profile factor #$factorIndexOnScreen : $factor" }
numRetrievedFactors++
logger(LogLevel.DEBUG) {
"Got basal profile factor #$factorIndexOnScreen : $factor; $numRetrievedFactors factor(s) read and $numObservedScreens screen(s) observed thus far"
}
getBasalProfileReporter.setCurrentProgressStage( getBasalProfileReporter.setCurrentProgressStage(
RTCommandProgressStage.GettingBasalProfile(numRetrievedFactors) RTCommandProgressStage.GettingBasalProfile(numRetrievedFactors)
) )
numRetrievedFactors++
return@longPressRTButtonUntil if (numObservedScreens >= NUM_COMBO_BASAL_PROFILE_FACTORS) return@longPressRTButtonUntil if (numObservedScreens >= NUM_COMBO_BASAL_PROFILE_FACTORS)
LongPressRTButtonsCommand.ReleaseButton LongPressRTButtonsCommand.ReleaseButton
else else
@ -2819,21 +2824,19 @@ class Pump(
} }
} }
numRetrievedFactors++
getBasalProfileReporter.setCurrentProgressStage( getBasalProfileReporter.setCurrentProgressStage(
RTCommandProgressStage.GettingBasalProfile(numRetrievedFactors) RTCommandProgressStage.GettingBasalProfile(numRetrievedFactors)
) )
numRetrievedFactors++
} }
} }
// All factors retrieved. Press CHECK once to get back to the total // All factors retrieved. Press BACK repeatedly until we are back at the main menu.
// basal rate screen, and then CHECK again to return to the main menu. cycleToRTScreen(
rtNavigationContext,
rtNavigationContext.shortPressButton(RTNavigationButton.CHECK) RTNavigationButton.BACK,
waitUntilScreenAppears(rtNavigationContext, ParsedScreen.BasalRateTotalScreen::class) ParsedScreen.MainScreen::class
)
rtNavigationContext.shortPressButton(RTNavigationButton.CHECK)
waitUntilScreenAppears(rtNavigationContext, ParsedScreen.MainScreen::class)
getBasalProfileReporter.setCurrentProgressStage(BasicProgressStage.Finished) getBasalProfileReporter.setCurrentProgressStage(BasicProgressStage.Finished)

View file

@ -85,6 +85,9 @@
<string name="combov2_reservoir_low_warning">Niveau réservoir pompe bas</string> <string name="combov2_reservoir_low_warning">Niveau réservoir pompe bas</string>
<string name="combov2_setting_tbr_succeeded">Paramétrage du DBT réussi</string> <string name="combov2_setting_tbr_succeeded">Paramétrage du DBT réussi</string>
<string name="combov2_setting_tbr_failed">Échec du réglage du DBT</string> <string name="combov2_setting_tbr_failed">Échec du réglage du DBT</string>
<string name="combov2_set_emulated_100_tbr">Définir l\'émulation 100% TBR</string>
<string name="combov2_letting_emulated_100_tbr_finish">Laisser se terminer l\'émulation 100% TBR en cours</string>
<string name="combov2_ignoring_redundant_100_tbr">Requête 100% DBT redondante ignorée</string>
<string name="combov2_hit_unexpected_tbr_limit">Limite inattendue lors de lajustement du DBT: le pourcentage cible de %1$d%%, a dépassé la limite de %1$d%%</string> <string name="combov2_hit_unexpected_tbr_limit">Limite inattendue lors de lajustement du DBT: le pourcentage cible de %1$d%%, a dépassé la limite de %1$d%%</string>
<string name="combov2_cannot_set_absolute_tbr_if_basal_zero">Impossible de définir le DBT absolu si le débit de basal est zéro</string> <string name="combov2_cannot_set_absolute_tbr_if_basal_zero">Impossible de définir le DBT absolu si le débit de basal est zéro</string>
<string name="combov2_pair_with_pump_summary">Appairer AndroidAPS et Android avec une pompe Accu-Chek Combo non appariée</string> <string name="combov2_pair_with_pump_summary">Appairer AndroidAPS et Android avec une pompe Accu-Chek Combo non appariée</string>

View file

@ -95,6 +95,9 @@
<string name="combov2_reservoir_low_warning">Низкий уровень инсулина в картридже помпы</string> <string name="combov2_reservoir_low_warning">Низкий уровень инсулина в картридже помпы</string>
<string name="combov2_setting_tbr_succeeded">Настройки TBR выполнены</string> <string name="combov2_setting_tbr_succeeded">Настройки TBR выполнены</string>
<string name="combov2_setting_tbr_failed">Не удалось установить TBR</string> <string name="combov2_setting_tbr_failed">Не удалось установить TBR</string>
<string name="combov2_set_emulated_100_tbr">Установить эмуляцию. временного базала TBR 100%</string>
<string name="combov2_letting_emulated_100_tbr_finish">Позволить завершиться текущей эмуляции временного базала 100% TBR</string>
<string name="combov2_ignoring_redundant_100_tbr">Игнорирование избыточного запроса на 100% TBR</string>
<string name="combov2_hit_unexpected_tbr_limit">Непредвиденный предел, встретившийся при настройке TBR: целевой процент составил %1$d%%, а достиг предела %1$d%%</string> <string name="combov2_hit_unexpected_tbr_limit">Непредвиденный предел, встретившийся при настройке TBR: целевой процент составил %1$d%%, а достиг предела %1$d%%</string>
<string name="combov2_cannot_set_absolute_tbr_if_basal_zero">Невозможно установить абсолютный TBR, если базовая скорость равна нулю</string> <string name="combov2_cannot_set_absolute_tbr_if_basal_zero">Невозможно установить абсолютный TBR, если базовая скорость равна нулю</string>
<string name="combov2_pair_with_pump_summary">Выполнить сопряжение AndroidAPS и Android с помпой Accu-Chek Combo</string> <string name="combov2_pair_with_pump_summary">Выполнить сопряжение AndroidAPS и Android с помпой Accu-Chek Combo</string>

View file

@ -55,7 +55,7 @@ class DanaPump @Inject constructor(
var lastConnection: Long = 0 var lastConnection: Long = 0
var lastSettingsRead: Long = 0 var lastSettingsRead: Long = 0
@JvmField var lastHistoryFetched: Long = 0 @JvmField var readHistoryFrom: Long = 0 // start next history read from this timestamp
@JvmField var historyDoneReceived: Boolean = false // true when last history message is received @JvmField var historyDoneReceived: Boolean = false // true when last history message is received
// Info // Info
@ -410,7 +410,7 @@ class DanaPump @Inject constructor(
aapsLogger.debug(LTag.PUMP, "DanaRPump reset") aapsLogger.debug(LTag.PUMP, "DanaRPump reset")
lastConnection = 0 lastConnection = 0
lastSettingsRead = 0 lastSettingsRead = 0
lastHistoryFetched = 0 readHistoryFrom = 0
} }
fun modelFriendlyName(): String = fun modelFriendlyName(): String =

View file

@ -57,8 +57,6 @@ public class DanaRv2Plugin extends AbstractDanaRPlugin {
private final TemporaryBasalStorage temporaryBasalStorage; private final TemporaryBasalStorage temporaryBasalStorage;
private final FabricPrivacy fabricPrivacy; private final FabricPrivacy fabricPrivacy;
public long lastEventTimeLoaded = 0;
@Inject @Inject
public DanaRv2Plugin( public DanaRv2Plugin(
HasAndroidInjector injector, HasAndroidInjector injector,
@ -345,7 +343,7 @@ public class DanaRv2Plugin extends AbstractDanaRPlugin {
PumpEnactResult result = new PumpEnactResult(getInjector()); PumpEnactResult result = new PumpEnactResult(getInjector());
if (danaPump.isTempBasalInProgress()) { if (danaPump.isTempBasalInProgress()) {
sExecutionService.tempBasalStop(); sExecutionService.tempBasalStop();
result.enacted(true).isTempCancel(true); result.success(true).enacted(true).isTempCancel(true);
} else { } else {
result.success(true).isTempCancel(true).comment(info.nightscout.core.ui.R.string.ok); result.success(true).isTempCancel(true).comment(info.nightscout.core.ui.R.string.ok);
aapsLogger.debug(LTag.PUMP, "cancelRealTempBasal: OK"); aapsLogger.debug(LTag.PUMP, "cancelRealTempBasal: OK");

View file

@ -346,7 +346,7 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService {
MsgSetHistoryEntry_v2 msgSetHistoryEntry_v2 = new MsgSetHistoryEntry_v2(injector, MsgSetHistoryEntry_v2 msgSetHistoryEntry_v2 = new MsgSetHistoryEntry_v2(injector,
DanaPump.HistoryEntry.CARBS.getValue(), carbtime, carbs, 0); DanaPump.HistoryEntry.CARBS.getValue(), carbtime, carbs, 0);
mSerialIOThread.sendMessage(msgSetHistoryEntry_v2); mSerialIOThread.sendMessage(msgSetHistoryEntry_v2);
danaPump.lastHistoryFetched = Math.min(danaPump.lastHistoryFetched, carbtime - T.Companion.mins(1).msecs()); danaPump.readHistoryFrom = Math.min(danaPump.readHistoryFrom, carbtime - T.Companion.mins(1).msecs());
if (!msgSetHistoryEntry_v2.isReceived() || msgSetHistoryEntry_v2.getFailed()) if (!msgSetHistoryEntry_v2.isReceived() || msgSetHistoryEntry_v2.getFailed())
uiInteraction.runAlarm(rh.gs(info.nightscout.pump.dana.R.string.carbs_store_error), rh.gs(info.nightscout.core.ui.R.string.error), info.nightscout.core.ui.R.raw.boluserror); uiInteraction.runAlarm(rh.gs(info.nightscout.pump.dana.R.string.carbs_store_error), rh.gs(info.nightscout.core.ui.R.string.error), info.nightscout.core.ui.R.raw.boluserror);
} }
@ -418,7 +418,7 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService {
MsgSetHistoryEntry_v2 msgSetHistoryEntry_v2 = new MsgSetHistoryEntry_v2(injector, MsgSetHistoryEntry_v2 msgSetHistoryEntry_v2 = new MsgSetHistoryEntry_v2(injector,
DanaPump.HistoryEntry.CARBS.getValue(), time, amount, 0); DanaPump.HistoryEntry.CARBS.getValue(), time, amount, 0);
mSerialIOThread.sendMessage(msgSetHistoryEntry_v2); mSerialIOThread.sendMessage(msgSetHistoryEntry_v2);
danaPump.lastHistoryFetched = Math.min(danaPump.lastHistoryFetched, time - T.Companion.mins(1).msecs()); danaPump.readHistoryFrom = Math.min(danaPump.readHistoryFrom, time - T.Companion.mins(1).msecs());
return true; return true;
} }
@ -433,18 +433,17 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService {
if (!isConnected()) if (!isConnected())
return new PumpEnactResult(injector).success(false); return new PumpEnactResult(injector).success(false);
SystemClock.sleep(300); SystemClock.sleep(300);
MsgHistoryEventsV2 msg = new MsgHistoryEventsV2(injector, danaPump.lastHistoryFetched); MsgHistoryEventsV2 msg = new MsgHistoryEventsV2(injector, danaPump.readHistoryFrom);
aapsLogger.debug(LTag.PUMP, "Loading event history from: " + dateUtil.dateAndTimeString(danaPump.lastHistoryFetched)); aapsLogger.debug(LTag.PUMP, "Loading event history from: " + dateUtil.dateAndTimeString(danaPump.readHistoryFrom));
mSerialIOThread.sendMessage(msg); mSerialIOThread.sendMessage(msg);
while (!danaPump.historyDoneReceived && mRfcommSocket.isConnected()) { while (!danaPump.historyDoneReceived && mRfcommSocket.isConnected()) {
SystemClock.sleep(100); SystemClock.sleep(100);
} }
SystemClock.sleep(200); SystemClock.sleep(200);
if (danaRv2Plugin.lastEventTimeLoaded != 0) if (danaPump.getLastEventTimeLoaded() != 0) danaPump.readHistoryFrom = danaPump.getLastEventTimeLoaded() - T.Companion.mins(1).msecs();
danaPump.lastHistoryFetched = danaRv2Plugin.lastEventTimeLoaded - T.Companion.mins(1).msecs();
else else
danaPump.lastHistoryFetched = 0; danaPump.readHistoryFrom = 0;
danaPump.setLastConnection(System.currentTimeMillis()); danaPump.setLastConnection(System.currentTimeMillis());
return new PumpEnactResult(injector).success(true); return new PumpEnactResult(injector).success(true);
} }

View file

@ -53,7 +53,6 @@ class PairingProgressDialog : DaggerDialogFragment() {
dialog?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN) dialog?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN)
isCancelable = false isCancelable = false
dialog?.setCanceledOnTouchOutside(false) dialog?.setCanceledOnTouchOutside(false)
setViews()
return binding.root return binding.root
} }
@ -84,6 +83,7 @@ class PairingProgressDialog : DaggerDialogFragment() {
_binding?.ok?.visibility = View.VISIBLE _binding?.ok?.visibility = View.VISIBLE
} }
} }
setViews()
} }
override fun dismiss() { override fun dismiss() {

View file

@ -262,19 +262,13 @@ class DanaRSService : DaggerService() {
return result return result
} }
SystemClock.sleep(1000) SystemClock.sleep(1000)
val msg: DanaRSPacketAPSHistoryEvents val msg = DanaRSPacketAPSHistoryEvents(injector, danaPump.readHistoryFrom)
if (danaPump.lastHistoryFetched == 0L) { aapsLogger.debug(LTag.PUMPCOMM, "Loading event history from: " + dateUtil.dateAndTimeString(danaPump.readHistoryFrom))
msg = DanaRSPacketAPSHistoryEvents(injector, 0)
aapsLogger.debug(LTag.PUMPCOMM, "Loading complete event history")
} else {
msg = DanaRSPacketAPSHistoryEvents(injector, danaPump.lastHistoryFetched)
aapsLogger.debug(LTag.PUMPCOMM, "Loading event history from: " + dateUtil.dateAndTimeString(danaPump.lastHistoryFetched))
}
sendMessage(msg) sendMessage(msg)
while (!danaPump.historyDoneReceived && bleComm.isConnected) { while (!danaPump.historyDoneReceived && bleComm.isConnected) {
SystemClock.sleep(100) SystemClock.sleep(100)
} }
danaPump.lastHistoryFetched = if (danaPump.lastEventTimeLoaded != 0L) danaPump.lastEventTimeLoaded - T.mins(1).msecs() else 0 danaPump.readHistoryFrom = if (danaPump.lastEventTimeLoaded != 0L) danaPump.lastEventTimeLoaded - T.mins(1).msecs() else 0
aapsLogger.debug(LTag.PUMPCOMM, "Events loaded") aapsLogger.debug(LTag.PUMPCOMM, "Events loaded")
rxBus.send(EventPumpStatusChanged(rh.gs(info.nightscout.pump.dana.R.string.gettingpumpstatus))) rxBus.send(EventPumpStatusChanged(rh.gs(info.nightscout.pump.dana.R.string.gettingpumpstatus)))
sendMessage(DanaRSPacketGeneralInitialScreenInformation(injector)) sendMessage(DanaRSPacketGeneralInitialScreenInformation(injector))
@ -305,7 +299,7 @@ class DanaRSService : DaggerService() {
// sendMessage(msg); // sendMessage(msg);
val msgSetHistoryEntryV2 = DanaRSPacketAPSSetEventHistory(injector, DanaPump.HistoryEntry.CARBS.value, carbTime, carbs, 0) val msgSetHistoryEntryV2 = DanaRSPacketAPSSetEventHistory(injector, DanaPump.HistoryEntry.CARBS.value, carbTime, carbs, 0)
sendMessage(msgSetHistoryEntryV2) sendMessage(msgSetHistoryEntryV2)
danaPump.lastHistoryFetched = min(danaPump.lastHistoryFetched, carbTime - T.mins(1).msecs()) danaPump.readHistoryFrom = min(danaPump.readHistoryFrom, carbTime - T.mins(1).msecs())
if (!msgSetHistoryEntryV2.isReceived || msgSetHistoryEntryV2.failed) if (!msgSetHistoryEntryV2.isReceived || msgSetHistoryEntryV2.failed)
uiInteraction.runAlarm(rh.gs(info.nightscout.pump.dana.R.string.carbs_store_error), rh.gs(info.nightscout.core.ui.R.string.error), info.nightscout.core.ui.R.raw.boluserror) uiInteraction.runAlarm(rh.gs(info.nightscout.pump.dana.R.string.carbs_store_error), rh.gs(info.nightscout.core.ui.R.string.error), info.nightscout.core.ui.R.raw.boluserror)
} }

View file

@ -3,7 +3,7 @@ package info.nightscout.pump.diaconn.packet
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.pump.diaconn.DiaconnG8Pump import info.nightscout.pump.diaconn.DiaconnG8Pump
import info.nightscout.pump.diaconn.R import info.nightscout.pump.diaconn.R
import info.nightscout.pump.diaconn.pumplog.PumplogUtil import info.nightscout.pump.diaconn.pumplog.PumpLogUtil
import info.nightscout.rx.logging.LTag import info.nightscout.rx.logging.LTag
import info.nightscout.shared.interfaces.ResourceHelper import info.nightscout.shared.interfaces.ResourceHelper
import info.nightscout.shared.sharedPreferences.SP import info.nightscout.shared.sharedPreferences.SP
@ -39,7 +39,7 @@ class BasalLimitInquireResponsePacket(injector: HasAndroidInjector) : DiaconnG8P
} }
diaconnG8Pump.maxBasalPerHours = getShortToInt(bufferData).toDouble() / 100.0 // not include tempbasal limit diaconnG8Pump.maxBasalPerHours = getShortToInt(bufferData).toDouble() / 100.0 // not include tempbasal limit
val pumpFirmwareVersion = sp.getString(rh.gs(R.string.pumpversion), "") val pumpFirmwareVersion = sp.getString(rh.gs(R.string.pumpversion), "")
if(pumpFirmwareVersion.isNotEmpty() && PumplogUtil.isPumpVersionGe(pumpFirmwareVersion, 3, 0)) { if(pumpFirmwareVersion.isNotEmpty() && PumpLogUtil.isPumpVersionGe(pumpFirmwareVersion, 3, 0)) {
diaconnG8Pump.maxBasal = diaconnG8Pump.maxBasalPerHours * 2.5 // include tempbasal diaconnG8Pump.maxBasal = diaconnG8Pump.maxBasalPerHours * 2.5 // include tempbasal
} else { } else {
diaconnG8Pump.maxBasal = diaconnG8Pump.maxBasalPerHours * 2.0 // include tempbasal diaconnG8Pump.maxBasal = diaconnG8Pump.maxBasalPerHours * 2.0 // include tempbasal

View file

@ -3,7 +3,7 @@ package info.nightscout.pump.diaconn.packet
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.pump.diaconn.DiaconnG8Pump import info.nightscout.pump.diaconn.DiaconnG8Pump
import info.nightscout.pump.diaconn.R import info.nightscout.pump.diaconn.R
import info.nightscout.pump.diaconn.pumplog.PumplogUtil import info.nightscout.pump.diaconn.pumplog.PumpLogUtil
import info.nightscout.rx.logging.LTag import info.nightscout.rx.logging.LTag
import info.nightscout.shared.interfaces.ResourceHelper import info.nightscout.shared.interfaces.ResourceHelper
import info.nightscout.shared.sharedPreferences.SP import info.nightscout.shared.sharedPreferences.SP
@ -214,7 +214,7 @@ class BigAPSMainInfoInquireResponsePacket(
diaconnG8Pump.pumpProfiles!![diaconnG8Pump.activeProfile][23] = diaconnG8Pump.baseAmount24 diaconnG8Pump.pumpProfiles!![diaconnG8Pump.activeProfile][23] = diaconnG8Pump.baseAmount24
//incarnation no 처리 //incarnation no 처리
diaconnG8Pump.isPumpVersionGe2_63 = PumplogUtil.isPumpVersionGe(sp.getString(rh.gs(R.string.pumpversion), ""), 2, 63) diaconnG8Pump.isPumpVersionGe2_63 = PumpLogUtil.isPumpVersionGe(sp.getString(rh.gs(R.string.pumpversion), ""), 2, 63)
aapsLogger.debug(LTag.PUMPCOMM, "result > " + diaconnG8Pump.result) aapsLogger.debug(LTag.PUMPCOMM, "result > " + diaconnG8Pump.result)
aapsLogger.debug(LTag.PUMPCOMM, "systemRemainInsulin > " + diaconnG8Pump.systemRemainInsulin) aapsLogger.debug(LTag.PUMPCOMM, "systemRemainInsulin > " + diaconnG8Pump.systemRemainInsulin)

View file

@ -19,32 +19,32 @@ import info.nightscout.pump.diaconn.api.PumpLogDto
import info.nightscout.pump.diaconn.common.RecordTypes import info.nightscout.pump.diaconn.common.RecordTypes
import info.nightscout.pump.diaconn.database.DiaconnHistoryRecord import info.nightscout.pump.diaconn.database.DiaconnHistoryRecord
import info.nightscout.pump.diaconn.database.DiaconnHistoryRecordDao import info.nightscout.pump.diaconn.database.DiaconnHistoryRecordDao
import info.nightscout.pump.diaconn.pumplog.LOG_ALARM_BATTERY import info.nightscout.pump.diaconn.pumplog.LogAlarmBattery
import info.nightscout.pump.diaconn.pumplog.LOG_ALARM_BLOCK import info.nightscout.pump.diaconn.pumplog.LogAlarmBlock
import info.nightscout.pump.diaconn.pumplog.LOG_ALARM_SHORTAGE import info.nightscout.pump.diaconn.pumplog.LogAlarmShortAge
import info.nightscout.pump.diaconn.pumplog.LOG_CHANGE_INJECTOR_SUCCESS import info.nightscout.pump.diaconn.pumplog.LogChangeInjectorSuccess
import info.nightscout.pump.diaconn.pumplog.LOG_CHANGE_NEEDLE_SUCCESS import info.nightscout.pump.diaconn.pumplog.LogChangeNeedleSuccess
import info.nightscout.pump.diaconn.pumplog.LOG_CHANGE_TUBE_SUCCESS import info.nightscout.pump.diaconn.pumplog.LogChangeTubeSuccess
import info.nightscout.pump.diaconn.pumplog.LOG_INJECTION_1DAY import info.nightscout.pump.diaconn.pumplog.LogInjectDualFail
import info.nightscout.pump.diaconn.pumplog.LOG_INJECTION_1DAY_BASAL import info.nightscout.pump.diaconn.pumplog.LogInjectDualSuccess
import info.nightscout.pump.diaconn.pumplog.LOG_INJECTION_1HOUR_BASAL import info.nightscout.pump.diaconn.pumplog.LogInjectMealFail
import info.nightscout.pump.diaconn.pumplog.LOG_INJECTION_DUAL_NORMAL import info.nightscout.pump.diaconn.pumplog.LogInjectMealSuccess
import info.nightscout.pump.diaconn.pumplog.LOG_INJECT_DUAL_FAIL import info.nightscout.pump.diaconn.pumplog.LogInjectNormalFail
import info.nightscout.pump.diaconn.pumplog.LOG_INJECT_DUAL_SUCCESS import info.nightscout.pump.diaconn.pumplog.LogInjectNormalSuccess
import info.nightscout.pump.diaconn.pumplog.LOG_INJECT_MEAL_FAIL import info.nightscout.pump.diaconn.pumplog.LogInjectSquareFail
import info.nightscout.pump.diaconn.pumplog.LOG_INJECT_MEAL_SUCCESS import info.nightscout.pump.diaconn.pumplog.LogInjectSquareSuccess
import info.nightscout.pump.diaconn.pumplog.LOG_INJECT_NORMAL_FAIL import info.nightscout.pump.diaconn.pumplog.LogInjection1Day
import info.nightscout.pump.diaconn.pumplog.LOG_INJECT_NORMAL_SUCCESS import info.nightscout.pump.diaconn.pumplog.LogInjection1DayBasal
import info.nightscout.pump.diaconn.pumplog.LOG_INJECT_SQUARE_FAIL import info.nightscout.pump.diaconn.pumplog.LogInjection1HourBasal
import info.nightscout.pump.diaconn.pumplog.LOG_INJECT_SQUARE_SUCCESS import info.nightscout.pump.diaconn.pumplog.LogInjectionDualNormal
import info.nightscout.pump.diaconn.pumplog.LOG_RESET_SYS_V3 import info.nightscout.pump.diaconn.pumplog.LogResetSysV3
import info.nightscout.pump.diaconn.pumplog.LOG_SET_DUAL_INJECTION import info.nightscout.pump.diaconn.pumplog.LogSetDualInjection
import info.nightscout.pump.diaconn.pumplog.LOG_SET_SQUARE_INJECTION import info.nightscout.pump.diaconn.pumplog.LogSetSquareInjection
import info.nightscout.pump.diaconn.pumplog.LOG_SUSPEND_RELEASE_V2 import info.nightscout.pump.diaconn.pumplog.LogSuspendReleaseV2
import info.nightscout.pump.diaconn.pumplog.LOG_SUSPEND_V2 import info.nightscout.pump.diaconn.pumplog.LogSuspendV2
import info.nightscout.pump.diaconn.pumplog.LOG_TB_START_V3 import info.nightscout.pump.diaconn.pumplog.LogTbStartV3
import info.nightscout.pump.diaconn.pumplog.LOG_TB_STOP_V3 import info.nightscout.pump.diaconn.pumplog.LogTbStopV3
import info.nightscout.pump.diaconn.pumplog.PumplogUtil import info.nightscout.pump.diaconn.pumplog.PumpLogUtil
import info.nightscout.rx.bus.RxBus import info.nightscout.rx.bus.RxBus
import info.nightscout.rx.events.EventPumpStatusChanged import info.nightscout.rx.events.EventPumpStatusChanged
import info.nightscout.rx.logging.LTag import info.nightscout.rx.logging.LTag
@ -113,22 +113,22 @@ class BigLogInquireResponsePacket(
val logNum = getShortToInt(bufferData) // 2byte val logNum = getShortToInt(bufferData) // 2byte
// log Data Parsing // log Data Parsing
val logData = byteArrayOf( val logData = byteArrayOf(
PumplogUtil.getByte(bufferData), PumpLogUtil.getByte(bufferData),
PumplogUtil.getByte(bufferData), PumpLogUtil.getByte(bufferData),
PumplogUtil.getByte(bufferData), PumpLogUtil.getByte(bufferData),
PumplogUtil.getByte(bufferData), PumpLogUtil.getByte(bufferData),
PumplogUtil.getByte(bufferData), PumpLogUtil.getByte(bufferData),
PumplogUtil.getByte(bufferData), PumpLogUtil.getByte(bufferData),
PumplogUtil.getByte(bufferData), PumpLogUtil.getByte(bufferData),
PumplogUtil.getByte(bufferData), PumpLogUtil.getByte(bufferData),
PumplogUtil.getByte(bufferData), PumpLogUtil.getByte(bufferData),
PumplogUtil.getByte(bufferData), PumpLogUtil.getByte(bufferData),
PumplogUtil.getByte(bufferData), PumpLogUtil.getByte(bufferData),
PumplogUtil.getByte(bufferData) PumpLogUtil.getByte(bufferData)
) )
// process Log to DB // process Log to DB
val logDataToHexString = toNarrowHex(logData) val logDataToHexString = toNarrowHex(logData)
val pumpLogKind: Byte = PumplogUtil.getKind(logDataToHexString) val pumpLogKind: Byte = PumpLogUtil.getKind(logDataToHexString)
var status: String var status: String
val diaconnG8HistoryRecord = DiaconnHistoryRecord(0) val diaconnG8HistoryRecord = DiaconnHistoryRecord(0)
@ -151,8 +151,8 @@ class BigLogInquireResponsePacket(
when (pumpLogKind) { when (pumpLogKind) {
LOG_INJECT_MEAL_SUCCESS.LOG_KIND -> { LogInjectMealSuccess.LOG_KIND -> {
val logItem = LOG_INJECT_MEAL_SUCCESS.parse(logDataToHexString) val logItem = LogInjectMealSuccess.parse(logDataToHexString)
aapsLogger.debug(LTag.PUMPCOMM, "$logItem ") aapsLogger.debug(LTag.PUMPCOMM, "$logItem ")
val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss") val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss")
val logDateTime = logStartDate.time val logDateTime = logStartDate.time
@ -186,8 +186,8 @@ class BigLogInquireResponsePacket(
status = "MEAL_BOLUS_SUCCESS" + dateUtil.timeString(logDateTime) status = "MEAL_BOLUS_SUCCESS" + dateUtil.timeString(logDateTime)
} }
LOG_INJECT_MEAL_FAIL.LOG_KIND -> { LogInjectMealFail.LOG_KIND -> {
val logItem = LOG_INJECT_MEAL_FAIL.parse(logDataToHexString) val logItem = LogInjectMealFail.parse(logDataToHexString)
aapsLogger.debug(LTag.PUMPCOMM, "$logItem ") aapsLogger.debug(LTag.PUMPCOMM, "$logItem ")
val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss") val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss")
val logDateTime = logStartDate.time val logDateTime = logStartDate.time
@ -221,8 +221,8 @@ class BigLogInquireResponsePacket(
status = "MEAL_BOLUS_FAIL " + dateUtil.timeString(logDateTime) status = "MEAL_BOLUS_FAIL " + dateUtil.timeString(logDateTime)
} }
LOG_INJECT_NORMAL_SUCCESS.LOG_KIND -> { LogInjectNormalSuccess.LOG_KIND -> {
val logItem = LOG_INJECT_NORMAL_SUCCESS.parse(logDataToHexString) val logItem = LogInjectNormalSuccess.parse(logDataToHexString)
aapsLogger.debug(LTag.PUMPCOMM, "$logItem ") aapsLogger.debug(LTag.PUMPCOMM, "$logItem ")
val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss") val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss")
@ -257,8 +257,8 @@ class BigLogInquireResponsePacket(
status = "BOLUS_SUCCESS" + dateUtil.timeString(logDateTime) status = "BOLUS_SUCCESS" + dateUtil.timeString(logDateTime)
} }
LOG_INJECT_NORMAL_FAIL.LOG_KIND -> { LogInjectNormalFail.LOG_KIND -> {
val logItem = LOG_INJECT_NORMAL_FAIL.parse(logDataToHexString) val logItem = LogInjectNormalFail.parse(logDataToHexString)
aapsLogger.debug(LTag.PUMPCOMM, "$logItem ") aapsLogger.debug(LTag.PUMPCOMM, "$logItem ")
val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss") val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss")
val logDateTime = logStartDate.time val logDateTime = logStartDate.time
@ -295,8 +295,8 @@ class BigLogInquireResponsePacket(
status = "BOLUS_FAIL " + dateUtil.timeString(logDateTime) status = "BOLUS_FAIL " + dateUtil.timeString(logDateTime)
} }
LOG_SET_SQUARE_INJECTION.LOG_KIND -> { LogSetSquareInjection.LOG_KIND -> {
val logItem = LOG_SET_SQUARE_INJECTION.parse(logDataToHexString) val logItem = LogSetSquareInjection.parse(logDataToHexString)
aapsLogger.debug(LTag.PUMPCOMM, "$logItem ") aapsLogger.debug(LTag.PUMPCOMM, "$logItem ")
val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss") val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss")
val logDateTime = logStartDate.time val logDateTime = logStartDate.time
@ -326,8 +326,8 @@ class BigLogInquireResponsePacket(
status = "EXTENDED_BOLUS_START " + dateUtil.timeString(logDateTime) status = "EXTENDED_BOLUS_START " + dateUtil.timeString(logDateTime)
} }
LOG_INJECT_SQUARE_SUCCESS.LOG_KIND -> { LogInjectSquareSuccess.LOG_KIND -> {
val logItem = LOG_INJECT_SQUARE_SUCCESS.parse(logDataToHexString) val logItem = LogInjectSquareSuccess.parse(logDataToHexString)
aapsLogger.debug(LTag.PUMPCOMM, "$logItem ") aapsLogger.debug(LTag.PUMPCOMM, "$logItem ")
val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss") val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss")
val logDateTime = logStartDate.time val logDateTime = logStartDate.time
@ -343,8 +343,8 @@ class BigLogInquireResponsePacket(
status = "EXTENDED_BOLUS_END " + dateUtil.timeString(logDateTime) status = "EXTENDED_BOLUS_END " + dateUtil.timeString(logDateTime)
} }
LOG_INJECT_SQUARE_FAIL.LOG_KIND -> { LogInjectSquareFail.LOG_KIND -> {
val logItem = LOG_INJECT_SQUARE_FAIL.parse(logDataToHexString) val logItem = LogInjectSquareFail.parse(logDataToHexString)
aapsLogger.debug(LTag.PUMPCOMM, "$logItem ") aapsLogger.debug(LTag.PUMPCOMM, "$logItem ")
val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss") val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss")
val logDateTime = logStartDate.time val logDateTime = logStartDate.time
@ -371,8 +371,8 @@ class BigLogInquireResponsePacket(
status = "EXTENDED_BOLUS_FAIL " + dateUtil.timeString(logDateTime) status = "EXTENDED_BOLUS_FAIL " + dateUtil.timeString(logDateTime)
} }
LOG_SET_DUAL_INJECTION.LOG_KIND -> { LogSetDualInjection.LOG_KIND -> {
val logItem = LOG_SET_DUAL_INJECTION.parse(logDataToHexString) val logItem = LogSetDualInjection.parse(logDataToHexString)
aapsLogger.debug(LTag.PUMPCOMM, "$logItem ") aapsLogger.debug(LTag.PUMPCOMM, "$logItem ")
val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss") val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss")
val logDateTime = logStartDate.time val logDateTime = logStartDate.time
@ -405,8 +405,8 @@ class BigLogInquireResponsePacket(
status = "DUAL_EXTENDED_START " + dateUtil.timeString(logDateTime) status = "DUAL_EXTENDED_START " + dateUtil.timeString(logDateTime)
} }
LOG_INJECTION_DUAL_NORMAL.LOG_KIND -> { LogInjectionDualNormal.LOG_KIND -> {
val logItem = LOG_INJECTION_DUAL_NORMAL.parse(logDataToHexString) val logItem = LogInjectionDualNormal.parse(logDataToHexString)
aapsLogger.debug(LTag.PUMPCOMM, "$logItem ") aapsLogger.debug(LTag.PUMPCOMM, "$logItem ")
val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss") val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss")
val logDateTime = logStartDate.time val logDateTime = logStartDate.time
@ -445,8 +445,8 @@ class BigLogInquireResponsePacket(
status = "DUAL_BOLUS" + dateUtil.timeString(logDateTime) status = "DUAL_BOLUS" + dateUtil.timeString(logDateTime)
} }
LOG_INJECT_DUAL_SUCCESS.LOG_KIND -> { LogInjectDualSuccess.LOG_KIND -> {
val logItem = LOG_INJECT_DUAL_SUCCESS.parse(logDataToHexString) val logItem = LogInjectDualSuccess.parse(logDataToHexString)
aapsLogger.debug(LTag.PUMPCOMM, "$logItem ") aapsLogger.debug(LTag.PUMPCOMM, "$logItem ")
val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss") val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss")
val logDateTime = logStartDate.time val logDateTime = logStartDate.time
@ -464,8 +464,8 @@ class BigLogInquireResponsePacket(
status = "DUAL_BOLUS_SQUARE_SUCCESS " + dateUtil.timeString(logDateTime) status = "DUAL_BOLUS_SQUARE_SUCCESS " + dateUtil.timeString(logDateTime)
} }
LOG_INJECT_DUAL_FAIL.LOG_KIND -> { LogInjectDualFail.LOG_KIND -> {
val logItem = LOG_INJECT_DUAL_FAIL.parse(logDataToHexString) val logItem = LogInjectDualFail.parse(logDataToHexString)
aapsLogger.debug(LTag.PUMPCOMM, "$logItem ") aapsLogger.debug(LTag.PUMPCOMM, "$logItem ")
val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss") val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss")
val logDateTime = logStartDate.time val logDateTime = logStartDate.time
@ -493,8 +493,8 @@ class BigLogInquireResponsePacket(
status = "DUAL_BOLUS FAIL " + dateUtil.timeString(logDateTime) status = "DUAL_BOLUS FAIL " + dateUtil.timeString(logDateTime)
} }
LOG_INJECTION_1HOUR_BASAL.LOG_KIND -> { LogInjection1HourBasal.LOG_KIND -> {
val logItem = LOG_INJECTION_1HOUR_BASAL.parse(logDataToHexString) val logItem = LogInjection1HourBasal.parse(logDataToHexString)
aapsLogger.debug(LTag.PUMPCOMM, "$logItem ") aapsLogger.debug(LTag.PUMPCOMM, "$logItem ")
val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss") val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss")
val logDateTime = logStartDate.time val logDateTime = logStartDate.time
@ -509,8 +509,8 @@ class BigLogInquireResponsePacket(
status = "1HOUR BASAL " + dateUtil.dateAndTimeString(logDateTime) status = "1HOUR BASAL " + dateUtil.dateAndTimeString(logDateTime)
} }
LOG_SUSPEND_V2.LOG_KIND -> { LogSuspendV2.LOG_KIND -> {
val logItem = LOG_SUSPEND_V2.parse(logDataToHexString) val logItem = LogSuspendV2.parse(logDataToHexString)
aapsLogger.debug(LTag.PUMPCOMM, "$logItem ") aapsLogger.debug(LTag.PUMPCOMM, "$logItem ")
val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss") val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss")
val logDateTime = logStartDate.time val logDateTime = logStartDate.time
@ -524,8 +524,8 @@ class BigLogInquireResponsePacket(
status = "SUSPEND " + dateUtil.timeString(logDateTime) status = "SUSPEND " + dateUtil.timeString(logDateTime)
} }
LOG_SUSPEND_RELEASE_V2.LOG_KIND -> { LogSuspendReleaseV2.LOG_KIND -> {
val logItem = LOG_SUSPEND_RELEASE_V2.parse(logDataToHexString) val logItem = LogSuspendReleaseV2.parse(logDataToHexString)
aapsLogger.debug(LTag.PUMPCOMM, "$logItem ") aapsLogger.debug(LTag.PUMPCOMM, "$logItem ")
val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss") val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss")
val logDateTime = logStartDate.time val logDateTime = logStartDate.time
@ -539,8 +539,8 @@ class BigLogInquireResponsePacket(
status = "SUSPEND_RELEASE " + dateUtil.timeString(logDateTime) status = "SUSPEND_RELEASE " + dateUtil.timeString(logDateTime)
} }
LOG_CHANGE_INJECTOR_SUCCESS.LOG_KIND -> { LogChangeInjectorSuccess.LOG_KIND -> {
val logItem = LOG_CHANGE_INJECTOR_SUCCESS.parse(logDataToHexString) val logItem = LogChangeInjectorSuccess.parse(logDataToHexString)
aapsLogger.debug(LTag.PUMPCOMM, "$logItem ") aapsLogger.debug(LTag.PUMPCOMM, "$logItem ")
val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss") val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss")
val logDateTime = logStartDate.time val logDateTime = logStartDate.time
@ -568,8 +568,8 @@ class BigLogInquireResponsePacket(
status = "INSULIN_CHANGE " + dateUtil.timeString(logDateTime) status = "INSULIN_CHANGE " + dateUtil.timeString(logDateTime)
} }
LOG_CHANGE_TUBE_SUCCESS.LOG_KIND -> { LogChangeTubeSuccess.LOG_KIND -> {
val logItem = LOG_CHANGE_TUBE_SUCCESS.parse(logDataToHexString) val logItem = LogChangeTubeSuccess.parse(logDataToHexString)
aapsLogger.debug(LTag.PUMPCOMM, "$logItem ") aapsLogger.debug(LTag.PUMPCOMM, "$logItem ")
val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss") val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss")
val logDateTime = logStartDate.time val logDateTime = logStartDate.time
@ -600,8 +600,8 @@ class BigLogInquireResponsePacket(
status = "TUBE_CHANGE " + dateUtil.timeString(logDateTime) status = "TUBE_CHANGE " + dateUtil.timeString(logDateTime)
} }
LOG_INJECTION_1DAY.LOG_KIND -> { // Daily Bolus Log LogInjection1Day.LOG_KIND -> { // Daily Bolus Log
val logItem = LOG_INJECTION_1DAY.parse(logDataToHexString) val logItem = LogInjection1Day.parse(logDataToHexString)
aapsLogger.debug(LTag.PUMPCOMM, "$logItem ") aapsLogger.debug(LTag.PUMPCOMM, "$logItem ")
val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss") val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss")
val logDateTime = logStartDate.time val logDateTime = logStartDate.time
@ -649,8 +649,8 @@ class BigLogInquireResponsePacket(
status = "DAILY_BOLUS " + dateUtil.timeString(logDateTime) status = "DAILY_BOLUS " + dateUtil.timeString(logDateTime)
} }
LOG_INJECTION_1DAY_BASAL.LOG_KIND -> { // Daily Basal Log LogInjection1DayBasal.LOG_KIND -> { // Daily Basal Log
val logItem = LOG_INJECTION_1DAY_BASAL.parse(logDataToHexString) val logItem = LogInjection1DayBasal.parse(logDataToHexString)
aapsLogger.debug(LTag.PUMPCOMM, "$logItem ") aapsLogger.debug(LTag.PUMPCOMM, "$logItem ")
val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss") val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss")
val logDateTime = logStartDate.time val logDateTime = logStartDate.time
@ -698,8 +698,8 @@ class BigLogInquireResponsePacket(
status = "DAILY_BASAL " + dateUtil.timeString(logDateTime) status = "DAILY_BASAL " + dateUtil.timeString(logDateTime)
} }
LOG_CHANGE_NEEDLE_SUCCESS.LOG_KIND -> { LogChangeNeedleSuccess.LOG_KIND -> {
val logItem = LOG_CHANGE_NEEDLE_SUCCESS.parse(logDataToHexString) val logItem = LogChangeNeedleSuccess.parse(logDataToHexString)
aapsLogger.debug(LTag.PUMPCOMM, "$logItem ") aapsLogger.debug(LTag.PUMPCOMM, "$logItem ")
val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss") val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss")
val logDateTime = logStartDate.time val logDateTime = logStartDate.time
@ -728,8 +728,8 @@ class BigLogInquireResponsePacket(
status = "NEEDLE_CHANGE " + dateUtil.timeString(logDateTime) status = "NEEDLE_CHANGE " + dateUtil.timeString(logDateTime)
} }
LOG_TB_START_V3.LOG_KIND -> { LogTbStartV3.LOG_KIND -> {
val logItem = LOG_TB_START_V3.parse(logDataToHexString) val logItem = LogTbStartV3.parse(logDataToHexString)
aapsLogger.debug(LTag.PUMPCOMM, "$logItem ") aapsLogger.debug(LTag.PUMPCOMM, "$logItem ")
val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss") val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss")
@ -772,8 +772,8 @@ class BigLogInquireResponsePacket(
status = "TEMP_START " + dateUtil.timeString(logDateTime) status = "TEMP_START " + dateUtil.timeString(logDateTime)
} }
LOG_TB_STOP_V3.LOG_KIND -> { LogTbStopV3.LOG_KIND -> {
val logItem = LOG_TB_STOP_V3.parse(logDataToHexString) val logItem = LogTbStopV3.parse(logDataToHexString)
aapsLogger.debug(LTag.PUMPCOMM, "$logItem ") aapsLogger.debug(LTag.PUMPCOMM, "$logItem ")
val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss") val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss")
val logDateTime = logStartDate.time val logDateTime = logStartDate.time
@ -806,8 +806,8 @@ class BigLogInquireResponsePacket(
status = "TEMP_STOP " + dateUtil.timeString(logDateTime) status = "TEMP_STOP " + dateUtil.timeString(logDateTime)
} }
LOG_ALARM_BATTERY.LOG_KIND -> { // BATTERY SHORTAGE ALARM LogAlarmBattery.LOG_KIND -> { // BATTERY SHORTAGE ALARM
val logItem = LOG_ALARM_BATTERY.parse(logDataToHexString) val logItem = LogAlarmBattery.parse(logDataToHexString)
aapsLogger.debug(LTag.PUMPCOMM, "$logItem ") aapsLogger.debug(LTag.PUMPCOMM, "$logItem ")
val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss") val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss")
val logDateTime = logStartDate.time val logDateTime = logStartDate.time
@ -822,8 +822,8 @@ class BigLogInquireResponsePacket(
status = "BATTERY_ALARM " + dateUtil.timeString(logDateTime) status = "BATTERY_ALARM " + dateUtil.timeString(logDateTime)
} }
LOG_ALARM_BLOCK.LOG_KIND -> { // INJECTION BLOCKED ALARM LogAlarmBlock.LOG_KIND -> { // INJECTION BLOCKED ALARM
val logItem = LOG_ALARM_BLOCK.parse(logDataToHexString) val logItem = LogAlarmBlock.parse(logDataToHexString)
aapsLogger.debug(LTag.PUMPCOMM, "$logItem ") aapsLogger.debug(LTag.PUMPCOMM, "$logItem ")
val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss") val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss")
@ -840,8 +840,8 @@ class BigLogInquireResponsePacket(
status = "BLOCK_ALARM " + dateUtil.timeString(logDateTime) status = "BLOCK_ALARM " + dateUtil.timeString(logDateTime)
} }
LOG_ALARM_SHORTAGE.LOG_KIND -> { // INSULIN SHORTAGE ALARM LogAlarmShortAge.LOG_KIND -> { // INSULIN SHORTAGE ALARM
val logItem = LOG_ALARM_SHORTAGE.parse(logDataToHexString) val logItem = LogAlarmShortAge.parse(logDataToHexString)
aapsLogger.debug(LTag.PUMPCOMM, "$logItem ") aapsLogger.debug(LTag.PUMPCOMM, "$logItem ")
val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss") val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss")
@ -858,8 +858,8 @@ class BigLogInquireResponsePacket(
status = "SHORT_AGE_ALARM " + dateUtil.timeString(logDateTime) status = "SHORT_AGE_ALARM " + dateUtil.timeString(logDateTime)
} }
LOG_RESET_SYS_V3.LOG_KIND -> { LogResetSysV3.LOG_KIND -> {
val logItem = LOG_RESET_SYS_V3.parse(logDataToHexString) val logItem = LogResetSysV3.parse(logDataToHexString)
aapsLogger.debug(LTag.PUMPCOMM, "$logItem ") aapsLogger.debug(LTag.PUMPCOMM, "$logItem ")
val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss") val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss")

View file

@ -5,7 +5,7 @@ import info.nightscout.interfaces.pump.defs.PumpDescription
import info.nightscout.interfaces.pump.defs.PumpType import info.nightscout.interfaces.pump.defs.PumpType
import info.nightscout.pump.diaconn.DiaconnG8Pump import info.nightscout.pump.diaconn.DiaconnG8Pump
import info.nightscout.pump.diaconn.R import info.nightscout.pump.diaconn.R
import info.nightscout.pump.diaconn.pumplog.PumplogUtil import info.nightscout.pump.diaconn.pumplog.PumpLogUtil
import info.nightscout.rx.logging.LTag import info.nightscout.rx.logging.LTag
import info.nightscout.shared.interfaces.ResourceHelper import info.nightscout.shared.interfaces.ResourceHelper
import info.nightscout.shared.sharedPreferences.SP import info.nightscout.shared.sharedPreferences.SP
@ -213,7 +213,7 @@ class BigMainInfoInquireResponsePacket(
diaconnG8Pump.pumpProfiles!![diaconnG8Pump.activeProfile][23] = diaconnG8Pump.baseAmount24 diaconnG8Pump.pumpProfiles!![diaconnG8Pump.activeProfile][23] = diaconnG8Pump.baseAmount24
//incarnation no 처리 //incarnation no 처리
diaconnG8Pump.isPumpVersionGe2_63 = PumplogUtil.isPumpVersionGe(sp.getString(rh.gs(R.string.pumpversion), ""), 2, 63) diaconnG8Pump.isPumpVersionGe2_63 = PumpLogUtil.isPumpVersionGe(sp.getString(rh.gs(R.string.pumpversion), ""), 2, 63)
aapsLogger.debug(LTag.PUMPCOMM, "result > " + diaconnG8Pump.result) aapsLogger.debug(LTag.PUMPCOMM, "result > " + diaconnG8Pump.result)
aapsLogger.debug(LTag.PUMPCOMM, "systemRemainInsulin > " + diaconnG8Pump.systemRemainInsulin) aapsLogger.debug(LTag.PUMPCOMM, "systemRemainInsulin > " + diaconnG8Pump.systemRemainInsulin)

View file

@ -6,7 +6,7 @@ import java.nio.ByteOrder
/* /*
* Battery Shortage Alarm Log * Battery Shortage Alarm Log
*/ */
class LOG_ALARM_BATTERY private constructor( class LogAlarmBattery private constructor(
val data: String, val data: String,
val dttm: String, val dttm: String,
typeAndKind: Byte, // 1=INFO, 2=WARNING, 3=MAJOR, 4=CRITICAL typeAndKind: Byte, // 1=INFO, 2=WARNING, 3=MAJOR, 4=CRITICAL
@ -15,8 +15,8 @@ class LOG_ALARM_BATTERY private constructor(
val batteryRemain: Byte val batteryRemain: Byte
) { ) {
val type: Byte = PumplogUtil.getType(typeAndKind) val type: Byte = PumpLogUtil.getType(typeAndKind)
val kind: Byte = PumplogUtil.getKind(typeAndKind) val kind: Byte = PumpLogUtil.getKind(typeAndKind)
override fun toString(): String { override fun toString(): String {
val sb = StringBuilder("LOG_ALARM_BATTERY{") val sb = StringBuilder("LOG_ALARM_BATTERY{")
@ -35,17 +35,17 @@ class LOG_ALARM_BATTERY private constructor(
companion object { companion object {
const val LOG_KIND: Byte = 0x28 const val LOG_KIND: Byte = 0x28
fun parse(data: String): LOG_ALARM_BATTERY { fun parse(data: String): LogAlarmBattery {
val bytes = PumplogUtil.hexStringToByteArray(data) val bytes = PumpLogUtil.hexStringToByteArray(data)
val buffer = ByteBuffer.wrap(bytes) val buffer = ByteBuffer.wrap(bytes)
buffer.order(ByteOrder.LITTLE_ENDIAN) buffer.order(ByteOrder.LITTLE_ENDIAN)
return LOG_ALARM_BATTERY( return LogAlarmBattery(
data, data,
PumplogUtil.getDttm(buffer), PumpLogUtil.getDttm(buffer),
PumplogUtil.getByte(buffer), PumpLogUtil.getByte(buffer),
PumplogUtil.getByte(buffer), PumpLogUtil.getByte(buffer),
PumplogUtil.getByte(buffer), PumpLogUtil.getByte(buffer),
PumplogUtil.getByte(buffer) PumpLogUtil.getByte(buffer)
) )
} }
} }

View file

@ -6,19 +6,19 @@ import java.nio.ByteOrder
/* /*
* Injection Blocked Alarm Log * Injection Blocked Alarm Log
*/ */
class LOG_ALARM_BLOCK private constructor( class LogAlarmBlock private constructor(
val data: String, val data: String,
val dttm: String, val dttm: String,
typeAndKind: Byte, // 1=INFO, 2=WARNING, 3=MAJOR, 4=CRITICAL typeAndKind: Byte, // 1=INFO, 2=WARNING, 3=MAJOR, 4=CRITICAL
val alarmLevel: Byte, // 1=OCCUR private val alarmLevel: Byte, // 1=OCCUR
val ack: Byte, private val ack: Byte,
val amount: Short, // 1=BASE, 2=Meal, 3=snack , 4=square, 5=dual, 6=tube change, 7=needle change, 8=insulin change val amount: Short, // 1=BASE, 2=Meal, 3=snack , 4=square, 5=dual, 6=tube change, 7=needle change, 8=insulin change
val reason: Byte, val reason: Byte,
val batteryRemain: Byte val batteryRemain: Byte
) { ) {
val type: Byte = PumplogUtil.getType(typeAndKind) val type: Byte = PumpLogUtil.getType(typeAndKind)
val kind: Byte = PumplogUtil.getKind(typeAndKind) val kind: Byte = PumpLogUtil.getKind(typeAndKind)
override fun toString(): String { override fun toString(): String {
val sb = StringBuilder("LOG_ALARM_BLOCK{") val sb = StringBuilder("LOG_ALARM_BLOCK{")
@ -39,19 +39,19 @@ class LOG_ALARM_BLOCK private constructor(
companion object { companion object {
const val LOG_KIND: Byte = 0x29 const val LOG_KIND: Byte = 0x29
fun parse(data: String): LOG_ALARM_BLOCK { fun parse(data: String): LogAlarmBlock {
val bytes = PumplogUtil.hexStringToByteArray(data) val bytes = PumpLogUtil.hexStringToByteArray(data)
val buffer = ByteBuffer.wrap(bytes) val buffer = ByteBuffer.wrap(bytes)
buffer.order(ByteOrder.LITTLE_ENDIAN) buffer.order(ByteOrder.LITTLE_ENDIAN)
return LOG_ALARM_BLOCK( return LogAlarmBlock(
data, data,
PumplogUtil.getDttm(buffer), PumpLogUtil.getDttm(buffer),
PumplogUtil.getByte(buffer), PumpLogUtil.getByte(buffer),
PumplogUtil.getByte(buffer), PumpLogUtil.getByte(buffer),
PumplogUtil.getByte(buffer), PumpLogUtil.getByte(buffer),
PumplogUtil.getShort(buffer), PumpLogUtil.getShort(buffer),
PumplogUtil.getByte(buffer), PumpLogUtil.getByte(buffer),
PumplogUtil.getByte(buffer) PumpLogUtil.getByte(buffer)
) )
} }
} }

View file

@ -6,18 +6,18 @@ import java.nio.ByteOrder
/* /*
* Insulin shortage alarm * Insulin shortage alarm
*/ */
class LOG_ALARM_SHORTAGE private constructor( class LogAlarmShortAge private constructor(
val data: String, val data: String,
val dttm: String, val dttm: String,
typeAndKind: Byte, // 1=INFO, 2=WARNING, 3=MAJOR, 4=CRITICAL typeAndKind: Byte, // 1=INFO, 2=WARNING, 3=MAJOR, 4=CRITICAL
val alarmLevel: Byte, // 1=OCCUR, 2=STOP private val alarmLevel: Byte, // 1=OCCUR, 2=STOP
val ack: Byte, // (1~100U) private val ack: Byte, // (1~100U)
val remain: Byte, val remain: Byte,
val batteryRemain: Byte val batteryRemain: Byte
) { ) {
val type: Byte = PumplogUtil.getType(typeAndKind) val type: Byte = PumpLogUtil.getType(typeAndKind)
val kind: Byte = PumplogUtil.getKind(typeAndKind) val kind: Byte = PumpLogUtil.getKind(typeAndKind)
override fun toString(): String { override fun toString(): String {
val sb = StringBuilder("LOG_ALARM_SHORTAGE{") val sb = StringBuilder("LOG_ALARM_SHORTAGE{")
@ -37,18 +37,18 @@ class LOG_ALARM_SHORTAGE private constructor(
companion object { companion object {
const val LOG_KIND: Byte = 0x2A const val LOG_KIND: Byte = 0x2A
fun parse(data: String): LOG_ALARM_SHORTAGE { fun parse(data: String): LogAlarmShortAge {
val bytes = PumplogUtil.hexStringToByteArray(data) val bytes = PumpLogUtil.hexStringToByteArray(data)
val buffer = ByteBuffer.wrap(bytes) val buffer = ByteBuffer.wrap(bytes)
buffer.order(ByteOrder.LITTLE_ENDIAN) buffer.order(ByteOrder.LITTLE_ENDIAN)
return LOG_ALARM_SHORTAGE( return LogAlarmShortAge(
data, data,
PumplogUtil.getDttm(buffer), PumpLogUtil.getDttm(buffer),
PumplogUtil.getByte(buffer), PumpLogUtil.getByte(buffer),
PumplogUtil.getByte(buffer), PumpLogUtil.getByte(buffer),
PumplogUtil.getByte(buffer), PumpLogUtil.getByte(buffer),
PumplogUtil.getByte(buffer), PumpLogUtil.getByte(buffer),
PumplogUtil.getByte(buffer) PumpLogUtil.getByte(buffer)
) )
} }
} }

View file

@ -6,7 +6,7 @@ import java.nio.ByteOrder
/* /*
* 주사기 교체 성공 * 주사기 교체 성공
*/ */
class LOG_CHANGE_INJECTOR_SUCCESS private constructor( class LogChangeInjectorSuccess private constructor(
val data: String, val data: String,
val dttm: String, val dttm: String,
typeAndKind: Byte, // 47.5=4750 typeAndKind: Byte, // 47.5=4750
@ -15,8 +15,8 @@ class LOG_CHANGE_INJECTOR_SUCCESS private constructor(
val batteryRemain: Byte val batteryRemain: Byte
) { ) {
val type: Byte = PumplogUtil.getType(typeAndKind) val type: Byte = PumpLogUtil.getType(typeAndKind)
val kind: Byte = PumplogUtil.getKind(typeAndKind) val kind: Byte = PumpLogUtil.getKind(typeAndKind)
override fun toString(): String { override fun toString(): String {
val sb = StringBuilder("LOG_CHANGE_INJECTOR_SUCCESS{") val sb = StringBuilder("LOG_CHANGE_INJECTOR_SUCCESS{")
@ -35,17 +35,17 @@ class LOG_CHANGE_INJECTOR_SUCCESS private constructor(
companion object { companion object {
const val LOG_KIND: Byte = 0x1A const val LOG_KIND: Byte = 0x1A
fun parse(data: String): LOG_CHANGE_INJECTOR_SUCCESS { fun parse(data: String): LogChangeInjectorSuccess {
val bytes = PumplogUtil.hexStringToByteArray(data) val bytes = PumpLogUtil.hexStringToByteArray(data)
val buffer = ByteBuffer.wrap(bytes) val buffer = ByteBuffer.wrap(bytes)
buffer.order(ByteOrder.LITTLE_ENDIAN) buffer.order(ByteOrder.LITTLE_ENDIAN)
return LOG_CHANGE_INJECTOR_SUCCESS( return LogChangeInjectorSuccess(
data, data,
PumplogUtil.getDttm(buffer), PumpLogUtil.getDttm(buffer),
PumplogUtil.getByte(buffer), PumpLogUtil.getByte(buffer),
PumplogUtil.getShort(buffer), PumpLogUtil.getShort(buffer),
PumplogUtil.getShort(buffer), PumpLogUtil.getShort(buffer),
PumplogUtil.getByte(buffer) PumpLogUtil.getByte(buffer)
) )
} }
} }

View file

@ -6,7 +6,8 @@ import java.nio.ByteOrder
/* /*
* 바늘 공기빼기 성공 * 바늘 공기빼기 성공
*/ */
class LOG_CHANGE_NEEDLE_SUCCESS private constructor( @Suppress("SpellCheckingInspection")
class LogChangeNeedleSuccess private constructor(
val data: String, val data: String,
val dttm: String, val dttm: String,
typeAndKind: Byte, // 47.5=4750 typeAndKind: Byte, // 47.5=4750
@ -15,8 +16,8 @@ class LOG_CHANGE_NEEDLE_SUCCESS private constructor(
val batteryRemain: Byte val batteryRemain: Byte
) { ) {
val type: Byte = PumplogUtil.getType(typeAndKind) val type: Byte = PumpLogUtil.getType(typeAndKind)
val kind: Byte = PumplogUtil.getKind(typeAndKind) val kind: Byte = PumpLogUtil.getKind(typeAndKind)
override fun toString(): String { override fun toString(): String {
val sb = StringBuilder("LOG_CHANGE_NEEDLE_SUCCESS{") val sb = StringBuilder("LOG_CHANGE_NEEDLE_SUCCESS{")
@ -35,17 +36,17 @@ class LOG_CHANGE_NEEDLE_SUCCESS private constructor(
companion object { companion object {
const val LOG_KIND: Byte = 0x1C const val LOG_KIND: Byte = 0x1C
fun parse(data: String): LOG_CHANGE_NEEDLE_SUCCESS { fun parse(data: String): LogChangeNeedleSuccess {
val bytes = PumplogUtil.hexStringToByteArray(data) val bytes = PumpLogUtil.hexStringToByteArray(data)
val buffer = ByteBuffer.wrap(bytes) val buffer = ByteBuffer.wrap(bytes)
buffer.order(ByteOrder.LITTLE_ENDIAN) buffer.order(ByteOrder.LITTLE_ENDIAN)
return LOG_CHANGE_NEEDLE_SUCCESS( return LogChangeNeedleSuccess(
data, data,
PumplogUtil.getDttm(buffer), PumpLogUtil.getDttm(buffer),
PumplogUtil.getByte(buffer), PumpLogUtil.getByte(buffer),
PumplogUtil.getShort(buffer), PumpLogUtil.getShort(buffer),
PumplogUtil.getShort(buffer), PumpLogUtil.getShort(buffer),
PumplogUtil.getByte(buffer) PumpLogUtil.getByte(buffer)
) )
} }
} }

View file

@ -6,7 +6,8 @@ import java.nio.ByteOrder
/* /*
* 튜브 공기빼기 성공 * 튜브 공기빼기 성공
*/ */
class LOG_CHANGE_TUBE_SUCCESS private constructor( @Suppress("SpellCheckingInspection")
class LogChangeTubeSuccess private constructor(
val data: String, val data: String,
val dttm: String, val dttm: String,
typeAndKind: Byte, // 47.5=4750 typeAndKind: Byte, // 47.5=4750
@ -15,8 +16,8 @@ class LOG_CHANGE_TUBE_SUCCESS private constructor(
val batteryRemain: Byte val batteryRemain: Byte
) { ) {
val type: Byte = PumplogUtil.getType(typeAndKind) val type: Byte = PumpLogUtil.getType(typeAndKind)
val kind: Byte = PumplogUtil.getKind(typeAndKind) val kind: Byte = PumpLogUtil.getKind(typeAndKind)
override fun toString(): String { override fun toString(): String {
val sb = StringBuilder("LOG_CHANGE_TUBE_SUCCESS{") val sb = StringBuilder("LOG_CHANGE_TUBE_SUCCESS{")
@ -35,17 +36,17 @@ class LOG_CHANGE_TUBE_SUCCESS private constructor(
companion object { companion object {
const val LOG_KIND: Byte = 0x18 const val LOG_KIND: Byte = 0x18
fun parse(data: String): LOG_CHANGE_TUBE_SUCCESS { fun parse(data: String): LogChangeTubeSuccess {
val bytes = PumplogUtil.hexStringToByteArray(data) val bytes = PumpLogUtil.hexStringToByteArray(data)
val buffer = ByteBuffer.wrap(bytes) val buffer = ByteBuffer.wrap(bytes)
buffer.order(ByteOrder.LITTLE_ENDIAN) buffer.order(ByteOrder.LITTLE_ENDIAN)
return LOG_CHANGE_TUBE_SUCCESS( return LogChangeTubeSuccess(
data, data,
PumplogUtil.getDttm(buffer), PumpLogUtil.getDttm(buffer),
PumplogUtil.getByte(buffer), PumpLogUtil.getByte(buffer),
PumplogUtil.getShort(buffer), PumpLogUtil.getShort(buffer),
PumplogUtil.getShort(buffer), PumpLogUtil.getShort(buffer),
PumplogUtil.getByte(buffer) PumpLogUtil.getByte(buffer)
) )
} }
} }

View file

@ -7,7 +7,8 @@ import java.nio.ByteOrder
/* /*
* Dual Injection Fail Log * Dual Injection Fail Log
*/ */
class LOG_INJECT_DUAL_FAIL private constructor( @Suppress("SpellCheckingInspection")
class LogInjectDualFail private constructor(
val data: String, val data: String,
val dttm: String, val dttm: String,
typeAndKind: Byte, // 47.5=4750 typeAndKind: Byte, // 47.5=4750
@ -18,8 +19,8 @@ class LOG_INJECT_DUAL_FAIL private constructor(
val batteryRemain: Byte val batteryRemain: Byte
) { ) {
val type: Byte = PumplogUtil.getType(typeAndKind) val type: Byte = PumpLogUtil.getType(typeAndKind)
val kind: Byte = PumplogUtil.getKind(typeAndKind) val kind: Byte = PumpLogUtil.getKind(typeAndKind)
fun getInjectTime(): Int { fun getInjectTime(): Int {
return injectTime and 0xff return injectTime and 0xff
@ -44,19 +45,19 @@ class LOG_INJECT_DUAL_FAIL private constructor(
companion object { companion object {
const val LOG_KIND: Byte = 0x11 const val LOG_KIND: Byte = 0x11
fun parse(data: String): LOG_INJECT_DUAL_FAIL { fun parse(data: String): LogInjectDualFail {
val bytes = PumplogUtil.hexStringToByteArray(data) val bytes = PumpLogUtil.hexStringToByteArray(data)
val buffer = ByteBuffer.wrap(bytes) val buffer = ByteBuffer.wrap(bytes)
buffer.order(ByteOrder.LITTLE_ENDIAN) buffer.order(ByteOrder.LITTLE_ENDIAN)
return LOG_INJECT_DUAL_FAIL( return LogInjectDualFail(
data, data,
PumplogUtil.getDttm(buffer), PumpLogUtil.getDttm(buffer),
PumplogUtil.getByte(buffer), PumpLogUtil.getByte(buffer),
PumplogUtil.getShort(buffer), PumpLogUtil.getShort(buffer),
PumplogUtil.getShort(buffer), PumpLogUtil.getShort(buffer),
PumplogUtil.getByte(buffer), PumpLogUtil.getByte(buffer),
PumplogUtil.getByte(buffer), PumpLogUtil.getByte(buffer),
PumplogUtil.getByte(buffer) PumpLogUtil.getByte(buffer)
) )
} }
} }

View file

@ -7,18 +7,19 @@ import java.nio.ByteOrder
/* /*
* 듀얼주입 성공 * 듀얼주입 성공
*/ */
class LOG_INJECT_DUAL_SUCCESS private constructor( @Suppress("SpellCheckingInspection")
class LogInjectDualSuccess private constructor(
val data: String, val data: String,
val dttm: String, val dttm: String,
typeAndKind: Byte, // 47.5=4750 typeAndKind: Byte, // 47.5=4750
val injectNormAmount: Short, // 47.5=4750 private val injectNormAmount: Short, // 47.5=4750
val injectSquareAmount: Short, // 1분단위 주입시간(124=124분=2시간4분) val injectSquareAmount: Short, // 1분단위 주입시간(124=124분=2시간4분)
private val injectTime: Byte, private val injectTime: Byte,
val batteryRemain: Byte val batteryRemain: Byte
) { ) {
val type: Byte = PumplogUtil.getType(typeAndKind) val type: Byte = PumpLogUtil.getType(typeAndKind)
val kind: Byte = PumplogUtil.getKind(typeAndKind) val kind: Byte = PumpLogUtil.getKind(typeAndKind)
fun getInjectTime(): Int { fun getInjectTime(): Int {
return injectTime and 0xff return injectTime and 0xff
} }
@ -41,18 +42,18 @@ class LOG_INJECT_DUAL_SUCCESS private constructor(
companion object { companion object {
const val LOG_KIND: Byte = 0x10 const val LOG_KIND: Byte = 0x10
fun parse(data: String): LOG_INJECT_DUAL_SUCCESS { fun parse(data: String): LogInjectDualSuccess {
val bytes = PumplogUtil.hexStringToByteArray(data) val bytes = PumpLogUtil.hexStringToByteArray(data)
val buffer = ByteBuffer.wrap(bytes) val buffer = ByteBuffer.wrap(bytes)
buffer.order(ByteOrder.LITTLE_ENDIAN) buffer.order(ByteOrder.LITTLE_ENDIAN)
return LOG_INJECT_DUAL_SUCCESS( return LogInjectDualSuccess(
data, data,
PumplogUtil.getDttm(buffer), PumpLogUtil.getDttm(buffer),
PumplogUtil.getByte(buffer), PumpLogUtil.getByte(buffer),
PumplogUtil.getShort(buffer), PumpLogUtil.getShort(buffer),
PumplogUtil.getShort(buffer), PumpLogUtil.getShort(buffer),
PumplogUtil.getByte(buffer), PumpLogUtil.getByte(buffer),
PumplogUtil.getByte(buffer) PumpLogUtil.getByte(buffer)
) )
} }
} }

View file

@ -7,7 +7,8 @@ import java.nio.ByteOrder
/* /*
* 식사주입 실패 * 식사주입 실패
*/ */
class LOG_INJECT_MEAL_FAIL private constructor( @Suppress("SpellCheckingInspection")
class LogInjectMealFail private constructor(
val data: String, val data: String,
val dttm: String, val dttm: String,
typeAndKind: Byte, // 47.5=4750 typeAndKind: Byte, // 47.5=4750
@ -18,8 +19,8 @@ class LOG_INJECT_MEAL_FAIL private constructor(
val reason: Byte val reason: Byte
) { ) {
val type: Byte = PumplogUtil.getType(typeAndKind) val type: Byte = PumpLogUtil.getType(typeAndKind)
val kind: Byte = PumplogUtil.getKind(typeAndKind) val kind: Byte = PumpLogUtil.getKind(typeAndKind)
fun getInjectTime(): Int { fun getInjectTime(): Int {
return injectTime and 0xff return injectTime and 0xff
@ -44,19 +45,19 @@ class LOG_INJECT_MEAL_FAIL private constructor(
companion object { companion object {
const val LOG_KIND: Byte = 0x09 const val LOG_KIND: Byte = 0x09
fun parse(data: String): LOG_INJECT_MEAL_FAIL { fun parse(data: String): LogInjectMealFail {
val bytes = PumplogUtil.hexStringToByteArray(data) val bytes = PumpLogUtil.hexStringToByteArray(data)
val buffer = ByteBuffer.wrap(bytes) val buffer = ByteBuffer.wrap(bytes)
buffer.order(ByteOrder.LITTLE_ENDIAN) buffer.order(ByteOrder.LITTLE_ENDIAN)
return LOG_INJECT_MEAL_FAIL( return LogInjectMealFail(
data, data,
PumplogUtil.getDttm(buffer), PumpLogUtil.getDttm(buffer),
PumplogUtil.getByte(buffer), PumpLogUtil.getByte(buffer),
PumplogUtil.getShort(buffer), PumpLogUtil.getShort(buffer),
PumplogUtil.getShort(buffer), PumpLogUtil.getShort(buffer),
PumplogUtil.getByte(buffer), PumpLogUtil.getByte(buffer),
PumplogUtil.getByte(buffer), PumpLogUtil.getByte(buffer),
PumplogUtil.getByte(buffer) PumpLogUtil.getByte(buffer)
) )
} }
} }

View file

@ -7,7 +7,8 @@ import java.nio.ByteOrder
/* /*
* 식사주입 성공 * 식사주입 성공
*/ */
class LOG_INJECT_MEAL_SUCCESS private constructor( @Suppress("SpellCheckingInspection")
class LogInjectMealSuccess private constructor(
val data: String, val data: String,
val dttm: String, val dttm: String,
typeAndKind: Byte, // 47.5=4750 typeAndKind: Byte, // 47.5=4750
@ -15,12 +16,11 @@ class LOG_INJECT_MEAL_SUCCESS private constructor(
val injectAmount: Short, // 1분단위 주입시간(124=124분=2시간4분) val injectAmount: Short, // 1분단위 주입시간(124=124분=2시간4분)
private val injectTime: Byte, // 아침=1, 점심=2, 저녁=3 private val injectTime: Byte, // 아침=1, 점심=2, 저녁=3
val time: Byte, val time: Byte,
batteryRemain: Byte val batteryRemain: Byte
) { ) {
val type: Byte = PumplogUtil.getType(typeAndKind) val type: Byte = PumpLogUtil.getType(typeAndKind)
val kind: Byte = PumplogUtil.getKind(typeAndKind) val kind: Byte = PumpLogUtil.getKind(typeAndKind)
val batteryRemain: Byte = batteryRemain
fun getInjectTime(): Int { fun getInjectTime(): Int {
return injectTime and 0xff return injectTime and 0xff
} }
@ -44,19 +44,19 @@ class LOG_INJECT_MEAL_SUCCESS private constructor(
companion object { companion object {
const val LOG_KIND: Byte = 0x08 const val LOG_KIND: Byte = 0x08
fun parse(data: String): LOG_INJECT_MEAL_SUCCESS { fun parse(data: String): LogInjectMealSuccess {
val bytes = PumplogUtil.hexStringToByteArray(data) val bytes = PumpLogUtil.hexStringToByteArray(data)
val buffer = ByteBuffer.wrap(bytes) val buffer = ByteBuffer.wrap(bytes)
buffer.order(ByteOrder.LITTLE_ENDIAN) buffer.order(ByteOrder.LITTLE_ENDIAN)
return LOG_INJECT_MEAL_SUCCESS( return LogInjectMealSuccess(
data, data,
PumplogUtil.getDttm(buffer), PumpLogUtil.getDttm(buffer),
PumplogUtil.getByte(buffer), PumpLogUtil.getByte(buffer),
PumplogUtil.getShort(buffer), PumpLogUtil.getShort(buffer),
PumplogUtil.getShort(buffer), PumpLogUtil.getShort(buffer),
PumplogUtil.getByte(buffer), PumpLogUtil.getByte(buffer),
PumplogUtil.getByte(buffer), PumpLogUtil.getByte(buffer),
PumplogUtil.getByte(buffer) PumpLogUtil.getByte(buffer)
) )
} }
} }

View file

@ -7,19 +7,20 @@ import java.nio.ByteOrder
/* /*
* 일반주입 실패 * 일반주입 실패
*/ */
class LOG_INJECT_NORMAL_FAIL private constructor( @Suppress("SpellCheckingInspection")
class LogInjectNormalFail private constructor(
val data: String, val data: String,
val dttm: String, val dttm: String,
typeAndKind: Byte, // 47.5=4750 typeAndKind: Byte, // 47.5=4750
val setAmount: Short, // 47.5=4750 private val setAmount: Short, // 47.5=4750
val injectAmount: Short, // 1분단위 주입시간(124=124분=2시간4분) val injectAmount: Short, // 1분단위 주입시간(124=124분=2시간4분)
val injectTime: Byte, // 1=주입막힘, 2=배터리잔량부족, 3=약물부족, 4=사용자중지, 5=시스템리셋, 6=기타, 7=긴급정지 val injectTime: Byte, // 1=주입막힘, 2=배터리잔량부족, 3=약물부족, 4=사용자중지, 5=시스템리셋, 6=기타, 7=긴급정지
val reason: Byte, val reason: Byte,
val batteryRemain: Byte val batteryRemain: Byte
) { ) {
val type: Byte = PumplogUtil.getType(typeAndKind) val type: Byte = PumpLogUtil.getType(typeAndKind)
val kind: Byte = PumplogUtil.getKind(typeAndKind) val kind: Byte = PumpLogUtil.getKind(typeAndKind)
fun getInjectTime(): Int { fun getInjectTime(): Int {
return injectTime and 0xff return injectTime and 0xff
@ -44,19 +45,19 @@ class LOG_INJECT_NORMAL_FAIL private constructor(
companion object { companion object {
const val LOG_KIND: Byte = 0x0B const val LOG_KIND: Byte = 0x0B
fun parse(data: String): LOG_INJECT_NORMAL_FAIL { fun parse(data: String): LogInjectNormalFail {
val bytes = PumplogUtil.hexStringToByteArray(data) val bytes = PumpLogUtil.hexStringToByteArray(data)
val buffer = ByteBuffer.wrap(bytes) val buffer = ByteBuffer.wrap(bytes)
buffer.order(ByteOrder.LITTLE_ENDIAN) buffer.order(ByteOrder.LITTLE_ENDIAN)
return LOG_INJECT_NORMAL_FAIL( return LogInjectNormalFail(
data, data,
PumplogUtil.getDttm(buffer), PumpLogUtil.getDttm(buffer),
PumplogUtil.getByte(buffer), PumpLogUtil.getByte(buffer),
PumplogUtil.getShort(buffer), PumpLogUtil.getShort(buffer),
PumplogUtil.getShort(buffer), PumpLogUtil.getShort(buffer),
PumplogUtil.getByte(buffer), PumpLogUtil.getByte(buffer),
PumplogUtil.getByte(buffer), PumpLogUtil.getByte(buffer),
PumplogUtil.getByte(buffer) PumpLogUtil.getByte(buffer)
) )
} }
} }

View file

@ -7,18 +7,19 @@ import java.nio.ByteOrder
/* /*
* 일반주입 성공 * 일반주입 성공
*/ */
class LOG_INJECT_NORMAL_SUCCESS private constructor( @Suppress("SpellCheckingInspection")
class LogInjectNormalSuccess private constructor(
val data: String, val data: String,
val dttm: String, val dttm: String,
typeAndKind: Byte, // 47.5=4750 typeAndKind: Byte, // 47.5=4750
val setAmount: Short, // 47.5=4750 private val setAmount: Short, // 47.5=4750
val injectAmount: Short, // 1분단위 주입시간(124=124분=2시간4분) val injectAmount: Short, // 1분단위 주입시간(124=124분=2시간4분)
val injectTime: Byte, val injectTime: Byte,
val batteryRemain: Byte val batteryRemain: Byte
) { ) {
val type: Byte = PumplogUtil.getType(typeAndKind) val type: Byte = PumpLogUtil.getType(typeAndKind)
val kind: Byte = PumplogUtil.getKind(typeAndKind) val kind: Byte = PumpLogUtil.getKind(typeAndKind)
fun getInjectTime(): Int { fun getInjectTime(): Int {
return injectTime and 0xff return injectTime and 0xff
} }
@ -41,18 +42,18 @@ class LOG_INJECT_NORMAL_SUCCESS private constructor(
companion object { companion object {
const val LOG_KIND: Byte = 0x0A const val LOG_KIND: Byte = 0x0A
fun parse(data: String): LOG_INJECT_NORMAL_SUCCESS { fun parse(data: String): LogInjectNormalSuccess {
val bytes = PumplogUtil.hexStringToByteArray(data) val bytes = PumpLogUtil.hexStringToByteArray(data)
val buffer = ByteBuffer.wrap(bytes) val buffer = ByteBuffer.wrap(bytes)
buffer.order(ByteOrder.LITTLE_ENDIAN) buffer.order(ByteOrder.LITTLE_ENDIAN)
return LOG_INJECT_NORMAL_SUCCESS( return LogInjectNormalSuccess(
data, data,
PumplogUtil.getDttm(buffer), PumpLogUtil.getDttm(buffer),
PumplogUtil.getByte(buffer), PumpLogUtil.getByte(buffer),
PumplogUtil.getShort(buffer), PumpLogUtil.getShort(buffer),
PumplogUtil.getShort(buffer), PumpLogUtil.getShort(buffer),
PumplogUtil.getByte(buffer), PumpLogUtil.getByte(buffer),
PumplogUtil.getByte(buffer) PumpLogUtil.getByte(buffer)
) )
} }
} }

View file

@ -7,7 +7,8 @@ import java.nio.ByteOrder
/* /*
* 스퀘어주입 실패 * 스퀘어주입 실패
*/ */
class LOG_INJECT_SQUARE_FAIL private constructor( @Suppress("SpellCheckingInspection")
class LogInjectSquareFail private constructor(
val data: String, val data: String,
val dttm: String, val dttm: String,
typeAndKind: Byte, // 47.5=4750 typeAndKind: Byte, // 47.5=4750
@ -17,8 +18,8 @@ class LOG_INJECT_SQUARE_FAIL private constructor(
val batteryRemain: Byte val batteryRemain: Byte
) { ) {
val type: Byte = PumplogUtil.getType(typeAndKind) val type: Byte = PumpLogUtil.getType(typeAndKind)
val kind: Byte = PumplogUtil.getKind(typeAndKind) val kind: Byte = PumpLogUtil.getKind(typeAndKind)
fun getInjectTime(): Int { fun getInjectTime(): Int {
return injectTime and 0xff return injectTime and 0xff
@ -42,18 +43,18 @@ class LOG_INJECT_SQUARE_FAIL private constructor(
companion object { companion object {
const val LOG_KIND: Byte = 0x0E const val LOG_KIND: Byte = 0x0E
fun parse(data: String): LOG_INJECT_SQUARE_FAIL { fun parse(data: String): LogInjectSquareFail {
val bytes = PumplogUtil.hexStringToByteArray(data) val bytes = PumpLogUtil.hexStringToByteArray(data)
val buffer = ByteBuffer.wrap(bytes) val buffer = ByteBuffer.wrap(bytes)
buffer.order(ByteOrder.LITTLE_ENDIAN) buffer.order(ByteOrder.LITTLE_ENDIAN)
return LOG_INJECT_SQUARE_FAIL( return LogInjectSquareFail(
data, data,
PumplogUtil.getDttm(buffer), PumpLogUtil.getDttm(buffer),
PumplogUtil.getByte(buffer), PumpLogUtil.getByte(buffer),
PumplogUtil.getShort(buffer), PumpLogUtil.getShort(buffer),
PumplogUtil.getByte(buffer), PumpLogUtil.getByte(buffer),
PumplogUtil.getByte(buffer), PumpLogUtil.getByte(buffer),
PumplogUtil.getByte(buffer) PumpLogUtil.getByte(buffer)
) )
} }
} }

View file

@ -7,17 +7,18 @@ import java.nio.ByteOrder
/* /*
* 스퀘어주입 성공 * 스퀘어주입 성공
*/ */
class LOG_INJECT_SQUARE_SUCCESS private constructor( @Suppress("SpellCheckingInspection")
class LogInjectSquareSuccess private constructor(
val data: String, val data: String,
val dttm: String, val dttm: String,
typeAndKind: Byte, // 47.5=4750 typeAndKind: Byte, // 47.5=4750
val injectAmount: Short, // 1분단위 주입시간(124=124분=2시간4분) private val injectAmount: Short, // 1분단위 주입시간(124=124분=2시간4분)
private val injectTime: Byte, private val injectTime: Byte,
val batteryRemain: Byte val batteryRemain: Byte
) { ) {
val type: Byte = PumplogUtil.getType(typeAndKind) val type: Byte = PumpLogUtil.getType(typeAndKind)
val kind: Byte = PumplogUtil.getKind(typeAndKind) val kind: Byte = PumpLogUtil.getKind(typeAndKind)
fun getInjectTime(): Int { fun getInjectTime(): Int {
return injectTime and 0xff return injectTime and 0xff
} }
@ -39,17 +40,17 @@ class LOG_INJECT_SQUARE_SUCCESS private constructor(
companion object { companion object {
const val LOG_KIND: Byte = 0x0D const val LOG_KIND: Byte = 0x0D
fun parse(data: String): LOG_INJECT_SQUARE_SUCCESS { fun parse(data: String): LogInjectSquareSuccess {
val bytes = PumplogUtil.hexStringToByteArray(data) val bytes = PumpLogUtil.hexStringToByteArray(data)
val buffer = ByteBuffer.wrap(bytes) val buffer = ByteBuffer.wrap(bytes)
buffer.order(ByteOrder.LITTLE_ENDIAN) buffer.order(ByteOrder.LITTLE_ENDIAN)
return LOG_INJECT_SQUARE_SUCCESS( return LogInjectSquareSuccess(
data, data,
PumplogUtil.getDttm(buffer), PumpLogUtil.getDttm(buffer),
PumplogUtil.getByte(buffer), PumpLogUtil.getByte(buffer),
PumplogUtil.getShort(buffer), PumpLogUtil.getShort(buffer),
PumplogUtil.getByte(buffer), PumpLogUtil.getByte(buffer),
PumplogUtil.getByte(buffer) PumpLogUtil.getByte(buffer)
) )
} }
} }

View file

@ -6,7 +6,8 @@ import java.nio.ByteOrder
/* /*
* 당일 주입 총량 (식사, 추가) * 당일 주입 총량 (식사, 추가)
*/ */
class LOG_INJECTION_1DAY private constructor( @Suppress("SpellCheckingInspection")
class LogInjection1Day private constructor(
val data: String, val data: String,
val dttm: String, val dttm: String,
typeAndKind: Byte, // 당일 식사주입 총량 47.5=4750 typeAndKind: Byte, // 당일 식사주입 총량 47.5=4750
@ -15,8 +16,8 @@ class LOG_INJECTION_1DAY private constructor(
val batteryRemain: Byte val batteryRemain: Byte
) { ) {
val type: Byte = PumplogUtil.getType(typeAndKind) val type: Byte = PumpLogUtil.getType(typeAndKind)
val kind: Byte = PumplogUtil.getKind(typeAndKind) val kind: Byte = PumpLogUtil.getKind(typeAndKind)
override fun toString(): String { override fun toString(): String {
val sb = StringBuilder("LOG_INJECTION_1DAY{") val sb = StringBuilder("LOG_INJECTION_1DAY{")
@ -35,17 +36,17 @@ class LOG_INJECTION_1DAY private constructor(
companion object { companion object {
const val LOG_KIND: Byte = 0x2F const val LOG_KIND: Byte = 0x2F
fun parse(data: String): LOG_INJECTION_1DAY { fun parse(data: String): LogInjection1Day {
val bytes = PumplogUtil.hexStringToByteArray(data) val bytes = PumpLogUtil.hexStringToByteArray(data)
val buffer = ByteBuffer.wrap(bytes) val buffer = ByteBuffer.wrap(bytes)
buffer.order(ByteOrder.LITTLE_ENDIAN) buffer.order(ByteOrder.LITTLE_ENDIAN)
return LOG_INJECTION_1DAY( return LogInjection1Day(
data, data,
PumplogUtil.getDttm(buffer), PumpLogUtil.getDttm(buffer),
PumplogUtil.getByte(buffer), PumpLogUtil.getByte(buffer),
PumplogUtil.getShort(buffer), PumpLogUtil.getShort(buffer),
PumplogUtil.getShort(buffer), PumpLogUtil.getShort(buffer),
PumplogUtil.getByte(buffer) PumpLogUtil.getByte(buffer)
) )
} }
} }

View file

@ -6,7 +6,8 @@ import java.nio.ByteOrder
/* /*
* 당일 주입 총량 (기저) * 당일 주입 총량 (기저)
*/ */
class LOG_INJECTION_1DAY_BASAL private constructor( @Suppress("SpellCheckingInspection")
class LogInjection1DayBasal private constructor(
val data: String, val data: String,
val dttm: String, val dttm: String,
typeAndKind: Byte, typeAndKind: Byte,
@ -15,8 +16,8 @@ class LOG_INJECTION_1DAY_BASAL private constructor(
val batteryRemain: Byte val batteryRemain: Byte
) { ) {
val type: Byte = PumplogUtil.getType(typeAndKind) val type: Byte = PumpLogUtil.getType(typeAndKind)
val kind: Byte = PumplogUtil.getKind(typeAndKind) val kind: Byte = PumpLogUtil.getKind(typeAndKind)
override fun toString(): String { override fun toString(): String {
val sb = StringBuilder("LOG_INJECTION_1DAY_BASAL{") val sb = StringBuilder("LOG_INJECTION_1DAY_BASAL{")
@ -33,16 +34,16 @@ class LOG_INJECTION_1DAY_BASAL private constructor(
companion object { companion object {
const val LOG_KIND: Byte = 0x2E const val LOG_KIND: Byte = 0x2E
fun parse(data: String): LOG_INJECTION_1DAY_BASAL { fun parse(data: String): LogInjection1DayBasal {
val bytes = PumplogUtil.hexStringToByteArray(data) val bytes = PumpLogUtil.hexStringToByteArray(data)
val buffer = ByteBuffer.wrap(bytes) val buffer = ByteBuffer.wrap(bytes)
buffer.order(ByteOrder.LITTLE_ENDIAN) buffer.order(ByteOrder.LITTLE_ENDIAN)
return LOG_INJECTION_1DAY_BASAL( return LogInjection1DayBasal(
data, data,
PumplogUtil.getDttm(buffer), PumpLogUtil.getDttm(buffer),
PumplogUtil.getByte(buffer), PumpLogUtil.getByte(buffer),
PumplogUtil.getShort(buffer), PumpLogUtil.getShort(buffer),
PumplogUtil.getByte(buffer) PumpLogUtil.getByte(buffer)
) )
} }
} }

View file

@ -6,7 +6,8 @@ import java.nio.ByteOrder
/* /*
* 1시간 단위 기저 주입량 * 1시간 단위 기저 주입량
*/ */
class LOG_INJECTION_1HOUR_BASAL private constructor( @Suppress("SpellCheckingInspection")
class LogInjection1HourBasal private constructor(
val data: String, val data: String,
val dttm: String, val dttm: String,
typeAndKind: Byte, typeAndKind: Byte,
@ -17,8 +18,8 @@ class LOG_INJECTION_1HOUR_BASAL private constructor(
private val remainTotalAmount: Short private val remainTotalAmount: Short
) { ) {
val type: Byte = PumplogUtil.getType(typeAndKind) val type: Byte = PumpLogUtil.getType(typeAndKind)
val kind: Byte = PumplogUtil.getKind(typeAndKind) val kind: Byte = PumpLogUtil.getKind(typeAndKind)
val beforeAmount // 해당시간의 임시기저 계산 전 기저주입량: 기저주입막힘 발생 시 기저주입 막힘량 제외, 기저정지로 인해 주입되지 않은 량 제외, 리셋으로 인해 주입되지 않은 량 제외(47.5=4750) val beforeAmount // 해당시간의 임시기저 계산 전 기저주입량: 기저주입막힘 발생 시 기저주입 막힘량 제외, 기저정지로 인해 주입되지 않은 량 제외, 리셋으로 인해 주입되지 않은 량 제외(47.5=4750)
: Short = tbBeforeAmount : Short = tbBeforeAmount
val afterAmount // 해당시간의 임시기저 계산 후 기저주입량: 기저주입막힘 발생 시 기저주입 막힘량 제외, 기저정지로 인해 주입되지 않은 량 제외, 리셋으로 인해 주입되지 않은 량 제외(47.5=4750) val afterAmount // 해당시간의 임시기저 계산 후 기저주입량: 기저주입막힘 발생 시 기저주입 막힘량 제외, 기저정지로 인해 주입되지 않은 량 제외, 리셋으로 인해 주입되지 않은 량 제외(47.5=4750)
@ -42,18 +43,18 @@ class LOG_INJECTION_1HOUR_BASAL private constructor(
companion object { companion object {
const val LOG_KIND: Byte = 0x2C const val LOG_KIND: Byte = 0x2C
fun parse(data: String): LOG_INJECTION_1HOUR_BASAL { fun parse(data: String): LogInjection1HourBasal {
val bytes = PumplogUtil.hexStringToByteArray(data) val bytes = PumpLogUtil.hexStringToByteArray(data)
val buffer = ByteBuffer.wrap(bytes) val buffer = ByteBuffer.wrap(bytes)
buffer.order(ByteOrder.LITTLE_ENDIAN) buffer.order(ByteOrder.LITTLE_ENDIAN)
return LOG_INJECTION_1HOUR_BASAL( return LogInjection1HourBasal(
data, data,
PumplogUtil.getDttm(buffer), PumpLogUtil.getDttm(buffer),
PumplogUtil.getByte(buffer), PumpLogUtil.getByte(buffer),
PumplogUtil.getShort(buffer), PumpLogUtil.getShort(buffer),
PumplogUtil.getShort(buffer), PumpLogUtil.getShort(buffer),
PumplogUtil.getByte(buffer), PumpLogUtil.getByte(buffer),
PumplogUtil.getShort(buffer) PumpLogUtil.getShort(buffer)
) )
} }
} }

View file

@ -7,18 +7,19 @@ import java.nio.ByteOrder
/* /*
* 듀얼(일반) 주입량: 듀얼(일반) 주입 완료 기록하는 방식 * 듀얼(일반) 주입량: 듀얼(일반) 주입 완료 기록하는 방식
*/ */
class LOG_INJECTION_DUAL_NORMAL private constructor( @Suppress("SpellCheckingInspection")
class LogInjectionDualNormal private constructor(
val data: String, val data: String,
val dttm: String, val dttm: String,
typeAndKind: Byte, // 설정량 47.5=4750 typeAndKind: Byte, // 설정량 47.5=4750
val setAmount: Short, // 주입량 47.5=4750 private val setAmount: Short, // 주입량 47.5=4750
val injectAmount: Short, // 1분 단위 주입 시간 Ex) 124 = 124분 = 2시간 4분 val injectAmount: Short, // 1분 단위 주입 시간 Ex) 124 = 124분 = 2시간 4분
private val injectTime: Byte, private val injectTime: Byte,
val batteryRemain: Byte val batteryRemain: Byte
) { ) {
val type: Byte = PumplogUtil.getType(typeAndKind) val type: Byte = PumpLogUtil.getType(typeAndKind)
val kind: Byte = PumplogUtil.getKind(typeAndKind) val kind: Byte = PumpLogUtil.getKind(typeAndKind)
fun getInjectTime(): Int { fun getInjectTime(): Int {
return injectTime and 0xff return injectTime and 0xff
} }
@ -41,18 +42,18 @@ class LOG_INJECTION_DUAL_NORMAL private constructor(
companion object { companion object {
const val LOG_KIND: Byte = 0x35 const val LOG_KIND: Byte = 0x35
fun parse(data: String): LOG_INJECTION_DUAL_NORMAL { fun parse(data: String): LogInjectionDualNormal {
val bytes = PumplogUtil.hexStringToByteArray(data) val bytes = PumpLogUtil.hexStringToByteArray(data)
val buffer = ByteBuffer.wrap(bytes) val buffer = ByteBuffer.wrap(bytes)
buffer.order(ByteOrder.LITTLE_ENDIAN) buffer.order(ByteOrder.LITTLE_ENDIAN)
return LOG_INJECTION_DUAL_NORMAL( return LogInjectionDualNormal(
data, data,
PumplogUtil.getDttm(buffer), PumpLogUtil.getDttm(buffer),
PumplogUtil.getByte(buffer), PumpLogUtil.getByte(buffer),
PumplogUtil.getShort(buffer), PumpLogUtil.getShort(buffer),
PumplogUtil.getShort(buffer), PumpLogUtil.getShort(buffer),
PumplogUtil.getByte(buffer), PumpLogUtil.getByte(buffer),
PumplogUtil.getByte(buffer) PumpLogUtil.getByte(buffer)
) )
} }
} }

Some files were not shown because too many files have changed in this diff Show more