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 address: String
val nsClientService: NSClientService?
fun pause(newState: Boolean)
fun resend(reason: String)
@ -24,9 +23,6 @@ interface NsClient : Sync {
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 info.nightscout.sdk.exceptions.DateHeaderOutOfToleranceException
import info.nightscout.sdk.exceptions.InvalidAccessTokenException
import info.nightscout.sdk.exceptions.InvalidFormatNightscoutException
import info.nightscout.sdk.exceptions.TodoNightscoutException
import info.nightscout.sdk.exceptions.UnknownResponseNightscoutException
import info.nightscout.sdk.interfaces.NSAndroidClient
import info.nightscout.sdk.localmodel.Status
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.mapper.toLocal
import info.nightscout.sdk.mapper.toRemoteTreatment
import info.nightscout.sdk.mapper.toSgv
import info.nightscout.sdk.mapper.toTreatment
import info.nightscout.sdk.networking.NetworkStackBuilder
@ -58,6 +62,8 @@ class NSAndroidClientImpl(
accessToken = accessToken,
logging = logging
)
override var lastStatus: Status? = null
private set
/*
* TODO: how should our result look like?
@ -81,7 +87,7 @@ class NSAndroidClientImpl(
}
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
@ -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 =
withContext(dispatcher) {
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.entry.NSSgvV3
import info.nightscout.sdk.localmodel.treatment.CreateUpdateResponse
import info.nightscout.sdk.localmodel.treatment.NSTreatment
import info.nightscout.sdk.remotemodel.LastModified
import info.nightscout.sdk.remotemodel.RemoteDeviceStatus
interface NSAndroidClient {
val lastStatus: Status?
suspend fun getVersion(): String
suspend fun getStatus(): Status
suspend fun getEntries(): String
@ -18,4 +20,5 @@ interface NSAndroidClient {
suspend fun getSgvsNewerThan(from: Long, limit: Long): List<NSSgvV3>
suspend fun getTreatmentsModifiedSince(from: Long, limit: Long): List<NSTreatment>
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 settings: 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 identifier: String,
override val units: NsUnits?,
override val srvModified: Long,
override val srvCreated: Long,
override val srvModified: Long?,
override val srvCreated: Long?,
override val utcOffset: Long,
override val subject: String?,
override var isReadOnly: Boolean,

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -8,8 +8,8 @@ data class NSTemporaryBasal(
override val device: String?,
override val identifier: String,
override val units: NsUnits?,
override val srvModified: Long,
override val srvCreated: Long,
override val srvModified: Long?,
override val srvCreated: Long?,
override val utcOffset: Long,
override val subject: String?,
override var isReadOnly: Boolean,
@ -21,9 +21,11 @@ data class NSTemporaryBasal(
override val pumpType: String?,
override val pumpSerial: String?,
val duration: Long,
val rate: Double,
val rate: Double, // when sending to NS always convertedToAbsolute(timestamp, profile)
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 {
enum class Type {

View file

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

View file

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

View file

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

View file

@ -117,7 +117,7 @@ internal fun RemoteTreatment.toTreatment(): NSTreatment? {
pumpSerial = extendedEmulated.pumpSerial,
enteredinsulin = extendedEmulated.enteredinsulin ?: 0.0,
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,
enteredinsulin = this.enteredinsulin,
duration = this.durationInMilliseconds ?: TimeUnit.MINUTES.toMillis(this.duration ?: 0L),
isEmulatingTempbasal = this.isEmulatingTempBasal
isEmulatingTempBasal = this.isEmulatingTempBasal
)
}
}
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.RemoteDeviceStatus
import info.nightscout.sdk.remotemodel.NSResponse
import info.nightscout.sdk.remotemodel.RemoteCreateUpdateResponse
import info.nightscout.sdk.remotemodel.RemoteEntry
import info.nightscout.sdk.remotemodel.RemoteStatusResponse
import info.nightscout.sdk.remotemodel.RemoteTreatment
import okhttp3.RequestBody
import retrofit2.Call
import retrofit2.Response
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.Header
import retrofit2.http.POST
import retrofit2.http.Path
import retrofit2.http.Query
@ -48,4 +54,8 @@ internal interface NightscoutRemoteService {
@GET("v3/devicestatus/history/{from}")
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
)
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(
@SerializedName("devicestatus") val deviceStatus: RemoteApiPermission,
@SerializedName("entries") val entries: RemoteApiPermission,

View file

@ -18,72 +18,71 @@ import org.json.JSONObject
* */
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("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("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("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("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("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
// document) or it is automatically parsed from the date field.
@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? = 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? = 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? = 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? = 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.
// @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("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("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("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("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("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("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("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? = 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? = 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? = 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? = 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? = 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? = 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("glucose") val glucose: Double?, // double Current glucose
@SerializedName("glucoseType") val glucoseType: String?, // 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("carbs") val carbs: Double?, // number... Amount of carbs given.
@SerializedName("protein") val protein: Int?, // number... Amount of protein given.
@SerializedName("fat") val fat: Int?, // number... Amount of fat given.
@SerializedName("insulin") val insulin: Double?, // number... Amount of insulin, if any.
@SerializedName("duration") val duration: Long?, // number... Duration in minutes.
@SerializedName("durationInMilliseconds") val durationInMilliseconds: Long?, // number... Duration in milliseconds.
@SerializedName("preBolus") val preBolus: Int?, // 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("splitExt") val splitExt: Int?, // number... Extended part of combo bolus (in percent).
@SerializedName("percent") val percent: Double?, // number... Eventual basal change in percent.
@SerializedName("absolute") val absolute: Double?, // number... Eventual basal change in absolute value (insulin units per hour).
@SerializedName("targetTop") val targetTop: Double?, // number... Top limit of temporary target.
@SerializedName("targetBottom") val targetBottom: Double?, // number... Bottom limit of temporary target.
@SerializedName("profile") val profile: String?, // 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("notes") val notes: String?, // string Description/notes of treatment.
@SerializedName("enteredBy") val enteredBy: String?, // string Who entered the treatment.
@SerializedName("glucose") val glucose: Double? = null, // double Current glucose
@SerializedName("glucoseType") val glucoseType: String? = null, // string example: "Sensor", "Finger", "Manual"
@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? = null, // number... Amount of carbs given.
@SerializedName("protein") val protein: Int? = null, // number... Amount of protein given.
@SerializedName("fat") val fat: Int? = null, // number... Amount of fat given.
@SerializedName("insulin") val insulin: Double? = null, // number... Amount of insulin, if any.
@SerializedName("duration") val duration: Long? = null, // number... Duration in minutes.
@SerializedName("durationInMilliseconds") val durationInMilliseconds: Long? = null, // number... Duration in milliseconds.
@SerializedName("preBolus") val preBolus: Int? = null, // number... How many minutes the bolus was given before the meal started.
@SerializedName("splitNow") val splitNow: Int? = null, // number... Immediate 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? = null, // number... Eventual basal change in percent.
@SerializedName("absolute") val absolute: Double? = null, // number... Eventual basal change in absolute value (insulin units per hour).
@SerializedName("targetTop") val targetTop: Double? = null, // number... Top limit of temporary target.
@SerializedName("targetBottom") val targetBottom: Double? = null, // number... Bottom limit of temporary target.
@SerializedName("profile") val profile: String? = null, // string Name of the profile to which the pump has been switched.
@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? = null, // string Description/notes of 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("pumpId") val pumpId: Long?, // 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("pumpSerial") val pumpSerial: String?, // string "Meal Bolus", "Correction Bolus", "Combo Bolus" "33013206",
@SerializedName("endId") val endId: Long? = null, // long id of record which ended this
@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? = null, // string "Meal Bolus", "Correction Bolus", "Combo Bolus" ex "ACCU_CHEK_INSIGHT_BLUETOOTH",
@SerializedName("pumpSerial") val pumpSerial: String? = null, // string "Meal Bolus", "Correction Bolus", "Combo Bolus" "33013206",
// 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}]}",
@SerializedName("originalProfileName") val originalProfileName: String?, // string "Effective Profile Switch"
@SerializedName("originalCustomizedName") val originalCustomizedName: String?, // string "Effective Profile Switch"
@SerializedName("originalTimeshift") val originalTimeshift: Long?, // long "Effective Profile Switch"
@SerializedName("originalPercentage") val originalPercentage: Int?, // int "Effective Profile Switch"
@SerializedName("originalDuration") val originalDuration: Long?, // long "Effective Profile Switch"
@SerializedName("originalEnd") val originalEnd: Long?, // long "Effective Profile Switch"
@SerializedName("originalProfileName") val originalProfileName: String? = null, // string "Effective Profile Switch"
@SerializedName("originalCustomizedName") val originalCustomizedName: String? = null, // string "Effective Profile Switch"
@SerializedName("originalTimeshift") val originalTimeshift: Long? = null, // long "Effective Profile Switch"
@SerializedName("originalPercentage") val originalPercentage: Int? = null, // int "Effective Profile Switch"
@SerializedName("originalDuration") val originalDuration: Long? = null, // 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("type") val type: String?, // 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("enteredinsulin") val enteredinsulin: Double?, // 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("isEmulatingTempBasal") val isEmulatingTempBasal: Boolean, // boolean "Combo Bolus", "extendedEmulated" (not in doc see below)
@SerializedName("isAnnouncement") val isAnnouncement: Boolean, // boolean "Announcement"
@SerializedName("rate") val rate: Double?, // Double "Temp Basal" absolute rate (could be calculated with percent and profile information...)
@SerializedName("extendedEmulated") val extendedEmulated: RemoteTreatment?, // Gson of emulated EB
@SerializedName("timeshift") val timeshift: Long, // integer "Profile Switch"
@SerializedName("percentage") val percentage: Int?, // integer "Profile Switch"
@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? = null, // string "Meal Bolus", "Correction Bolus", "Combo Bolus", "Temp Basal" type of bolus "NORMAL", "SMB", "FAKE_EXTENDED"
@SerializedName("isSMB") val isSMB: Boolean? = null, // boolean "Meal Bolus", "Correction Bolus", "Combo Bolus"
@SerializedName("enteredinsulin") val enteredinsulin: Double? = null, // number... "Combo Bolus" insulin is missing only enteredinsulin field found
@SerializedName("relative") val relative: Double? = null, // number... "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? = null, // boolean "Announcement"
@SerializedName("rate") val rate: Double? = null, // Double "Temp Basal" absolute rate (could be calculated with percent and profile information...)
@SerializedName("extendedEmulated") val extendedEmulated: RemoteTreatment? = null, // Gson of emulated EB
@SerializedName("timeshift") val timeshift: Long? = null, // integer "Profile Switch"
@SerializedName("percentage") val percentage: Int? = null // integer "Profile Switch"
) {
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 =

View file

@ -1,4 +1,4 @@
package info.nightscout.androidaps.utils.extensions
package info.nightscout.core.ui.extensions
import android.widget.RadioGroup
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_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="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="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>
@ -161,6 +162,8 @@
<string name="dia">DAI</string>
<string name="ic_short">G/I</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="suspendloop_label">Boucle désactivée/suspendue</string>
<string name="iob_label">Insuline Active (IA)</string>
@ -246,6 +249,7 @@
<!-- CarbsReq-->
<string name="carbsreq">%1$dg de glucides requis dans %2$d min.</string>
<!-- TDDStatsActivity-->
<string name="cumulative_tdd">DTQ cumulée</string>
<string name="expweight">DTQ avec Pondération Exponentielle</string>
<string name="basalrate">Basal</string>
<string name="bolus">Bolus</string>

View file

@ -419,7 +419,7 @@
<string name="autotune_warning">Aviso :</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_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_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>

View file

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

View file

@ -483,7 +483,7 @@
<!-- Constraints-->
<string name="limitingbasalratio">最大基础率被限定为 %1$.2f U/h 由于 %2$s</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="limitingbolus">由于 %2$s, 将大剂量限制为 %1$.1f U</string>
<!-- Locale -->

View file

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

View file

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

View file

@ -89,14 +89,14 @@ class AutotuneFS @Inject constructor(
}
fun exportPumpProfile(profile: ATProfile) {
createAutotunefile(PUMPPROFILE, profile.profiletoOrefJSON(), true)
createAutotunefile(PUMPPROFILE, profile.profiletoOrefJSON())
createAutotunefile(PUMPPROFILE, profile.profileToOrefJSON(), true)
createAutotunefile(PUMPPROFILE, profile.profileToOrefJSON())
}
fun exportTunedProfile(tunedProfile: ATProfile) {
createAutotunefile(TUNEDPROFILE + formatDate(tunedProfile.from) + ".json", tunedProfile.profiletoOrefJSON())
createAutotunefile(TUNEDPROFILE + formatDate(tunedProfile.from) + ".json", tunedProfile.profileToOrefJSON())
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) {
}
}

View file

@ -28,9 +28,9 @@ import info.nightscout.interfaces.Constants
import info.nightscout.interfaces.GlucoseUnit
import info.nightscout.interfaces.logging.UserEntryLogger
import info.nightscout.interfaces.plugin.ActivePlugin
import info.nightscout.interfaces.profile.Instantiator
import info.nightscout.interfaces.profile.Profile
import info.nightscout.interfaces.profile.ProfileFunction
import info.nightscout.interfaces.profile.Instantiator
import info.nightscout.interfaces.profile.ProfileStore
import info.nightscout.interfaces.ui.UiInteraction
import info.nightscout.interfaces.utils.MidnightTime
@ -149,12 +149,12 @@ class AutotuneFragment : DaggerFragment() {
}
binding.autotuneUpdateProfile.setOnClickListener {
val localName = autotunePlugin.pumpProfile.profilename
val localName = autotunePlugin.pumpProfile.profileName
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_local_profile_message, localName),
Runnable {
autotunePlugin.tunedProfile?.profilename = localName
autotunePlugin.tunedProfile?.profileName = localName
autotunePlugin.updateProfile(autotunePlugin.tunedProfile)
autotunePlugin.updateButtonVisibility = View.GONE
autotunePlugin.saveLastRun()
@ -169,12 +169,12 @@ class AutotuneFragment : DaggerFragment() {
}
binding.autotuneRevertProfile.setOnClickListener {
val localName = autotunePlugin.pumpProfile.profilename
val localName = autotunePlugin.pumpProfile.profileName
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_local_profile_message, localName),
Runnable {
autotunePlugin.tunedProfile?.profilename = ""
autotunePlugin.tunedProfile?.profileName = ""
autotunePlugin.updateProfile(autotunePlugin.pumpProfile)
autotunePlugin.updateButtonVisibility = View.VISIBLE
autotunePlugin.saveLastRun()
@ -192,11 +192,11 @@ class AutotuneFragment : DaggerFragment() {
val pumpProfile = profileFunction.getProfile()?.let { currentProfile ->
profileStore.getSpecificProfile(profileName)?.let { specificProfile ->
ATProfile(ProfileSealed.Pure(specificProfile), LocalInsulin(""), injector).also {
it.profilename = profileName
it.profileName = profileName
}
}
?: ATProfile(currentProfile, LocalInsulin(""), injector).also {
it.profilename = profileFunction.getProfileName()
it.profileName = profileFunction.getProfileName()
}
}
pumpProfile?.let {
@ -205,7 +205,7 @@ class AutotuneFragment : DaggerFragment() {
time = dateUtil.now(),
mode = UiInteraction.Mode.CUSTOM_PROFILE,
customProfile = pumpProfile.profile.toPureNsJson(dateUtil).toString(),
customProfileName = pumpProfile.profilename
customProfileName = pumpProfile.profileName
)
}
}
@ -219,7 +219,7 @@ class AutotuneFragment : DaggerFragment() {
time = dateUtil.now(),
mode = UiInteraction.Mode.PROFILE_COMPARE,
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()
)
}
@ -231,17 +231,17 @@ class AutotuneFragment : DaggerFragment() {
tunedProfile?.let { tunedP ->
tunedP.profileStore(circadian)?.let {
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(
UserEntry.Action.STORE_PROFILE,
UserEntry.Sources.Autotune,
ValueWithUnit.SimpleString(tunedP.profilename)
ValueWithUnit.SimpleString(tunedP.profileName)
)
val now = dateUtil.now()
if (profileFunction.createProfileSwitch(
it,
profileName = tunedP.profilename,
profileName = tunedP.profileName,
durationInMinutes = 0,
percentage = 100,
timeShiftInHours = 0,
@ -252,7 +252,7 @@ class AutotuneFragment : DaggerFragment() {
UserEntry.Action.PROFILE_SWITCH,
UserEntry.Sources.Autotune,
"Autotune AutoSwitch",
ValueWithUnit.SimpleString(autotunePlugin.tunedProfile!!.profilename)
ValueWithUnit.SimpleString(autotunePlugin.tunedProfile!!.profileName)
)
}
rxBus.send(EventLocalProfileChanged())
@ -472,7 +472,7 @@ class AutotuneFragment : DaggerFragment() {
val time = df.format(h.toLong()) + ":00"
totalPump += autotunePlugin.pumpProfile.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", " "))
}

View file

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

View file

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

View file

@ -127,5 +127,6 @@
<string name="saturday_short">S</string>
<string name="sunday_short">D</string>
<!-- 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>
</resources>

View file

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

View file

@ -1,12 +1,12 @@
package info.nightscout.plugins.constraints.safety
import dagger.android.HasAndroidInjector
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.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.interfaces.Config
import info.nightscout.interfaces.ApsMode
import info.nightscout.interfaces.constraints.Constraint

View file

@ -1,145 +1,68 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="dia_whatmeansdia">¿Qué es cierto acerca de DIA?</string>
<string name="dia_label_exam">Duración de la acción de insulina (DIA)</string>
<string name="dia_profile">Debes establecer el valor de DIA en tu perfil.</string>
<string name="dia_minimumis5h">El valor mínimo permitido es 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 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ías determinar por ti mismo el valor apropiado para DIA.</string>
<string name="hypott_label">Objetivo temporal ante Hipoglucemia</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="dia_whatmeansdia">¿Qué es cierto acerca de DAI?</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 DAI en tu perfil.</string>
<string name="dia_minimumis5h">El valor mínimo permitido es de 5 horas.</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_valuemustbedetermined">Deberás determinar por ti mismo el valor apropiado para DAI.</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="pumpdisconnect_openloop">Se activará el modo de bucle abierto en AAPS.</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="objectives2_label">Ajustes de AAPS</string>
<string name="objectives_howtosave">¿Cuáles son las mejores prácticas para hacer copias de seguridad de sus configuraciones?</string>
<string name="objectives_notesettings">No necesita exportar sus configuraciones siempre que haga una nota de ellos.</string>
<string name="objectives_afterobjective">Exporta tu configuración después de completar un objetivo.</string>
<string name="objectives_afterchange">Exportar la configuración después de cambiar cualquiera de sus ajustes.</string>
<string name="objectives_afterinitialsetup">Exportar la configuración una vez finalizada la configuración inicial y haber establecido sus preferencias.</string>
<string name="objectives2_maintenance">Exportar la configuración localmente usando el menú de mantenimiento.</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="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="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="objectives_hint1">https://androidaps.readthedocs.io/en/latest/EN/Usage/ExportImportSettings.html</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="noisycgm_label">Lecturas CGM ruidosas</string>
<string name="noisycgm_whattodo">¿Qué se debe hacer si los datos de CGM tienen ruido?</string>
<string name="noisycgm_nothing">No hacer nada: AAPS se ocupará de ello.</string>
<string name="noisycgm_pause">Deshabilita el lazo cerrado para evitar posibles sobredosis o subdosis.</string>
<string name="noisycgm_replacesensor">Sustituya los sensores con valores ruidosos o inexactos.</string>
<string name="noisycgm_checksmoothing">Comprueba que tu aplicación del CGM proporciona datos suavizados.</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="exerciseprofile_label">Ejercicio y perfiles</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="exerciseprofile_switchprofilebelow100">Haga un cambio de perfil a menos de 100%.</string>
<string name="exerciseprofile_switchprofileabove100">Haga un cambio de perfil a más de 100%.</string>
<string name="exerciseprofile_leaveat100">Dejar el perfil configurado al 100%.</string>
<string name="exerciseprofile_suspendloop">Suspender el lazo</string>
<string name="exerciseprofile_hint1">https://androidaps.readthedocs.io/en/latest/EN/Usage/temptarget.html#activity-temp-target</string>
<string name="exercise_label">Ejercicios y objetivos temporales</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="exercise_settt">Establece un objetivo de glucosa en la sangre actividad que comienza un tiempo adecuado antes de comenzar el ejercicio.</string>
<string name="exercise_setfinished">Establece un objetivo de glucosa en la sangre actividad después de finalizar el ejercicio.</string>
<string name="exercise_setunchanged">Deja tu objetivo de glucosa sanguíneo sin cambios.</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="exercise_hint1">https://androidaps.readthedocs.io/en/latest/EN/Usage/temptarget.html#activity-temp-target</string>
<string name="suspendloop_doigetinsulin">¿Recibo insulina cuando el lazo está desactivado/suspendido?</string>
<string name="suspendloop_yes">Sí, la insulina basal sigue siendo entregada.</string>
<string name="suspendloop_no">No, la administración de la insulina está detenida.</string>
<string name="basaltest_label">Pruebas basales, ISF, e I:C</string>
<string name="basaltest_when">¿Cuándo se deben validar estos valores?</string>
<string name="basaltest_beforeloop">Antes de empezar el lazo</string>
<string name="basaltest_havingregularhighlow">Cuando se tienen valores de glucosa altos o bajos frecuentemente.</string>
<string name="basaltest_weekly">Al menos una vez a la semana.</string>
<string name="basaltest_fixed">Una vez fijados y validados, estos valores no debrían cambiar a lo largo del tiempo.</string>
<string name="basaltest_hint1">https://androidaps.readthedocs.io/en/latest/EN/Getting-Started/FAQ.html#androidaps-settings</string>
<string name="prerequisites_label">Requisitos previos</string>
<string name="prerequisites_what">¿Qué es esencial para configurar y utilizar AAPS?</string>
<string name="prerequisites_determinedcorrectprofile">Información de perfil validada (Basal, IC, ISF, DIA).</string>
<string name="prerequisites_computer">Un ordenador con Android Studio instalado y configurado.</string>
<string name="prerequisites_phone">Un teléfono compatible.</string>
<string name="prerequisites_pump">Una bomba de insulina compatible, si planeas usar el sistema en modo \"lazo cerrado\".</string>
<string name="prerequisites_nightscout">Nightscout, para tener un registro de los datos y revisar los parámetros de configuración.</string>
<string name="prerequisites_tidepoolaccount">Una cuenta de Tidepool.</string>
<string name="prerequisites_googleaccount">Una cuenta de Google.</string>
<string name="prerequisites_githubaccount">Una cuenta de Github.</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="objectives_notesettings">No necesita exportar sus configuraciones siempre que haga las tenga anotadas.</string>
<string name="objectives_afterobjective">Exportar tu configuración después de completar un objetivo.</string>
<string name="objectives_afterchange">Exportar las configuraciones después de cambiar cualquiera de sus ajustes.</string>
<string name="objectives_afterinitialsetup">Exportar las configuraciones una vez finalizada la configuración inicial y haber establecido sus preferencias.</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="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="noisycgm_label">Lecturas CGM con mucha variabilidad</string>
<string name="noisycgm_whattodo">¿Qué se debe hacer si los datos de CGM tienen mucha variabilidad?</string>
<string name="noisycgm_pause">Deshabilitar el bucle cerrado para evitar posibles sobredosis o subdosis.</string>
<string name="noisycgm_replacesensor">Sustituya el sensor con valores muy variables o inexactos.</string>
<string name="exerciseprofile_whattodo">¿Cómo puede usar los perfiles para mejorar el sistema durante el ejercicio aeróbico?</string>
<string name="exerciseprofile_switchprofilebelow100">Cambie el perfil por un valor menor a 100%.</string>
<string name="exerciseprofile_switchprofileabove100">Cambie el perfil por un valor mayor a 100%.</string>
<string name="exerciseprofile_suspendloop">Suspender el bucle.</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="exercise_settt">Establezca el objetivo de tipo actividad antes de comenzar el ejercicio, considerando un tiempo razonable antes de la actividad.</string>
<string name="exercise_setfinished">Establezca un objetivo de tipo actividad después de finalizar el ejercicio.</string>
<string name="exercise_setunchanged">Deja tu objetivo de glucosa sin cambios.</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="suspendloop_doigetinsulin">¿Puedo recibir insulina cuando el bucle está desactivado/suspendido?</string>
<string name="suspendloop_yes">Sí, la insulina basal sigue siendo suministrada.</string>
<string name="suspendloop_no">No, la administración de la insulina se detiene.</string>
<string name="basaltest_label">Pruebas para basales, I:C y FSI</string>
<string name="basaltest_beforeloop">Antes de empezar cualquier bucle.</string>
<string name="basaltest_havingregularhighlow">Cuando los valores de glucosa son muy altos o bajos de manera frecuente.</string>
<string name="basaltest_fixed">Una vez establecidos y validados, estos valores no deberían cambiar a lo largo del tiempo.</string>
<string name="prerequisites_determinedcorrectprofile">Información de perfil previamente validada (Basal, IC, FSI, DAI).</string>
<string name="prerequisites_computer">Una computadora con Android Studio instalado y configurado.</string>
<string name="prerequisites_pump">Una bomba de insulina compatible, si planeas usar el sistema en modo bucle cerrado.</string>
<string name="prerequisites2_internet">AAPS requiere una conexión a Internet para funcionar con el modo bucle cerrado.</string>
<string name="whatistrue">Seleccione todas las respuestas correctas.</string>
<string name="update_git">Es necesario tener Git instalado y configurado en la computadora.</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="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="update_neverupdate">Nunca se debe actualizar AAPS si el sistema está funcionando bien.</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="troubleshooting_yourendo">Debes preguntar a tu endocrinólogo o educador en diabetes.</string>
<string name="sensitivity_which">Seleccione todas las respuestas correctas.</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="sensitivity_cannula">Registrar el cámbio de cánula reinicia Autosens, volviendo de nuevo al 100%.</string>
<string name="wrongcarbs_label">Error de ingreso de Carbohidratos</string>
<string name="wrongcarbs_whattodo">¿Qué deberías hacer si has cometido un error al ingresar carbohidratos?</string>
<string name="wrongcarbs_treatmentstab">Elimina la entrada incorrecta en pestaña de tratamientos e introduce el valor correcto.</string>
<string name="wrongcarbs_addinsulin">Darse un bolo desde el menú de llenado de la infusión.</string>
<string name="wrongcarbs_donothing">No hacer nada - AAPS realizará los ajustes necesarios.</string>
<string name="wrongcarbs_bolus">Darse un bolo usando el botón de Insulina (bolus) en página general.</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="wronginsulin_compare">Comparar valores en AAPS con el historial de la bomba (si la bomba los registra).</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="wronginsulin_donothing">No hacer nada y permite que AAPS corrija cualquier resultado de nivel alto de glucosa.</string>
<string name="cob_question">¿Cómo afecta el cambio del valor FSI al cálculo de COB?</string>
<string name="cob_longer">Incrementar el FSI hará que los carbohidratos se absorban más lentamente</string>
<string name="cob_shorter">Incrementar el FSI hará que los carbohidratos se absorban más rápidamente</string>
<string name="cob_no_effect">Incrementar el FSI 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_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>

View file

@ -2,12 +2,27 @@
<resources>
<!-- PhoneChecker -->
<!-- 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 -->
<string name="disk_full">Boucle désactivée ! Libérez au moins %1$d Mo du stockage interne !</string>
<!-- 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 -->
<!-- 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>
<!-- 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="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>
@ -17,7 +32,7 @@
<string name="smbnotallowedinopenloopmode">SMB non autorisé en mode boucle ouverte</string>
<string name="maxvalueinpreferences">valeur Max dans les préférences</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 -->
<string name="completed_well_done">Terminé, félicitations !</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_hint2">https://www.facebook.com/groups/AndroidAPSUsers/</string>
<string name="troubleshooting_hint3">https://discord.gg/4fQUWHZ4Mw</string>
<string name="insulin_plugins">Модули для инсулинов</string>
<string name="insulin_ultrarapid">Какой инсулин следует использовать с модулем Сверхбыстрый Oref?</string>
<string name="insulin_fiasp">Fiasp®</string>
<string name="insulin_novorapid">Novoapid ® /Novolog ®</string>

View file

@ -2,11 +2,27 @@
<resources>
<!-- PhoneChecker -->
<!-- DST Helper -->
<string name="dst_in_24h_warning">Переход на летнее/зимнее время через 24 часа или менее</string>
<string name="dst_loop_disabled_warning">Изменение сезонного времени произошло меньше 3 часов назад-Закрытый цикл выключен</string>
<!-- Storage constraint -->
<string name="disk_full">Освободите по крайней мере %1$d MB из внутренней памяти! Цикл остановлен!</string>
<!-- 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 -->
<!-- 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 -->
<string name="limitingextendedbolus">Ограничиваю пролонгированный болюс до %1$.1f ед. из-за %2$s</string>
<string name="limitingcarbs">Ограничение углеводов до %1$d г. из-за %2$s</string>
<string name="pumpisnottempbasalcapable">Помпа не рассчитана на подачу временного базала</string>
<string name="closedmodedisabledinpreferences">Режим замкнутого цикла отключен в настройках</string>
@ -18,6 +34,7 @@
<string name="hardlimit">жесткий предел</string>
<string name="treatmentssafety_title">Безопасность терапии</string>
<!-- Objectives -->
<string name="completed_well_done">Завершено, отлично!</string>
<string name="not_completed_yet">Не завершено</string>
<string name="time_elapsed">Прошло времени</string>
<string name="maxiobset">Максимум активного инсулина IOB установлен правильно</string>

View file

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

View file

@ -1,8 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- 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="rapid_acting_oref">Insuline à Action 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="fast_acting_insulin_comment">Novorapid, Novolog, Humalog</string>
<string name="ultra_fast_acting_insulin_comment">Fiasp</string>
</resources>

View file

@ -1,11 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<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_MMS" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.SEND_MMS" />
<uses-permission android:name="android.permission.INTERNET" />
<application>

View file

@ -7,14 +7,14 @@ import androidx.preference.SwitchPreference
import dagger.android.HasAndroidInjector
import info.nightscout.core.events.EventIobCalculationProgress
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.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.interfaces.Config
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.TimeFormat
import dagger.android.support.DaggerDialogFragment
import info.nightscout.androidaps.utils.extensions.selectedItemPosition
import info.nightscout.androidaps.utils.extensions.setEnableForChildren
import info.nightscout.androidaps.utils.extensions.setSelection
import info.nightscout.core.ui.extensions.selectedItemPosition
import info.nightscout.core.ui.extensions.setEnableForChildren
import info.nightscout.core.ui.extensions.setSelection
import info.nightscout.core.wizard.QuickWizard
import info.nightscout.core.wizard.QuickWizardEntry
import info.nightscout.plugins.R

View file

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

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.WearableListenerService
import dagger.android.AndroidInjection
import info.nightscout.androidaps.plugins.general.wear.events.EventWearUpdateGui
import info.nightscout.core.utils.fabric.FabricPrivacy
import info.nightscout.database.impl.AppRepository
import info.nightscout.interfaces.Config
@ -27,6 +26,7 @@ import info.nightscout.interfaces.profile.ProfileFunction
import info.nightscout.interfaces.receivers.ReceiverStatusStore
import info.nightscout.plugins.R
import info.nightscout.plugins.general.wear.WearPlugin
import info.nightscout.plugins.general.wear.events.EventWearUpdateGui
import info.nightscout.rx.AapsSchedulers
import info.nightscout.rx.bus.RxBus
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)
holder.binding.date.visibility = newDay.toVisibility()
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.direction.setImageResource(glucoseValue.trendArrow.directionToIcon())
if (position > 0) {

View file

@ -1,22 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Source -->
<string name="ns_client_bg">NSClient BG</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="eversense">Eversense App (parchada)</string>
<string name="glunovo">Glunovo</string>
<string name="description_source_glunovo">Recibir los valores de glucosa de la aplicación Glunovo</string>
<string name="intelligo">Intelligo</string>
@ -35,4 +20,5 @@
<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_summary">Crear evento \"Cambio de sensor\" en Nightscout automáticamente al iniciar el sensor</string>
<string name="direction">dirección</string>
</resources>

View file

@ -35,4 +35,5 @@
<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_summary">Créer automatiquement un événement \"Changement de capteur\" dans NS au démarrage du capteur</string>
<string name="direction">direction</string>
</resources>

View file

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

View file

@ -159,7 +159,7 @@ class DataSyncSelectorImplementation @Inject constructor(
}
// without nsId = create new
bolus.first.interfaceIDs.nightscoutId == null ->
activePlugin.activeNsClient?.nsClientService?.dbAdd(
activePlugin.activeNsClient?.dbAdd(
"treatments",
bolus.first.toJson(true, dateUtil),
DataSyncSelector.PairBolus(bolus.first, bolus.second.id),
@ -167,7 +167,7 @@ class DataSyncSelectorImplementation @Inject constructor(
)
// with nsId = update if it's modified record
bolus.first.interfaceIDs.nightscoutId != null && bolus.first.id != bolus.second.id ->
activePlugin.activeNsClient?.nsClientService?.dbUpdate(
activePlugin.activeNsClient?.dbUpdate(
"treatments",
bolus.first.interfaceIDs.nightscoutId,
bolus.first.toJson(false, dateUtil),
@ -222,10 +222,10 @@ class DataSyncSelectorImplementation @Inject constructor(
}
// without nsId = create new
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
carb.first.interfaceIDs.nightscoutId != null && carb.first.id != carb.second.id ->
activePlugin.activeNsClient?.nsClientService?.dbUpdate(
activePlugin.activeNsClient?.dbUpdate(
"treatments",
carb.first.interfaceIDs.nightscoutId,
carb.first.toJson(false, dateUtil),
@ -280,7 +280,7 @@ class DataSyncSelectorImplementation @Inject constructor(
}
// without nsId = create new
bolusCalculatorResult.first.interfaceIDs.nightscoutId == null ->
activePlugin.activeNsClient?.nsClientService?.dbAdd(
activePlugin.activeNsClient?.dbAdd(
"treatments",
bolusCalculatorResult.first.toJson(true, dateUtil, profileFunction),
DataSyncSelector.PairBolusCalculatorResult(bolusCalculatorResult.first, bolusCalculatorResult.second.id),
@ -288,7 +288,7 @@ class DataSyncSelectorImplementation @Inject constructor(
)
// with nsId = update if it's modified record
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),
DataSyncSelector.PairBolusCalculatorResult(bolusCalculatorResult.first, bolusCalculatorResult.second.id), "$startId/$lastDbId"
)
@ -340,7 +340,7 @@ class DataSyncSelectorImplementation @Inject constructor(
}
// without nsId = create new
tt.first.interfaceIDs.nightscoutId == null ->
activePlugin.activeNsClient?.nsClientService?.dbAdd(
activePlugin.activeNsClient?.dbAdd(
"treatments",
tt.first.toJson(true, profileFunction.getUnits(), dateUtil),
DataSyncSelector.PairTemporaryTarget(tt.first, tt.second.id),
@ -348,7 +348,7 @@ class DataSyncSelectorImplementation @Inject constructor(
)
// existing with nsId = update
tt.first.interfaceIDs.nightscoutId != null ->
activePlugin.activeNsClient?.nsClientService?.dbUpdate(
activePlugin.activeNsClient?.dbUpdate(
"treatments",
tt.first.interfaceIDs.nightscoutId,
tt.first.toJson(false, profileFunction.getUnits(), dateUtil),
@ -403,10 +403,10 @@ class DataSyncSelectorImplementation @Inject constructor(
}
// without nsId = create new
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
food.first.interfaceIDs.nightscoutId != null ->
activePlugin.activeNsClient?.nsClientService?.dbUpdate(
activePlugin.activeNsClient?.dbUpdate(
"food",
food.first.interfaceIDs.nightscoutId,
food.first.toJson(false),
@ -462,10 +462,10 @@ class DataSyncSelectorImplementation @Inject constructor(
}
// without nsId = create new
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
else -> // gv.first.interfaceIDs.nightscoutId != null
activePlugin.activeNsClient?.nsClientService?.dbUpdate(
activePlugin.activeNsClient?.dbUpdate(
"entries",
gv.first.interfaceIDs.nightscoutId,
gv.first.toJson(false, dateUtil),
@ -524,10 +524,10 @@ class DataSyncSelectorImplementation @Inject constructor(
}
// without nsId = create new
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
te.first.interfaceIDs.nightscoutId != null ->
activePlugin.activeNsClient?.nsClientService?.dbUpdate(
activePlugin.activeNsClient?.dbUpdate(
"treatments",
te.first.interfaceIDs.nightscoutId,
te.first.toJson(false, dateUtil),
@ -567,7 +567,7 @@ class DataSyncSelectorImplementation @Inject constructor(
when {
// without nsId = create new
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
deviceStatus.interfaceIDs.nightscoutId != null -> Any()
}
@ -620,7 +620,7 @@ class DataSyncSelectorImplementation @Inject constructor(
}
// without nsId = create new
tb.first.interfaceIDs.nightscoutId == null ->
activePlugin.activeNsClient?.nsClientService?.dbAdd(
activePlugin.activeNsClient?.dbAdd(
"treatments",
tb.first.toJson(true, profile, dateUtil),
DataSyncSelector.PairTemporaryBasal(tb.first, tb.second.id),
@ -628,7 +628,7 @@ class DataSyncSelectorImplementation @Inject constructor(
)
// with nsId = update
tb.first.interfaceIDs.nightscoutId != null ->
activePlugin.activeNsClient?.nsClientService?.dbUpdate(
activePlugin.activeNsClient?.dbUpdate(
"treatments",
tb.first.interfaceIDs.nightscoutId,
tb.first.toJson(false, profile, dateUtil),
@ -691,7 +691,7 @@ class DataSyncSelectorImplementation @Inject constructor(
}
// without nsId = create new
eb.first.interfaceIDs.nightscoutId == null ->
activePlugin.activeNsClient?.nsClientService?.dbAdd(
activePlugin.activeNsClient?.dbAdd(
"treatments",
eb.first.toJson(true, profile, dateUtil),
DataSyncSelector.PairExtendedBolus(eb.first, eb.second.id),
@ -699,7 +699,7 @@ class DataSyncSelectorImplementation @Inject constructor(
)
// with nsId = update
eb.first.interfaceIDs.nightscoutId != null ->
activePlugin.activeNsClient?.nsClientService?.dbUpdate(
activePlugin.activeNsClient?.dbUpdate(
"treatments",
eb.first.interfaceIDs.nightscoutId,
eb.first.toJson(false, profile, dateUtil),
@ -759,10 +759,10 @@ class DataSyncSelectorImplementation @Inject constructor(
}
// without nsId = create new
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
ps.first.interfaceIDs.nightscoutId != null ->
activePlugin.activeNsClient?.nsClientService?.dbUpdate(
activePlugin.activeNsClient?.dbUpdate(
"treatments",
ps.first.interfaceIDs.nightscoutId,
ps.first.toJson(false, dateUtil),
@ -816,7 +816,7 @@ class DataSyncSelectorImplementation @Inject constructor(
}
// without nsId = create new
ps.first.interfaceIDs.nightscoutId == null ->
activePlugin.activeNsClient?.nsClientService?.dbAdd(
activePlugin.activeNsClient?.dbAdd(
"treatments",
ps.first.toJson(true, dateUtil),
DataSyncSelector.PairEffectiveProfileSwitch(ps.first, ps.second.id),
@ -824,7 +824,7 @@ class DataSyncSelectorImplementation @Inject constructor(
)
// with nsId = update
ps.first.interfaceIDs.nightscoutId != null ->
activePlugin.activeNsClient?.nsClientService?.dbUpdate(
activePlugin.activeNsClient?.dbUpdate(
"treatments",
ps.first.interfaceIDs.nightscoutId,
ps.first.toJson(false, dateUtil),
@ -879,10 +879,10 @@ class DataSyncSelectorImplementation @Inject constructor(
}
// without nsId = create new
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
oe.first.interfaceIDs.nightscoutId != null ->
activePlugin.activeNsClient?.nsClientService?.dbUpdate(
activePlugin.activeNsClient?.dbUpdate(
"treatments",
oe.first.interfaceIDs.nightscoutId,
oe.first.toJson(false, dateUtil),
@ -905,7 +905,7 @@ class DataSyncSelectorImplementation @Inject constructor(
if (lastChange > lastSync) {
if (activePlugin.activeProfileSource.profile?.allProfilesValid != true) 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 io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import org.json.JSONObject
import javax.inject.Inject
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 listLog: MutableList<EventNSClientNewLog> = ArrayList()
override var status = ""
override var nsClientService: NSClientService? = null
var nsClientService: NSClientService? = null
val isAllowed: Boolean
get() = nsClientReceiverDelegate.allowed
val blockingReason: String
@ -235,4 +236,12 @@ class NSClientPlugin @Inject constructor(
override fun resetToFullSync() {
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.profile.ProfileSealed
import info.nightscout.database.entities.ProfileSwitch
import info.nightscout.database.entities.TherapyEvent
import info.nightscout.database.entities.embedments.InterfaceIDs
import info.nightscout.interfaces.plugin.ActivePlugin
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("enteredBy", "openaps://" + "AndroidAPS")
.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
timeshift = 0
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.NSSettingsStatus
import info.nightscout.interfaces.sync.DataSyncSelector
import info.nightscout.interfaces.sync.NsClient
import info.nightscout.interfaces.ui.UiInteraction
import info.nightscout.interfaces.utils.JsonHelper.safeGetString
import info.nightscout.interfaces.utils.JsonHelper.safeGetStringAllowNull
@ -72,7 +71,7 @@ import java.net.URISyntaxException
import java.util.Locale
import javax.inject.Inject
class NSClientService : DaggerService(), NsClient.NSClientService {
class NSClientService : DaggerService() {
@Inject lateinit var injector: HasAndroidInjector
@Inject lateinit var aapsLogger: AAPSLogger
@ -251,7 +250,7 @@ class NSClientService : DaggerService(), NsClient.NSClientService {
} else if (!nsEnabled) {
rxBus.send(EventNSClientNewLog("NSCLIENT", "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 {
rxBus.send(EventNSClientStatus("Connecting ..."))
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 {
if (_id == null) 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 {
if (!isConnected || !hasWriteAuth) return
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.nsShared.NSClientFragment
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.nsclient.NsClientReceiverDelegate
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 kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import org.json.JSONObject
import javax.inject.Inject
import javax.inject.Singleton
import kotlin.math.max
@ -87,21 +87,30 @@ class NSClientV3Plugin @Inject constructor(
companion object {
val JOB_NAME: String = this::class.java.simpleName
val REFRESH_INTERVAL = T.mins(5).msecs()
}
private val disposable = CompositeDisposable()
private lateinit var runLoop: Runnable
private val handler = Handler(HandlerThread(this::class.simpleName + "Handler").also { it.start() }.looper)
private val listLog: MutableList<EventNSClientNewLog> = ArrayList()
override var status = ""
override val nsClientService: NSClientService? = null // service not needed
override val status
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
// private lateinit var nsAndroidRxClient: NSAndroidRxClient
val isAllowed: Boolean
get() = nsClientReceiverDelegate.allowed
val blockingReason: String
get() = nsClientReceiverDelegate.blockingReason
val isAllowed get() = nsClientReceiverDelegate.allowed
val blockingReason get() = nsClientReceiverDelegate.blockingReason
private val maxAge = T.days(77).msecs()
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.devicestatus = max(dateUtil.now() - maxAge, lastFetched.collections.devicestatus)
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
)
setClient()
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
.toObservable(EventNetworkChange::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({ ev -> nsClientReceiverDelegate.onStatusEvent(ev) }, fabricPrivacy::logException)
.subscribe({ ev ->
nsClientReceiverDelegate.onStatusEvent(ev)
setClient()
}, fabricPrivacy::logException)
disposable += rxBus
.toObservable(EventPreferenceChange::class.java)
.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
// .toObservable(EventAppExit::class.java)
// .observeOn(aapsSchedulers.io)
@ -177,10 +179,18 @@ class NSClientV3Plugin @Inject constructor(
.toObservable(EventNSClientResend::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({ event -> resend(event.reason) }, fabricPrivacy::logException)
runLoop = Runnable {
executeLoop()
handler.postDelayed(runLoop, REFRESH_INTERVAL)
}
handler.postDelayed(runLoop, REFRESH_INTERVAL)
executeLoop()
}
override fun onStop() {
// context.applicationContext.unbindService(mConnection)
handler.removeCallbacksAndMessages(null)
disposable.clear()
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()
}
override val hasWritePermission: Boolean get() = nsClientService?.hasWriteAuth ?: false
override val connected: Boolean get() = nsClientService?.isConnected ?: false
override val hasWritePermission: Boolean get() = nsAndroidClient.lastStatus?.apiPermissions?.isFull() ?: false
override val connected: Boolean get() = nsAndroidClient.lastStatus != null
override fun clearLog() {
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) {
synchronized(listLog) {
listLog.add(ev)
@ -231,7 +251,7 @@ class NSClientV3Plugin @Inject constructor(
}
override fun resend(reason: String) {
nsClientService?.resend(reason)
// nsClientService?.resend(reason)
}
override fun pause(newState: Boolean) {
@ -239,8 +259,7 @@ class NSClientV3Plugin @Inject constructor(
rxBus.send(EventPreferenceChange(rh.gs(R.string.key_ns_client_paused)))
}
override val version: NsClient.Version
get() = NsClient.Version.V3
override val version: NsClient.Version get() = NsClient.Version.V3
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")
return
}
nsClientService?.sendAlarmAck(
AlarmAck().also { ack ->
ack.level = originalAlarm.level()
ack.group = originalAlarm.group()
ack.silenceTime = silenceTimeInMilliseconds
})
// nsClientService?.sendAlarmAck(
// AlarmAck().also { ack ->
// ack.level = originalAlarm.level()
// ack.group = originalAlarm.group()
// ack.silenceTime = silenceTimeInMilliseconds
// })
}
override fun updateLatestBgReceivedIfNewer(latestReceived: Long) {
@ -282,11 +301,39 @@ class NSClientV3Plugin @Inject constructor(
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() {
sp.putString(R.string.key_ns_client_v3_last_modified, Json.encodeToString(LastModified.serializer(), lastFetched))
}
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)))
rxBus.send(EventNSClientNewLog("RUN", "Already running"))
else {

View file

@ -11,6 +11,6 @@ fun NSExtendedBolus.toExtendedBolus(): ExtendedBolus =
utcOffset = utcOffset,
amount = enteredinsulin,
duration = duration,
isEmulatingTempBasal = isEmulatingTempbasal,
isEmulatingTempBasal = isEmulatingTempBasal ?: false,
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 {
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)
.beginUniqueWork(
NSClientV3Plugin.JOB_NAME,

View file

@ -97,4 +97,7 @@
<string name="remove_all">Odstranit vše</string>
<string name="reset_start">Resetovat start</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>

View file

@ -97,4 +97,7 @@
<string name="remove_all">Eliminar todos</string>
<string name="reset_start">Restablecer inicio</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>

View file

@ -97,4 +97,7 @@
<string name="remove_all">Supprimer tout</string>
<string name="reset_start">Réinitialiser le démarrage</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>

View file

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

View file

@ -143,4 +143,8 @@
<string name="reset_start">Reset start</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>

View file

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

View file

@ -1,7 +1,6 @@
package info.nightscout.pump.combo.di
import dagger.Module
import info.nightscout.androidaps.danars.di.ComboActivitiesModule
@Module(includes = [
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
// the retryBlocking loop here is in place because the _Android device_
// may not be ready to connect right away.
// TODO: Test and define what happens when all attempts failed.
// The user needs to be informed and given the choice to try again.
// When all attempts fail, retryBlocking() lets the exception pass through.
// That exception is wrapped in BluetoothException, which then needs to be
// handled by the caller.
val totalNumAttempts = 5
retryBlocking(numberOfRetries = totalNumAttempts, delayBetweenRetries = 100) { attemptNumber, previousException ->
if (abortConnectAttempt)

View file

@ -381,13 +381,6 @@ class AndroidBluetoothInterface(private val androidContext: Context) : Bluetooth
// instance was already processed. This check here instead
// verifies if we have seen the same Bluetooth address on
// *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) {
previouslyDiscoveredDevices[comboctlBtAddress] = androidBtDevice
logger(LogLevel.DEBUG) {

View file

@ -2743,8 +2743,6 @@ class Pump(
)
}
numObservedScreens++
val factorIndexOnScreen = parsedScreen.beginTime.hour
// numUnits null means the basal profile factor
@ -2752,6 +2750,11 @@ class Pump(
if (parsedScreen.numUnits == null)
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,
// it means it was already read earlier.
if (basalProfileFactors[factorIndexOnScreen] >= 0)
@ -2759,14 +2762,16 @@ class Pump(
val factor = parsedScreen.numUnits
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(
RTCommandProgressStage.GettingBasalProfile(numRetrievedFactors)
)
numRetrievedFactors++
return@longPressRTButtonUntil if (numObservedScreens >= NUM_COMBO_BASAL_PROFILE_FACTORS)
LongPressRTButtonsCommand.ReleaseButton
else
@ -2819,21 +2824,19 @@ class Pump(
}
}
numRetrievedFactors++
getBasalProfileReporter.setCurrentProgressStage(
RTCommandProgressStage.GettingBasalProfile(numRetrievedFactors)
)
numRetrievedFactors++
}
}
// All factors retrieved. Press CHECK once to get back to the total
// basal rate screen, and then CHECK again to return to the main menu.
rtNavigationContext.shortPressButton(RTNavigationButton.CHECK)
waitUntilScreenAppears(rtNavigationContext, ParsedScreen.BasalRateTotalScreen::class)
rtNavigationContext.shortPressButton(RTNavigationButton.CHECK)
waitUntilScreenAppears(rtNavigationContext, ParsedScreen.MainScreen::class)
// All factors retrieved. Press BACK repeatedly until we are back at the main menu.
cycleToRTScreen(
rtNavigationContext,
RTNavigationButton.BACK,
ParsedScreen.MainScreen::class
)
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_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_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_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>

View file

@ -95,6 +95,9 @@
<string name="combov2_reservoir_low_warning">Низкий уровень инсулина в картридже помпы</string>
<string name="combov2_setting_tbr_succeeded">Настройки 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_cannot_set_absolute_tbr_if_basal_zero">Невозможно установить абсолютный TBR, если базовая скорость равна нулю</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 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
// Info
@ -410,7 +410,7 @@ class DanaPump @Inject constructor(
aapsLogger.debug(LTag.PUMP, "DanaRPump reset")
lastConnection = 0
lastSettingsRead = 0
lastHistoryFetched = 0
readHistoryFrom = 0
}
fun modelFriendlyName(): String =

View file

@ -57,8 +57,6 @@ public class DanaRv2Plugin extends AbstractDanaRPlugin {
private final TemporaryBasalStorage temporaryBasalStorage;
private final FabricPrivacy fabricPrivacy;
public long lastEventTimeLoaded = 0;
@Inject
public DanaRv2Plugin(
HasAndroidInjector injector,
@ -345,7 +343,7 @@ public class DanaRv2Plugin extends AbstractDanaRPlugin {
PumpEnactResult result = new PumpEnactResult(getInjector());
if (danaPump.isTempBasalInProgress()) {
sExecutionService.tempBasalStop();
result.enacted(true).isTempCancel(true);
result.success(true).enacted(true).isTempCancel(true);
} else {
result.success(true).isTempCancel(true).comment(info.nightscout.core.ui.R.string.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,
DanaPump.HistoryEntry.CARBS.getValue(), carbtime, carbs, 0);
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())
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,
DanaPump.HistoryEntry.CARBS.getValue(), time, amount, 0);
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;
}
@ -433,18 +433,17 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService {
if (!isConnected())
return new PumpEnactResult(injector).success(false);
SystemClock.sleep(300);
MsgHistoryEventsV2 msg = new MsgHistoryEventsV2(injector, danaPump.lastHistoryFetched);
aapsLogger.debug(LTag.PUMP, "Loading event history from: " + dateUtil.dateAndTimeString(danaPump.lastHistoryFetched));
MsgHistoryEventsV2 msg = new MsgHistoryEventsV2(injector, danaPump.readHistoryFrom);
aapsLogger.debug(LTag.PUMP, "Loading event history from: " + dateUtil.dateAndTimeString(danaPump.readHistoryFrom));
mSerialIOThread.sendMessage(msg);
while (!danaPump.historyDoneReceived && mRfcommSocket.isConnected()) {
SystemClock.sleep(100);
}
SystemClock.sleep(200);
if (danaRv2Plugin.lastEventTimeLoaded != 0)
danaPump.lastHistoryFetched = danaRv2Plugin.lastEventTimeLoaded - T.Companion.mins(1).msecs();
if (danaPump.getLastEventTimeLoaded() != 0) danaPump.readHistoryFrom = danaPump.getLastEventTimeLoaded() - T.Companion.mins(1).msecs();
else
danaPump.lastHistoryFetched = 0;
danaPump.readHistoryFrom = 0;
danaPump.setLastConnection(System.currentTimeMillis());
return new PumpEnactResult(injector).success(true);
}

View file

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

View file

@ -262,19 +262,13 @@ class DanaRSService : DaggerService() {
return result
}
SystemClock.sleep(1000)
val msg: DanaRSPacketAPSHistoryEvents
if (danaPump.lastHistoryFetched == 0L) {
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))
}
val msg = DanaRSPacketAPSHistoryEvents(injector, danaPump.readHistoryFrom)
aapsLogger.debug(LTag.PUMPCOMM, "Loading event history from: " + dateUtil.dateAndTimeString(danaPump.readHistoryFrom))
sendMessage(msg)
while (!danaPump.historyDoneReceived && bleComm.isConnected) {
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")
rxBus.send(EventPumpStatusChanged(rh.gs(info.nightscout.pump.dana.R.string.gettingpumpstatus)))
sendMessage(DanaRSPacketGeneralInitialScreenInformation(injector))
@ -305,7 +299,7 @@ class DanaRSService : DaggerService() {
// sendMessage(msg);
val msgSetHistoryEntryV2 = DanaRSPacketAPSSetEventHistory(injector, DanaPump.HistoryEntry.CARBS.value, carbTime, carbs, 0)
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)
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 info.nightscout.pump.diaconn.DiaconnG8Pump
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.shared.interfaces.ResourceHelper
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
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
} else {
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 info.nightscout.pump.diaconn.DiaconnG8Pump
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.shared.interfaces.ResourceHelper
import info.nightscout.shared.sharedPreferences.SP
@ -214,7 +214,7 @@ class BigAPSMainInfoInquireResponsePacket(
diaconnG8Pump.pumpProfiles!![diaconnG8Pump.activeProfile][23] = diaconnG8Pump.baseAmount24
//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, "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.database.DiaconnHistoryRecord
import info.nightscout.pump.diaconn.database.DiaconnHistoryRecordDao
import info.nightscout.pump.diaconn.pumplog.LOG_ALARM_BATTERY
import info.nightscout.pump.diaconn.pumplog.LOG_ALARM_BLOCK
import info.nightscout.pump.diaconn.pumplog.LOG_ALARM_SHORTAGE
import info.nightscout.pump.diaconn.pumplog.LOG_CHANGE_INJECTOR_SUCCESS
import info.nightscout.pump.diaconn.pumplog.LOG_CHANGE_NEEDLE_SUCCESS
import info.nightscout.pump.diaconn.pumplog.LOG_CHANGE_TUBE_SUCCESS
import info.nightscout.pump.diaconn.pumplog.LOG_INJECTION_1DAY
import info.nightscout.pump.diaconn.pumplog.LOG_INJECTION_1DAY_BASAL
import info.nightscout.pump.diaconn.pumplog.LOG_INJECTION_1HOUR_BASAL
import info.nightscout.pump.diaconn.pumplog.LOG_INJECTION_DUAL_NORMAL
import info.nightscout.pump.diaconn.pumplog.LOG_INJECT_DUAL_FAIL
import info.nightscout.pump.diaconn.pumplog.LOG_INJECT_DUAL_SUCCESS
import info.nightscout.pump.diaconn.pumplog.LOG_INJECT_MEAL_FAIL
import info.nightscout.pump.diaconn.pumplog.LOG_INJECT_MEAL_SUCCESS
import info.nightscout.pump.diaconn.pumplog.LOG_INJECT_NORMAL_FAIL
import info.nightscout.pump.diaconn.pumplog.LOG_INJECT_NORMAL_SUCCESS
import info.nightscout.pump.diaconn.pumplog.LOG_INJECT_SQUARE_FAIL
import info.nightscout.pump.diaconn.pumplog.LOG_INJECT_SQUARE_SUCCESS
import info.nightscout.pump.diaconn.pumplog.LOG_RESET_SYS_V3
import info.nightscout.pump.diaconn.pumplog.LOG_SET_DUAL_INJECTION
import info.nightscout.pump.diaconn.pumplog.LOG_SET_SQUARE_INJECTION
import info.nightscout.pump.diaconn.pumplog.LOG_SUSPEND_RELEASE_V2
import info.nightscout.pump.diaconn.pumplog.LOG_SUSPEND_V2
import info.nightscout.pump.diaconn.pumplog.LOG_TB_START_V3
import info.nightscout.pump.diaconn.pumplog.LOG_TB_STOP_V3
import info.nightscout.pump.diaconn.pumplog.PumplogUtil
import info.nightscout.pump.diaconn.pumplog.LogAlarmBattery
import info.nightscout.pump.diaconn.pumplog.LogAlarmBlock
import info.nightscout.pump.diaconn.pumplog.LogAlarmShortAge
import info.nightscout.pump.diaconn.pumplog.LogChangeInjectorSuccess
import info.nightscout.pump.diaconn.pumplog.LogChangeNeedleSuccess
import info.nightscout.pump.diaconn.pumplog.LogChangeTubeSuccess
import info.nightscout.pump.diaconn.pumplog.LogInjectDualFail
import info.nightscout.pump.diaconn.pumplog.LogInjectDualSuccess
import info.nightscout.pump.diaconn.pumplog.LogInjectMealFail
import info.nightscout.pump.diaconn.pumplog.LogInjectMealSuccess
import info.nightscout.pump.diaconn.pumplog.LogInjectNormalFail
import info.nightscout.pump.diaconn.pumplog.LogInjectNormalSuccess
import info.nightscout.pump.diaconn.pumplog.LogInjectSquareFail
import info.nightscout.pump.diaconn.pumplog.LogInjectSquareSuccess
import info.nightscout.pump.diaconn.pumplog.LogInjection1Day
import info.nightscout.pump.diaconn.pumplog.LogInjection1DayBasal
import info.nightscout.pump.diaconn.pumplog.LogInjection1HourBasal
import info.nightscout.pump.diaconn.pumplog.LogInjectionDualNormal
import info.nightscout.pump.diaconn.pumplog.LogResetSysV3
import info.nightscout.pump.diaconn.pumplog.LogSetDualInjection
import info.nightscout.pump.diaconn.pumplog.LogSetSquareInjection
import info.nightscout.pump.diaconn.pumplog.LogSuspendReleaseV2
import info.nightscout.pump.diaconn.pumplog.LogSuspendV2
import info.nightscout.pump.diaconn.pumplog.LogTbStartV3
import info.nightscout.pump.diaconn.pumplog.LogTbStopV3
import info.nightscout.pump.diaconn.pumplog.PumpLogUtil
import info.nightscout.rx.bus.RxBus
import info.nightscout.rx.events.EventPumpStatusChanged
import info.nightscout.rx.logging.LTag
@ -113,22 +113,22 @@ class BigLogInquireResponsePacket(
val logNum = getShortToInt(bufferData) // 2byte
// log Data Parsing
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
val logDataToHexString = toNarrowHex(logData)
val pumpLogKind: Byte = PumplogUtil.getKind(logDataToHexString)
val pumpLogKind: Byte = PumpLogUtil.getKind(logDataToHexString)
var status: String
val diaconnG8HistoryRecord = DiaconnHistoryRecord(0)
@ -151,8 +151,8 @@ class BigLogInquireResponsePacket(
when (pumpLogKind) {
LOG_INJECT_MEAL_SUCCESS.LOG_KIND -> {
val logItem = LOG_INJECT_MEAL_SUCCESS.parse(logDataToHexString)
LogInjectMealSuccess.LOG_KIND -> {
val logItem = LogInjectMealSuccess.parse(logDataToHexString)
aapsLogger.debug(LTag.PUMPCOMM, "$logItem ")
val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss")
val logDateTime = logStartDate.time
@ -186,8 +186,8 @@ class BigLogInquireResponsePacket(
status = "MEAL_BOLUS_SUCCESS" + dateUtil.timeString(logDateTime)
}
LOG_INJECT_MEAL_FAIL.LOG_KIND -> {
val logItem = LOG_INJECT_MEAL_FAIL.parse(logDataToHexString)
LogInjectMealFail.LOG_KIND -> {
val logItem = LogInjectMealFail.parse(logDataToHexString)
aapsLogger.debug(LTag.PUMPCOMM, "$logItem ")
val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss")
val logDateTime = logStartDate.time
@ -221,8 +221,8 @@ class BigLogInquireResponsePacket(
status = "MEAL_BOLUS_FAIL " + dateUtil.timeString(logDateTime)
}
LOG_INJECT_NORMAL_SUCCESS.LOG_KIND -> {
val logItem = LOG_INJECT_NORMAL_SUCCESS.parse(logDataToHexString)
LogInjectNormalSuccess.LOG_KIND -> {
val logItem = LogInjectNormalSuccess.parse(logDataToHexString)
aapsLogger.debug(LTag.PUMPCOMM, "$logItem ")
val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss")
@ -257,8 +257,8 @@ class BigLogInquireResponsePacket(
status = "BOLUS_SUCCESS" + dateUtil.timeString(logDateTime)
}
LOG_INJECT_NORMAL_FAIL.LOG_KIND -> {
val logItem = LOG_INJECT_NORMAL_FAIL.parse(logDataToHexString)
LogInjectNormalFail.LOG_KIND -> {
val logItem = LogInjectNormalFail.parse(logDataToHexString)
aapsLogger.debug(LTag.PUMPCOMM, "$logItem ")
val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss")
val logDateTime = logStartDate.time
@ -295,8 +295,8 @@ class BigLogInquireResponsePacket(
status = "BOLUS_FAIL " + dateUtil.timeString(logDateTime)
}
LOG_SET_SQUARE_INJECTION.LOG_KIND -> {
val logItem = LOG_SET_SQUARE_INJECTION.parse(logDataToHexString)
LogSetSquareInjection.LOG_KIND -> {
val logItem = LogSetSquareInjection.parse(logDataToHexString)
aapsLogger.debug(LTag.PUMPCOMM, "$logItem ")
val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss")
val logDateTime = logStartDate.time
@ -326,8 +326,8 @@ class BigLogInquireResponsePacket(
status = "EXTENDED_BOLUS_START " + dateUtil.timeString(logDateTime)
}
LOG_INJECT_SQUARE_SUCCESS.LOG_KIND -> {
val logItem = LOG_INJECT_SQUARE_SUCCESS.parse(logDataToHexString)
LogInjectSquareSuccess.LOG_KIND -> {
val logItem = LogInjectSquareSuccess.parse(logDataToHexString)
aapsLogger.debug(LTag.PUMPCOMM, "$logItem ")
val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss")
val logDateTime = logStartDate.time
@ -343,8 +343,8 @@ class BigLogInquireResponsePacket(
status = "EXTENDED_BOLUS_END " + dateUtil.timeString(logDateTime)
}
LOG_INJECT_SQUARE_FAIL.LOG_KIND -> {
val logItem = LOG_INJECT_SQUARE_FAIL.parse(logDataToHexString)
LogInjectSquareFail.LOG_KIND -> {
val logItem = LogInjectSquareFail.parse(logDataToHexString)
aapsLogger.debug(LTag.PUMPCOMM, "$logItem ")
val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss")
val logDateTime = logStartDate.time
@ -371,8 +371,8 @@ class BigLogInquireResponsePacket(
status = "EXTENDED_BOLUS_FAIL " + dateUtil.timeString(logDateTime)
}
LOG_SET_DUAL_INJECTION.LOG_KIND -> {
val logItem = LOG_SET_DUAL_INJECTION.parse(logDataToHexString)
LogSetDualInjection.LOG_KIND -> {
val logItem = LogSetDualInjection.parse(logDataToHexString)
aapsLogger.debug(LTag.PUMPCOMM, "$logItem ")
val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss")
val logDateTime = logStartDate.time
@ -405,8 +405,8 @@ class BigLogInquireResponsePacket(
status = "DUAL_EXTENDED_START " + dateUtil.timeString(logDateTime)
}
LOG_INJECTION_DUAL_NORMAL.LOG_KIND -> {
val logItem = LOG_INJECTION_DUAL_NORMAL.parse(logDataToHexString)
LogInjectionDualNormal.LOG_KIND -> {
val logItem = LogInjectionDualNormal.parse(logDataToHexString)
aapsLogger.debug(LTag.PUMPCOMM, "$logItem ")
val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss")
val logDateTime = logStartDate.time
@ -445,8 +445,8 @@ class BigLogInquireResponsePacket(
status = "DUAL_BOLUS" + dateUtil.timeString(logDateTime)
}
LOG_INJECT_DUAL_SUCCESS.LOG_KIND -> {
val logItem = LOG_INJECT_DUAL_SUCCESS.parse(logDataToHexString)
LogInjectDualSuccess.LOG_KIND -> {
val logItem = LogInjectDualSuccess.parse(logDataToHexString)
aapsLogger.debug(LTag.PUMPCOMM, "$logItem ")
val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss")
val logDateTime = logStartDate.time
@ -464,8 +464,8 @@ class BigLogInquireResponsePacket(
status = "DUAL_BOLUS_SQUARE_SUCCESS " + dateUtil.timeString(logDateTime)
}
LOG_INJECT_DUAL_FAIL.LOG_KIND -> {
val logItem = LOG_INJECT_DUAL_FAIL.parse(logDataToHexString)
LogInjectDualFail.LOG_KIND -> {
val logItem = LogInjectDualFail.parse(logDataToHexString)
aapsLogger.debug(LTag.PUMPCOMM, "$logItem ")
val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss")
val logDateTime = logStartDate.time
@ -493,8 +493,8 @@ class BigLogInquireResponsePacket(
status = "DUAL_BOLUS FAIL " + dateUtil.timeString(logDateTime)
}
LOG_INJECTION_1HOUR_BASAL.LOG_KIND -> {
val logItem = LOG_INJECTION_1HOUR_BASAL.parse(logDataToHexString)
LogInjection1HourBasal.LOG_KIND -> {
val logItem = LogInjection1HourBasal.parse(logDataToHexString)
aapsLogger.debug(LTag.PUMPCOMM, "$logItem ")
val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss")
val logDateTime = logStartDate.time
@ -509,8 +509,8 @@ class BigLogInquireResponsePacket(
status = "1HOUR BASAL " + dateUtil.dateAndTimeString(logDateTime)
}
LOG_SUSPEND_V2.LOG_KIND -> {
val logItem = LOG_SUSPEND_V2.parse(logDataToHexString)
LogSuspendV2.LOG_KIND -> {
val logItem = LogSuspendV2.parse(logDataToHexString)
aapsLogger.debug(LTag.PUMPCOMM, "$logItem ")
val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss")
val logDateTime = logStartDate.time
@ -524,8 +524,8 @@ class BigLogInquireResponsePacket(
status = "SUSPEND " + dateUtil.timeString(logDateTime)
}
LOG_SUSPEND_RELEASE_V2.LOG_KIND -> {
val logItem = LOG_SUSPEND_RELEASE_V2.parse(logDataToHexString)
LogSuspendReleaseV2.LOG_KIND -> {
val logItem = LogSuspendReleaseV2.parse(logDataToHexString)
aapsLogger.debug(LTag.PUMPCOMM, "$logItem ")
val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss")
val logDateTime = logStartDate.time
@ -539,8 +539,8 @@ class BigLogInquireResponsePacket(
status = "SUSPEND_RELEASE " + dateUtil.timeString(logDateTime)
}
LOG_CHANGE_INJECTOR_SUCCESS.LOG_KIND -> {
val logItem = LOG_CHANGE_INJECTOR_SUCCESS.parse(logDataToHexString)
LogChangeInjectorSuccess.LOG_KIND -> {
val logItem = LogChangeInjectorSuccess.parse(logDataToHexString)
aapsLogger.debug(LTag.PUMPCOMM, "$logItem ")
val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss")
val logDateTime = logStartDate.time
@ -568,8 +568,8 @@ class BigLogInquireResponsePacket(
status = "INSULIN_CHANGE " + dateUtil.timeString(logDateTime)
}
LOG_CHANGE_TUBE_SUCCESS.LOG_KIND -> {
val logItem = LOG_CHANGE_TUBE_SUCCESS.parse(logDataToHexString)
LogChangeTubeSuccess.LOG_KIND -> {
val logItem = LogChangeTubeSuccess.parse(logDataToHexString)
aapsLogger.debug(LTag.PUMPCOMM, "$logItem ")
val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss")
val logDateTime = logStartDate.time
@ -600,8 +600,8 @@ class BigLogInquireResponsePacket(
status = "TUBE_CHANGE " + dateUtil.timeString(logDateTime)
}
LOG_INJECTION_1DAY.LOG_KIND -> { // Daily Bolus Log
val logItem = LOG_INJECTION_1DAY.parse(logDataToHexString)
LogInjection1Day.LOG_KIND -> { // Daily Bolus Log
val logItem = LogInjection1Day.parse(logDataToHexString)
aapsLogger.debug(LTag.PUMPCOMM, "$logItem ")
val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss")
val logDateTime = logStartDate.time
@ -649,8 +649,8 @@ class BigLogInquireResponsePacket(
status = "DAILY_BOLUS " + dateUtil.timeString(logDateTime)
}
LOG_INJECTION_1DAY_BASAL.LOG_KIND -> { // Daily Basal Log
val logItem = LOG_INJECTION_1DAY_BASAL.parse(logDataToHexString)
LogInjection1DayBasal.LOG_KIND -> { // Daily Basal Log
val logItem = LogInjection1DayBasal.parse(logDataToHexString)
aapsLogger.debug(LTag.PUMPCOMM, "$logItem ")
val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss")
val logDateTime = logStartDate.time
@ -698,8 +698,8 @@ class BigLogInquireResponsePacket(
status = "DAILY_BASAL " + dateUtil.timeString(logDateTime)
}
LOG_CHANGE_NEEDLE_SUCCESS.LOG_KIND -> {
val logItem = LOG_CHANGE_NEEDLE_SUCCESS.parse(logDataToHexString)
LogChangeNeedleSuccess.LOG_KIND -> {
val logItem = LogChangeNeedleSuccess.parse(logDataToHexString)
aapsLogger.debug(LTag.PUMPCOMM, "$logItem ")
val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss")
val logDateTime = logStartDate.time
@ -728,8 +728,8 @@ class BigLogInquireResponsePacket(
status = "NEEDLE_CHANGE " + dateUtil.timeString(logDateTime)
}
LOG_TB_START_V3.LOG_KIND -> {
val logItem = LOG_TB_START_V3.parse(logDataToHexString)
LogTbStartV3.LOG_KIND -> {
val logItem = LogTbStartV3.parse(logDataToHexString)
aapsLogger.debug(LTag.PUMPCOMM, "$logItem ")
val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss")
@ -772,8 +772,8 @@ class BigLogInquireResponsePacket(
status = "TEMP_START " + dateUtil.timeString(logDateTime)
}
LOG_TB_STOP_V3.LOG_KIND -> {
val logItem = LOG_TB_STOP_V3.parse(logDataToHexString)
LogTbStopV3.LOG_KIND -> {
val logItem = LogTbStopV3.parse(logDataToHexString)
aapsLogger.debug(LTag.PUMPCOMM, "$logItem ")
val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss")
val logDateTime = logStartDate.time
@ -806,8 +806,8 @@ class BigLogInquireResponsePacket(
status = "TEMP_STOP " + dateUtil.timeString(logDateTime)
}
LOG_ALARM_BATTERY.LOG_KIND -> { // BATTERY SHORTAGE ALARM
val logItem = LOG_ALARM_BATTERY.parse(logDataToHexString)
LogAlarmBattery.LOG_KIND -> { // BATTERY SHORTAGE ALARM
val logItem = LogAlarmBattery.parse(logDataToHexString)
aapsLogger.debug(LTag.PUMPCOMM, "$logItem ")
val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss")
val logDateTime = logStartDate.time
@ -822,8 +822,8 @@ class BigLogInquireResponsePacket(
status = "BATTERY_ALARM " + dateUtil.timeString(logDateTime)
}
LOG_ALARM_BLOCK.LOG_KIND -> { // INJECTION BLOCKED ALARM
val logItem = LOG_ALARM_BLOCK.parse(logDataToHexString)
LogAlarmBlock.LOG_KIND -> { // INJECTION BLOCKED ALARM
val logItem = LogAlarmBlock.parse(logDataToHexString)
aapsLogger.debug(LTag.PUMPCOMM, "$logItem ")
val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss")
@ -840,8 +840,8 @@ class BigLogInquireResponsePacket(
status = "BLOCK_ALARM " + dateUtil.timeString(logDateTime)
}
LOG_ALARM_SHORTAGE.LOG_KIND -> { // INSULIN SHORTAGE ALARM
val logItem = LOG_ALARM_SHORTAGE.parse(logDataToHexString)
LogAlarmShortAge.LOG_KIND -> { // INSULIN SHORTAGE ALARM
val logItem = LogAlarmShortAge.parse(logDataToHexString)
aapsLogger.debug(LTag.PUMPCOMM, "$logItem ")
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)
}
LOG_RESET_SYS_V3.LOG_KIND -> {
val logItem = LOG_RESET_SYS_V3.parse(logDataToHexString)
LogResetSysV3.LOG_KIND -> {
val logItem = LogResetSysV3.parse(logDataToHexString)
aapsLogger.debug(LTag.PUMPCOMM, "$logItem ")
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.pump.diaconn.DiaconnG8Pump
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.shared.interfaces.ResourceHelper
import info.nightscout.shared.sharedPreferences.SP
@ -213,7 +213,7 @@ class BigMainInfoInquireResponsePacket(
diaconnG8Pump.pumpProfiles!![diaconnG8Pump.activeProfile][23] = diaconnG8Pump.baseAmount24
//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, "systemRemainInsulin > " + diaconnG8Pump.systemRemainInsulin)

View file

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

View file

@ -6,18 +6,18 @@ import java.nio.ByteOrder
/*
* Insulin shortage alarm
*/
class LOG_ALARM_SHORTAGE private constructor(
class LogAlarmShortAge private constructor(
val data: String,
val dttm: String,
typeAndKind: Byte, // 1=INFO, 2=WARNING, 3=MAJOR, 4=CRITICAL
val alarmLevel: Byte, // 1=OCCUR, 2=STOP
val ack: Byte, // (1~100U)
private val alarmLevel: Byte, // 1=OCCUR, 2=STOP
private val ack: Byte, // (1~100U)
val remain: Byte,
val batteryRemain: Byte
) {
val type: Byte = PumplogUtil.getType(typeAndKind)
val kind: Byte = PumplogUtil.getKind(typeAndKind)
val type: Byte = PumpLogUtil.getType(typeAndKind)
val kind: Byte = PumpLogUtil.getKind(typeAndKind)
override fun toString(): String {
val sb = StringBuilder("LOG_ALARM_SHORTAGE{")
@ -37,18 +37,18 @@ class LOG_ALARM_SHORTAGE private constructor(
companion object {
const val LOG_KIND: Byte = 0x2A
fun parse(data: String): LOG_ALARM_SHORTAGE {
val bytes = PumplogUtil.hexStringToByteArray(data)
fun parse(data: String): LogAlarmShortAge {
val bytes = PumpLogUtil.hexStringToByteArray(data)
val buffer = ByteBuffer.wrap(bytes)
buffer.order(ByteOrder.LITTLE_ENDIAN)
return LOG_ALARM_SHORTAGE(
return LogAlarmShortAge(
data,
PumplogUtil.getDttm(buffer),
PumplogUtil.getByte(buffer),
PumplogUtil.getByte(buffer),
PumplogUtil.getByte(buffer),
PumplogUtil.getByte(buffer),
PumplogUtil.getByte(buffer)
PumpLogUtil.getDttm(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 dttm: String,
typeAndKind: Byte, // 47.5=4750
@ -15,8 +15,8 @@ class LOG_CHANGE_INJECTOR_SUCCESS private constructor(
val batteryRemain: Byte
) {
val type: Byte = PumplogUtil.getType(typeAndKind)
val kind: Byte = PumplogUtil.getKind(typeAndKind)
val type: Byte = PumpLogUtil.getType(typeAndKind)
val kind: Byte = PumpLogUtil.getKind(typeAndKind)
override fun toString(): String {
val sb = StringBuilder("LOG_CHANGE_INJECTOR_SUCCESS{")
@ -35,17 +35,17 @@ class LOG_CHANGE_INJECTOR_SUCCESS private constructor(
companion object {
const val LOG_KIND: Byte = 0x1A
fun parse(data: String): LOG_CHANGE_INJECTOR_SUCCESS {
val bytes = PumplogUtil.hexStringToByteArray(data)
fun parse(data: String): LogChangeInjectorSuccess {
val bytes = PumpLogUtil.hexStringToByteArray(data)
val buffer = ByteBuffer.wrap(bytes)
buffer.order(ByteOrder.LITTLE_ENDIAN)
return LOG_CHANGE_INJECTOR_SUCCESS(
return LogChangeInjectorSuccess(
data,
PumplogUtil.getDttm(buffer),
PumplogUtil.getByte(buffer),
PumplogUtil.getShort(buffer),
PumplogUtil.getShort(buffer),
PumplogUtil.getByte(buffer)
PumpLogUtil.getDttm(buffer),
PumpLogUtil.getByte(buffer),
PumpLogUtil.getShort(buffer),
PumpLogUtil.getShort(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 dttm: String,
typeAndKind: Byte, // 47.5=4750
@ -15,8 +16,8 @@ class LOG_CHANGE_NEEDLE_SUCCESS private constructor(
val batteryRemain: Byte
) {
val type: Byte = PumplogUtil.getType(typeAndKind)
val kind: Byte = PumplogUtil.getKind(typeAndKind)
val type: Byte = PumpLogUtil.getType(typeAndKind)
val kind: Byte = PumpLogUtil.getKind(typeAndKind)
override fun toString(): String {
val sb = StringBuilder("LOG_CHANGE_NEEDLE_SUCCESS{")
@ -35,17 +36,17 @@ class LOG_CHANGE_NEEDLE_SUCCESS private constructor(
companion object {
const val LOG_KIND: Byte = 0x1C
fun parse(data: String): LOG_CHANGE_NEEDLE_SUCCESS {
val bytes = PumplogUtil.hexStringToByteArray(data)
fun parse(data: String): LogChangeNeedleSuccess {
val bytes = PumpLogUtil.hexStringToByteArray(data)
val buffer = ByteBuffer.wrap(bytes)
buffer.order(ByteOrder.LITTLE_ENDIAN)
return LOG_CHANGE_NEEDLE_SUCCESS(
return LogChangeNeedleSuccess(
data,
PumplogUtil.getDttm(buffer),
PumplogUtil.getByte(buffer),
PumplogUtil.getShort(buffer),
PumplogUtil.getShort(buffer),
PumplogUtil.getByte(buffer)
PumpLogUtil.getDttm(buffer),
PumpLogUtil.getByte(buffer),
PumpLogUtil.getShort(buffer),
PumpLogUtil.getShort(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 dttm: String,
typeAndKind: Byte, // 47.5=4750
@ -15,8 +16,8 @@ class LOG_CHANGE_TUBE_SUCCESS private constructor(
val batteryRemain: Byte
) {
val type: Byte = PumplogUtil.getType(typeAndKind)
val kind: Byte = PumplogUtil.getKind(typeAndKind)
val type: Byte = PumpLogUtil.getType(typeAndKind)
val kind: Byte = PumpLogUtil.getKind(typeAndKind)
override fun toString(): String {
val sb = StringBuilder("LOG_CHANGE_TUBE_SUCCESS{")
@ -35,17 +36,17 @@ class LOG_CHANGE_TUBE_SUCCESS private constructor(
companion object {
const val LOG_KIND: Byte = 0x18
fun parse(data: String): LOG_CHANGE_TUBE_SUCCESS {
val bytes = PumplogUtil.hexStringToByteArray(data)
fun parse(data: String): LogChangeTubeSuccess {
val bytes = PumpLogUtil.hexStringToByteArray(data)
val buffer = ByteBuffer.wrap(bytes)
buffer.order(ByteOrder.LITTLE_ENDIAN)
return LOG_CHANGE_TUBE_SUCCESS(
return LogChangeTubeSuccess(
data,
PumplogUtil.getDttm(buffer),
PumplogUtil.getByte(buffer),
PumplogUtil.getShort(buffer),
PumplogUtil.getShort(buffer),
PumplogUtil.getByte(buffer)
PumpLogUtil.getDttm(buffer),
PumpLogUtil.getByte(buffer),
PumpLogUtil.getShort(buffer),
PumpLogUtil.getShort(buffer),
PumpLogUtil.getByte(buffer)
)
}
}

View file

@ -7,7 +7,8 @@ import java.nio.ByteOrder
/*
* Dual Injection Fail Log
*/
class LOG_INJECT_DUAL_FAIL private constructor(
@Suppress("SpellCheckingInspection")
class LogInjectDualFail private constructor(
val data: String,
val dttm: String,
typeAndKind: Byte, // 47.5=4750
@ -18,8 +19,8 @@ class LOG_INJECT_DUAL_FAIL private constructor(
val batteryRemain: Byte
) {
val type: Byte = PumplogUtil.getType(typeAndKind)
val kind: Byte = PumplogUtil.getKind(typeAndKind)
val type: Byte = PumpLogUtil.getType(typeAndKind)
val kind: Byte = PumpLogUtil.getKind(typeAndKind)
fun getInjectTime(): Int {
return injectTime and 0xff
@ -44,19 +45,19 @@ class LOG_INJECT_DUAL_FAIL private constructor(
companion object {
const val LOG_KIND: Byte = 0x11
fun parse(data: String): LOG_INJECT_DUAL_FAIL {
val bytes = PumplogUtil.hexStringToByteArray(data)
fun parse(data: String): LogInjectDualFail {
val bytes = PumpLogUtil.hexStringToByteArray(data)
val buffer = ByteBuffer.wrap(bytes)
buffer.order(ByteOrder.LITTLE_ENDIAN)
return LOG_INJECT_DUAL_FAIL(
return LogInjectDualFail(
data,
PumplogUtil.getDttm(buffer),
PumplogUtil.getByte(buffer),
PumplogUtil.getShort(buffer),
PumplogUtil.getShort(buffer),
PumplogUtil.getByte(buffer),
PumplogUtil.getByte(buffer),
PumplogUtil.getByte(buffer)
PumpLogUtil.getDttm(buffer),
PumpLogUtil.getByte(buffer),
PumpLogUtil.getShort(buffer),
PumpLogUtil.getShort(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 dttm: String,
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분)
private val injectTime: Byte,
val batteryRemain: Byte
) {
val type: Byte = PumplogUtil.getType(typeAndKind)
val kind: Byte = PumplogUtil.getKind(typeAndKind)
val type: Byte = PumpLogUtil.getType(typeAndKind)
val kind: Byte = PumpLogUtil.getKind(typeAndKind)
fun getInjectTime(): Int {
return injectTime and 0xff
}
@ -41,18 +42,18 @@ class LOG_INJECT_DUAL_SUCCESS private constructor(
companion object {
const val LOG_KIND: Byte = 0x10
fun parse(data: String): LOG_INJECT_DUAL_SUCCESS {
val bytes = PumplogUtil.hexStringToByteArray(data)
fun parse(data: String): LogInjectDualSuccess {
val bytes = PumpLogUtil.hexStringToByteArray(data)
val buffer = ByteBuffer.wrap(bytes)
buffer.order(ByteOrder.LITTLE_ENDIAN)
return LOG_INJECT_DUAL_SUCCESS(
return LogInjectDualSuccess(
data,
PumplogUtil.getDttm(buffer),
PumplogUtil.getByte(buffer),
PumplogUtil.getShort(buffer),
PumplogUtil.getShort(buffer),
PumplogUtil.getByte(buffer),
PumplogUtil.getByte(buffer)
PumpLogUtil.getDttm(buffer),
PumpLogUtil.getByte(buffer),
PumpLogUtil.getShort(buffer),
PumpLogUtil.getShort(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 dttm: String,
typeAndKind: Byte, // 47.5=4750
@ -18,8 +19,8 @@ class LOG_INJECT_MEAL_FAIL private constructor(
val reason: Byte
) {
val type: Byte = PumplogUtil.getType(typeAndKind)
val kind: Byte = PumplogUtil.getKind(typeAndKind)
val type: Byte = PumpLogUtil.getType(typeAndKind)
val kind: Byte = PumpLogUtil.getKind(typeAndKind)
fun getInjectTime(): Int {
return injectTime and 0xff
@ -44,19 +45,19 @@ class LOG_INJECT_MEAL_FAIL private constructor(
companion object {
const val LOG_KIND: Byte = 0x09
fun parse(data: String): LOG_INJECT_MEAL_FAIL {
val bytes = PumplogUtil.hexStringToByteArray(data)
fun parse(data: String): LogInjectMealFail {
val bytes = PumpLogUtil.hexStringToByteArray(data)
val buffer = ByteBuffer.wrap(bytes)
buffer.order(ByteOrder.LITTLE_ENDIAN)
return LOG_INJECT_MEAL_FAIL(
return LogInjectMealFail(
data,
PumplogUtil.getDttm(buffer),
PumplogUtil.getByte(buffer),
PumplogUtil.getShort(buffer),
PumplogUtil.getShort(buffer),
PumplogUtil.getByte(buffer),
PumplogUtil.getByte(buffer),
PumplogUtil.getByte(buffer)
PumpLogUtil.getDttm(buffer),
PumpLogUtil.getByte(buffer),
PumpLogUtil.getShort(buffer),
PumpLogUtil.getShort(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 dttm: String,
typeAndKind: Byte, // 47.5=4750
@ -15,12 +16,11 @@ class LOG_INJECT_MEAL_SUCCESS private constructor(
val injectAmount: Short, // 1분단위 주입시간(124=124분=2시간4분)
private val injectTime: Byte, // 아침=1, 점심=2, 저녁=3
val time: Byte,
batteryRemain: Byte
val batteryRemain: Byte
) {
val type: Byte = PumplogUtil.getType(typeAndKind)
val kind: Byte = PumplogUtil.getKind(typeAndKind)
val batteryRemain: Byte = batteryRemain
val type: Byte = PumpLogUtil.getType(typeAndKind)
val kind: Byte = PumpLogUtil.getKind(typeAndKind)
fun getInjectTime(): Int {
return injectTime and 0xff
}
@ -44,19 +44,19 @@ class LOG_INJECT_MEAL_SUCCESS private constructor(
companion object {
const val LOG_KIND: Byte = 0x08
fun parse(data: String): LOG_INJECT_MEAL_SUCCESS {
val bytes = PumplogUtil.hexStringToByteArray(data)
fun parse(data: String): LogInjectMealSuccess {
val bytes = PumpLogUtil.hexStringToByteArray(data)
val buffer = ByteBuffer.wrap(bytes)
buffer.order(ByteOrder.LITTLE_ENDIAN)
return LOG_INJECT_MEAL_SUCCESS(
return LogInjectMealSuccess(
data,
PumplogUtil.getDttm(buffer),
PumplogUtil.getByte(buffer),
PumplogUtil.getShort(buffer),
PumplogUtil.getShort(buffer),
PumplogUtil.getByte(buffer),
PumplogUtil.getByte(buffer),
PumplogUtil.getByte(buffer)
PumpLogUtil.getDttm(buffer),
PumpLogUtil.getByte(buffer),
PumpLogUtil.getShort(buffer),
PumpLogUtil.getShort(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 dttm: String,
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 injectTime: Byte, // 1=주입막힘, 2=배터리잔량부족, 3=약물부족, 4=사용자중지, 5=시스템리셋, 6=기타, 7=긴급정지
val reason: Byte,
val batteryRemain: Byte
) {
val type: Byte = PumplogUtil.getType(typeAndKind)
val kind: Byte = PumplogUtil.getKind(typeAndKind)
val type: Byte = PumpLogUtil.getType(typeAndKind)
val kind: Byte = PumpLogUtil.getKind(typeAndKind)
fun getInjectTime(): Int {
return injectTime and 0xff
@ -44,19 +45,19 @@ class LOG_INJECT_NORMAL_FAIL private constructor(
companion object {
const val LOG_KIND: Byte = 0x0B
fun parse(data: String): LOG_INJECT_NORMAL_FAIL {
val bytes = PumplogUtil.hexStringToByteArray(data)
fun parse(data: String): LogInjectNormalFail {
val bytes = PumpLogUtil.hexStringToByteArray(data)
val buffer = ByteBuffer.wrap(bytes)
buffer.order(ByteOrder.LITTLE_ENDIAN)
return LOG_INJECT_NORMAL_FAIL(
return LogInjectNormalFail(
data,
PumplogUtil.getDttm(buffer),
PumplogUtil.getByte(buffer),
PumplogUtil.getShort(buffer),
PumplogUtil.getShort(buffer),
PumplogUtil.getByte(buffer),
PumplogUtil.getByte(buffer),
PumplogUtil.getByte(buffer)
PumpLogUtil.getDttm(buffer),
PumpLogUtil.getByte(buffer),
PumpLogUtil.getShort(buffer),
PumpLogUtil.getShort(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 dttm: String,
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 injectTime: Byte,
val batteryRemain: Byte
) {
val type: Byte = PumplogUtil.getType(typeAndKind)
val kind: Byte = PumplogUtil.getKind(typeAndKind)
val type: Byte = PumpLogUtil.getType(typeAndKind)
val kind: Byte = PumpLogUtil.getKind(typeAndKind)
fun getInjectTime(): Int {
return injectTime and 0xff
}
@ -41,18 +42,18 @@ class LOG_INJECT_NORMAL_SUCCESS private constructor(
companion object {
const val LOG_KIND: Byte = 0x0A
fun parse(data: String): LOG_INJECT_NORMAL_SUCCESS {
val bytes = PumplogUtil.hexStringToByteArray(data)
fun parse(data: String): LogInjectNormalSuccess {
val bytes = PumpLogUtil.hexStringToByteArray(data)
val buffer = ByteBuffer.wrap(bytes)
buffer.order(ByteOrder.LITTLE_ENDIAN)
return LOG_INJECT_NORMAL_SUCCESS(
return LogInjectNormalSuccess(
data,
PumplogUtil.getDttm(buffer),
PumplogUtil.getByte(buffer),
PumplogUtil.getShort(buffer),
PumplogUtil.getShort(buffer),
PumplogUtil.getByte(buffer),
PumplogUtil.getByte(buffer)
PumpLogUtil.getDttm(buffer),
PumpLogUtil.getByte(buffer),
PumpLogUtil.getShort(buffer),
PumpLogUtil.getShort(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 dttm: String,
typeAndKind: Byte, // 47.5=4750
@ -17,8 +18,8 @@ class LOG_INJECT_SQUARE_FAIL private constructor(
val batteryRemain: Byte
) {
val type: Byte = PumplogUtil.getType(typeAndKind)
val kind: Byte = PumplogUtil.getKind(typeAndKind)
val type: Byte = PumpLogUtil.getType(typeAndKind)
val kind: Byte = PumpLogUtil.getKind(typeAndKind)
fun getInjectTime(): Int {
return injectTime and 0xff
@ -42,18 +43,18 @@ class LOG_INJECT_SQUARE_FAIL private constructor(
companion object {
const val LOG_KIND: Byte = 0x0E
fun parse(data: String): LOG_INJECT_SQUARE_FAIL {
val bytes = PumplogUtil.hexStringToByteArray(data)
fun parse(data: String): LogInjectSquareFail {
val bytes = PumpLogUtil.hexStringToByteArray(data)
val buffer = ByteBuffer.wrap(bytes)
buffer.order(ByteOrder.LITTLE_ENDIAN)
return LOG_INJECT_SQUARE_FAIL(
return LogInjectSquareFail(
data,
PumplogUtil.getDttm(buffer),
PumplogUtil.getByte(buffer),
PumplogUtil.getShort(buffer),
PumplogUtil.getByte(buffer),
PumplogUtil.getByte(buffer),
PumplogUtil.getByte(buffer)
PumpLogUtil.getDttm(buffer),
PumpLogUtil.getByte(buffer),
PumpLogUtil.getShort(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 dttm: String,
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,
val batteryRemain: Byte
) {
val type: Byte = PumplogUtil.getType(typeAndKind)
val kind: Byte = PumplogUtil.getKind(typeAndKind)
val type: Byte = PumpLogUtil.getType(typeAndKind)
val kind: Byte = PumpLogUtil.getKind(typeAndKind)
fun getInjectTime(): Int {
return injectTime and 0xff
}
@ -39,17 +40,17 @@ class LOG_INJECT_SQUARE_SUCCESS private constructor(
companion object {
const val LOG_KIND: Byte = 0x0D
fun parse(data: String): LOG_INJECT_SQUARE_SUCCESS {
val bytes = PumplogUtil.hexStringToByteArray(data)
fun parse(data: String): LogInjectSquareSuccess {
val bytes = PumpLogUtil.hexStringToByteArray(data)
val buffer = ByteBuffer.wrap(bytes)
buffer.order(ByteOrder.LITTLE_ENDIAN)
return LOG_INJECT_SQUARE_SUCCESS(
return LogInjectSquareSuccess(
data,
PumplogUtil.getDttm(buffer),
PumplogUtil.getByte(buffer),
PumplogUtil.getShort(buffer),
PumplogUtil.getByte(buffer),
PumplogUtil.getByte(buffer)
PumpLogUtil.getDttm(buffer),
PumpLogUtil.getByte(buffer),
PumpLogUtil.getShort(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 dttm: String,
typeAndKind: Byte, // 당일 식사주입 총량 47.5=4750
@ -15,8 +16,8 @@ class LOG_INJECTION_1DAY private constructor(
val batteryRemain: Byte
) {
val type: Byte = PumplogUtil.getType(typeAndKind)
val kind: Byte = PumplogUtil.getKind(typeAndKind)
val type: Byte = PumpLogUtil.getType(typeAndKind)
val kind: Byte = PumpLogUtil.getKind(typeAndKind)
override fun toString(): String {
val sb = StringBuilder("LOG_INJECTION_1DAY{")
@ -35,17 +36,17 @@ class LOG_INJECTION_1DAY private constructor(
companion object {
const val LOG_KIND: Byte = 0x2F
fun parse(data: String): LOG_INJECTION_1DAY {
val bytes = PumplogUtil.hexStringToByteArray(data)
fun parse(data: String): LogInjection1Day {
val bytes = PumpLogUtil.hexStringToByteArray(data)
val buffer = ByteBuffer.wrap(bytes)
buffer.order(ByteOrder.LITTLE_ENDIAN)
return LOG_INJECTION_1DAY(
return LogInjection1Day(
data,
PumplogUtil.getDttm(buffer),
PumplogUtil.getByte(buffer),
PumplogUtil.getShort(buffer),
PumplogUtil.getShort(buffer),
PumplogUtil.getByte(buffer)
PumpLogUtil.getDttm(buffer),
PumpLogUtil.getByte(buffer),
PumpLogUtil.getShort(buffer),
PumpLogUtil.getShort(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 dttm: String,
typeAndKind: Byte,
@ -15,8 +16,8 @@ class LOG_INJECTION_1DAY_BASAL private constructor(
val batteryRemain: Byte
) {
val type: Byte = PumplogUtil.getType(typeAndKind)
val kind: Byte = PumplogUtil.getKind(typeAndKind)
val type: Byte = PumpLogUtil.getType(typeAndKind)
val kind: Byte = PumpLogUtil.getKind(typeAndKind)
override fun toString(): String {
val sb = StringBuilder("LOG_INJECTION_1DAY_BASAL{")
@ -33,16 +34,16 @@ class LOG_INJECTION_1DAY_BASAL private constructor(
companion object {
const val LOG_KIND: Byte = 0x2E
fun parse(data: String): LOG_INJECTION_1DAY_BASAL {
val bytes = PumplogUtil.hexStringToByteArray(data)
fun parse(data: String): LogInjection1DayBasal {
val bytes = PumpLogUtil.hexStringToByteArray(data)
val buffer = ByteBuffer.wrap(bytes)
buffer.order(ByteOrder.LITTLE_ENDIAN)
return LOG_INJECTION_1DAY_BASAL(
return LogInjection1DayBasal(
data,
PumplogUtil.getDttm(buffer),
PumplogUtil.getByte(buffer),
PumplogUtil.getShort(buffer),
PumplogUtil.getByte(buffer)
PumpLogUtil.getDttm(buffer),
PumpLogUtil.getByte(buffer),
PumpLogUtil.getShort(buffer),
PumpLogUtil.getByte(buffer)
)
}
}

View file

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

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