Merge branch 'dev' into ns15

This commit is contained in:
Milos Kozak 2023-01-21 18:01:21 +01:00
commit 7a88237806
18 changed files with 522 additions and 224 deletions

View file

@ -51,7 +51,6 @@ import info.nightscout.interfaces.aps.Loop
import info.nightscout.interfaces.constraints.Constraints import info.nightscout.interfaces.constraints.Constraints
import info.nightscout.interfaces.logging.UserEntryLogger import info.nightscout.interfaces.logging.UserEntryLogger
import info.nightscout.interfaces.maintenance.PrefFileListProvider import info.nightscout.interfaces.maintenance.PrefFileListProvider
import info.nightscout.interfaces.nsclient.NSSettingsStatus
import info.nightscout.interfaces.plugin.ActivePlugin import info.nightscout.interfaces.plugin.ActivePlugin
import info.nightscout.interfaces.plugin.PluginBase import info.nightscout.interfaces.plugin.PluginBase
import info.nightscout.interfaces.profile.ProfileFunction import info.nightscout.interfaces.profile.ProfileFunction
@ -62,7 +61,6 @@ import info.nightscout.interfaces.versionChecker.VersionCheckerUtils
import info.nightscout.plugins.constraints.signatureVerifier.SignatureVerifierPlugin import info.nightscout.plugins.constraints.signatureVerifier.SignatureVerifierPlugin
import info.nightscout.rx.AapsSchedulers import info.nightscout.rx.AapsSchedulers
import info.nightscout.rx.events.EventAppExit import info.nightscout.rx.events.EventAppExit
import info.nightscout.rx.events.EventInitializationChanged
import info.nightscout.rx.events.EventPreferenceChange import info.nightscout.rx.events.EventPreferenceChange
import info.nightscout.rx.events.EventRebuildTabs import info.nightscout.rx.events.EventRebuildTabs
import info.nightscout.rx.logging.LTag import info.nightscout.rx.logging.LTag
@ -88,7 +86,6 @@ class MainActivity : DaggerAppCompatActivityWithResult() {
@Inject lateinit var versionCheckerUtils: VersionCheckerUtils @Inject lateinit var versionCheckerUtils: VersionCheckerUtils
@Inject lateinit var smsCommunicator: SmsCommunicator @Inject lateinit var smsCommunicator: SmsCommunicator
@Inject lateinit var loop: Loop @Inject lateinit var loop: Loop
@Inject lateinit var nsSettingsStatus: NSSettingsStatus
@Inject lateinit var config: Config @Inject lateinit var config: Config
@Inject lateinit var activePlugin: ActivePlugin @Inject lateinit var activePlugin: ActivePlugin
@Inject lateinit var fabricPrivacy: FabricPrivacy @Inject lateinit var fabricPrivacy: FabricPrivacy
@ -347,7 +344,7 @@ class MainActivity : DaggerAppCompatActivityWithResult() {
R.id.nav_about -> { R.id.nav_about -> {
var message = "Build: ${BuildConfig.BUILDVERSION}\n" var message = "Build: ${BuildConfig.BUILDVERSION}\n"
message += "Flavor: ${BuildConfig.FLAVOR}${BuildConfig.BUILD_TYPE}\n" message += "Flavor: ${BuildConfig.FLAVOR}${BuildConfig.BUILD_TYPE}\n"
message += "${rh.gs(info.nightscout.configuration.R.string.configbuilder_nightscoutversion_label)} ${nsSettingsStatus.getVersion()}" message += "${rh.gs(info.nightscout.configuration.R.string.configbuilder_nightscoutversion_label)} ${activePlugin.activeNsClient?.detectedNsVersion() ?: rh.gs(info.nightscout.plugins.R.string.not_available_full)}"
if (config.isEngineeringMode()) message += "\n${rh.gs(info.nightscout.configuration.R.string.engineering_mode_enabled)}" if (config.isEngineeringMode()) message += "\n${rh.gs(info.nightscout.configuration.R.string.engineering_mode_enabled)}"
if (config.isUnfinishedMode()) message += "\nUnfinished mode enabled" if (config.isUnfinishedMode()) message += "\nUnfinished mode enabled"
if (!fabricPrivacy.fabricEnabled()) message += "\n${rh.gs(R.string.fabric_upload_disabled)}" if (!fabricPrivacy.fabricEnabled()) message += "\n${rh.gs(R.string.fabric_upload_disabled)}"

View file

@ -3,20 +3,44 @@ package info.nightscout.interfaces.sync
import android.text.Spanned import android.text.Spanned
import info.nightscout.interfaces.nsclient.NSAlarm import info.nightscout.interfaces.nsclient.NSAlarm
/**
* Plugin providing communication with Nightscout server
*/
interface NsClient : Sync { interface NsClient : Sync {
enum class Version {
NONE, V1, V3
}
val version: Version /**
* NS URL
*/
val address: String val address: String
/**
* Set plugin in paused state
*/
fun pause(newState: Boolean) fun pause(newState: Boolean)
/**
* Initiate new round of upload/download
*/
fun resend(reason: String) fun resend(reason: String)
/**
* @return List last of messages for fragment in HTML format
*/
fun textLog(): Spanned fun textLog(): Spanned
/**
* Clear list of stored messages displayed in fragment
*/
fun clearLog() fun clearLog()
/**
* Version of NS server
* @return Returns detected version of NS server
*/
fun detectedNsVersion(): String?
enum class Collection { ENTRIES, TREATMENTS, FOODS, PROFILE } enum class Collection { ENTRIES, TREATMENTS, FOODS, PROFILE }
/** /**
* NSC v3 does first load of all data * NSC v3 does first load of all data
* next loads are using srvModified property for sync * next loads are using srvModified property for sync
@ -34,6 +58,7 @@ interface NsClient : Sync {
* *
*/ */
fun updateLatestBgReceivedIfNewer(latestReceived: Long) fun updateLatestBgReceivedIfNewer(latestReceived: Long)
/** /**
* Update newest loaded timestamp for treatments collection (first load or NSCv1) * Update newest loaded timestamp for treatments collection (first load or NSCv1)
* Update newest srvModified (sync loads) * Update newest srvModified (sync loads)
@ -42,10 +67,37 @@ interface NsClient : Sync {
* *
*/ */
fun updateLatestTreatmentReceivedIfNewer(latestReceived: Long) fun updateLatestTreatmentReceivedIfNewer(latestReceived: Long)
/**
* Send alarm confirmation to NS
*
* @param originalAlarm alarm to be cleared
* @param silenceTimeInMilliseconds silence alarm for specified duration
*/
fun handleClearAlarm(originalAlarm: NSAlarm, silenceTimeInMilliseconds: Long) fun handleClearAlarm(originalAlarm: NSAlarm, silenceTimeInMilliseconds: Long)
/**
* Clear synchronization status
*
* Next synchronization will start from scratch
*/
fun resetToFullSync() fun resetToFullSync()
/**
* Upload new record to NS
*
* @param collection target ns collection
* @param dataPair data to upload (data.first) and id of changed record (data.second)
* @param progress progress of sync in format "number/number". Only for display in fragment
*/
fun nsAdd(collection: String, dataPair: DataSyncSelector.DataPair, progress: String) fun nsAdd(collection: String, dataPair: DataSyncSelector.DataPair, progress: String)
/**
* Upload updated record to NS
*
* @param collection target ns collection
* @param dataPair data to upload (data.first) and id of changed record (data.second)
* @param progress progress of sync in format "number/number". Only for display in fragment
*/
fun nsUpdate(collection: String, dataPair: DataSyncSelector.DataPair, progress: String) fun nsUpdate(collection: String, dataPair: DataSyncSelector.DataPair, progress: String)
} }

View file

@ -5,6 +5,7 @@ import com.google.gson.JsonParser
import info.nightscout.sdk.exceptions.DateHeaderOutOfToleranceException import info.nightscout.sdk.exceptions.DateHeaderOutOfToleranceException
import info.nightscout.sdk.exceptions.InvalidAccessTokenException import info.nightscout.sdk.exceptions.InvalidAccessTokenException
import info.nightscout.sdk.exceptions.InvalidFormatNightscoutException import info.nightscout.sdk.exceptions.InvalidFormatNightscoutException
import info.nightscout.sdk.exceptions.InvalidParameterNightscoutException
import info.nightscout.sdk.exceptions.UnknownResponseNightscoutException import info.nightscout.sdk.exceptions.UnknownResponseNightscoutException
import info.nightscout.sdk.exceptions.UnsuccessfullNightscoutException import info.nightscout.sdk.exceptions.UnsuccessfullNightscoutException
import info.nightscout.sdk.interfaces.NSAndroidClient import info.nightscout.sdk.interfaces.NSAndroidClient
@ -105,20 +106,22 @@ class NSAndroidClientImpl(
val response = api.lastModified() val response = api.lastModified()
if (response.isSuccessful) { if (response.isSuccessful) {
return@callWrapper response.body()?.result ?: throw UnsuccessfullNightscoutException() return@callWrapper response.body()?.result ?: throw UnsuccessfullNightscoutException()
} else { } else if (response.code() in 400..499)
throw InvalidParameterNightscoutException(response.errorBody()?.string() ?: response.message())
else
throw UnsuccessfullNightscoutException() throw UnsuccessfullNightscoutException()
} }
}
override suspend fun getSgvs(): NSAndroidClient.ReadResponse<List<NSSgvV3>> = callWrapper(dispatcher) { override suspend fun getSgvs(): NSAndroidClient.ReadResponse<List<NSSgvV3>> = callWrapper(dispatcher) {
val response = api.getSgvs() val response = api.getSgvs()
if (response.isSuccessful) { if (response.isSuccessful) {
return@callWrapper NSAndroidClient.ReadResponse(code = response.raw().networkResponse?.code ?: response.code(), lastServerModified = 0, values = response.body()?.result?.map(RemoteEntry::toSgv).toNotNull()) return@callWrapper NSAndroidClient.ReadResponse(code = response.raw().networkResponse?.code ?: response.code(), lastServerModified = 0, values = response.body()?.result?.map(RemoteEntry::toSgv).toNotNull())
} else { } else if (response.code() in 400..499)
throw InvalidParameterNightscoutException(response.errorBody()?.string() ?: response.message())
else
throw UnsuccessfullNightscoutException() throw UnsuccessfullNightscoutException()
} }
}
override suspend fun getSgvsModifiedSince(from: Long, limit: Long): NSAndroidClient.ReadResponse<List<NSSgvV3>> = callWrapper(dispatcher) { override suspend fun getSgvsModifiedSince(from: Long, limit: Long): NSAndroidClient.ReadResponse<List<NSSgvV3>> = callWrapper(dispatcher) {
@ -127,20 +130,22 @@ class NSAndroidClientImpl(
val eTagString = response.headers()["ETag"] val eTagString = response.headers()["ETag"]
val eTag = eTagString?.substring(3, eTagString.length - 1)?.toLong() val eTag = eTagString?.substring(3, eTagString.length - 1)?.toLong()
return@callWrapper NSAndroidClient.ReadResponse(code = response.raw().networkResponse?.code ?: response.code(), lastServerModified = eTag, values = response.body()?.result?.map(RemoteEntry::toSgv).toNotNull()) return@callWrapper NSAndroidClient.ReadResponse(code = response.raw().networkResponse?.code ?: response.code(), lastServerModified = eTag, values = response.body()?.result?.map(RemoteEntry::toSgv).toNotNull())
} else { } else if (response.code() in 400..499)
throw InvalidParameterNightscoutException(response.errorBody()?.string() ?: response.message())
else
throw UnsuccessfullNightscoutException() throw UnsuccessfullNightscoutException()
} }
}
override suspend fun getSgvsNewerThan(from: Long, limit: Long): NSAndroidClient.ReadResponse<List<NSSgvV3>> = callWrapper(dispatcher) { override suspend fun getSgvsNewerThan(from: Long, limit: Long): NSAndroidClient.ReadResponse<List<NSSgvV3>> = callWrapper(dispatcher) {
val response = api.getSgvsNewerThan(from, limit) val response = api.getSgvsNewerThan(from, limit)
if (response.isSuccessful) { if (response.isSuccessful) {
return@callWrapper NSAndroidClient.ReadResponse(code = response.raw().networkResponse?.code ?: response.code(), lastServerModified = 0, values = response.body()?.result?.map(RemoteEntry::toSgv).toNotNull()) return@callWrapper NSAndroidClient.ReadResponse(code = response.raw().networkResponse?.code ?: response.code(), lastServerModified = 0, values = response.body()?.result?.map(RemoteEntry::toSgv).toNotNull())
} else { } else if (response.code() in 400..499)
throw InvalidParameterNightscoutException(response.errorBody()?.string() ?: response.message())
else
throw UnsuccessfullNightscoutException() throw UnsuccessfullNightscoutException()
} }
}
override suspend fun createSvg(nsSgvV3: NSSgvV3): CreateUpdateResponse = callWrapper(dispatcher) { override suspend fun createSvg(nsSgvV3: NSSgvV3): CreateUpdateResponse = callWrapper(dispatcher) {
@ -176,7 +181,10 @@ class NSAndroidClientImpl(
identifier = null, identifier = null,
errorResponse = errorResponse errorResponse = errorResponse
) )
} else throw UnknownResponseNightscoutException() } else if (response.code() in 400..499)
throw InvalidParameterNightscoutException(response.errorBody()?.string() ?: response.message())
else
throw UnsuccessfullNightscoutException()
} }
override suspend fun updateSvg(nsSgvV3: NSSgvV3): CreateUpdateResponse = callWrapper(dispatcher) { override suspend fun updateSvg(nsSgvV3: NSSgvV3): CreateUpdateResponse = callWrapper(dispatcher) {
@ -205,20 +213,22 @@ class NSAndroidClientImpl(
deduplicatedIdentifier = null, deduplicatedIdentifier = null,
lastModified = null lastModified = null
) )
} else { } else if (response.code() in 400..499)
throw InvalidParameterNightscoutException(response.errorBody()?.string() ?: response.message())
else
throw UnsuccessfullNightscoutException() throw UnsuccessfullNightscoutException()
} }
}
override suspend fun getTreatmentsNewerThan(createdAt: String, limit: Long): NSAndroidClient.ReadResponse<List<NSTreatment>> = callWrapper(dispatcher) { override suspend fun getTreatmentsNewerThan(createdAt: String, limit: Long): NSAndroidClient.ReadResponse<List<NSTreatment>> = callWrapper(dispatcher) {
val response = api.getTreatmentsNewerThan(createdAt, limit) val response = api.getTreatmentsNewerThan(createdAt, limit)
if (response.isSuccessful) { if (response.isSuccessful) {
return@callWrapper NSAndroidClient.ReadResponse(code = response.raw().networkResponse?.code ?: response.code(), lastServerModified = 0, values = response.body()?.result?.map(RemoteTreatment::toTreatment).toNotNull()) return@callWrapper NSAndroidClient.ReadResponse(code = response.raw().networkResponse?.code ?: response.code(), lastServerModified = 0, values = response.body()?.result?.map(RemoteTreatment::toTreatment).toNotNull())
} else { } else if (response.code() in 400..499)
throw InvalidParameterNightscoutException(response.errorBody()?.string() ?: response.message())
else
throw UnsuccessfullNightscoutException() throw UnsuccessfullNightscoutException()
} }
}
override suspend fun getTreatmentsModifiedSince(from: Long, limit: Long): NSAndroidClient.ReadResponse<List<NSTreatment>> = callWrapper(dispatcher) { override suspend fun getTreatmentsModifiedSince(from: Long, limit: Long): NSAndroidClient.ReadResponse<List<NSTreatment>> = callWrapper(dispatcher) {
@ -226,22 +236,26 @@ class NSAndroidClientImpl(
if (response.isSuccessful) { if (response.isSuccessful) {
val eTagString = response.headers()["ETag"] val eTagString = response.headers()["ETag"]
val eTag = eTagString?.substring(3, eTagString.length - 1)?.toLong() val eTag = eTagString?.substring(3, eTagString.length - 1)?.toLong()
return@callWrapper NSAndroidClient.ReadResponse(code = response.raw().networkResponse?.code ?: response.code(), lastServerModified = eTag, values = response.body()?.result?.map return@callWrapper NSAndroidClient.ReadResponse(
(RemoteTreatment::toTreatment).toNotNull()) code = response.raw().networkResponse?.code ?: response.code(), lastServerModified = eTag, values = response.body()?.result?.map
} else { (RemoteTreatment::toTreatment).toNotNull()
)
} else if (response.code() in 400..499)
throw InvalidParameterNightscoutException(response.errorBody()?.string() ?: response.message())
else
throw UnsuccessfullNightscoutException() throw UnsuccessfullNightscoutException()
} }
}
override suspend fun getDeviceStatusModifiedSince(from: Long): List<NSDeviceStatus> = callWrapper(dispatcher) { override suspend fun getDeviceStatusModifiedSince(from: Long): List<NSDeviceStatus> = callWrapper(dispatcher) {
val response = api.getDeviceStatusModifiedSince(from) val response = api.getDeviceStatusModifiedSince(from)
if (response.isSuccessful) { if (response.isSuccessful) {
return@callWrapper response.body()?.result?.map(RemoteDeviceStatus::toNSDeviceStatus).toNotNull() return@callWrapper response.body()?.result?.map(RemoteDeviceStatus::toNSDeviceStatus).toNotNull()
} else { } else if (response.code() in 400..499)
throw InvalidParameterNightscoutException(response.errorBody()?.string() ?: response.message())
else
throw UnsuccessfullNightscoutException() throw UnsuccessfullNightscoutException()
} }
}
override suspend fun createDeviceStatus(nsDeviceStatus: NSDeviceStatus): CreateUpdateResponse = callWrapper(dispatcher) { override suspend fun createDeviceStatus(nsDeviceStatus: NSDeviceStatus): CreateUpdateResponse = callWrapper(dispatcher) {
@ -266,10 +280,11 @@ class NSAndroidClientImpl(
lastModified = response.body()?.result?.lastModified lastModified = response.body()?.result?.lastModified
) )
} else throw UnknownResponseNightscoutException() } else throw UnknownResponseNightscoutException()
} else { } else if (response.code() in 400..499)
throw InvalidParameterNightscoutException(response.errorBody()?.string() ?: response.message())
else
throw UnsuccessfullNightscoutException() throw UnsuccessfullNightscoutException()
} }
}
override suspend fun createTreatment(nsTreatment: NSTreatment): CreateUpdateResponse = callWrapper(dispatcher) { override suspend fun createTreatment(nsTreatment: NSTreatment): CreateUpdateResponse = callWrapper(dispatcher) {
@ -304,7 +319,10 @@ class NSAndroidClientImpl(
identifier = null, identifier = null,
errorResponse = errorResponse errorResponse = errorResponse
) )
} else throw UnknownResponseNightscoutException() } else if (response.code() in 400..499)
throw InvalidParameterNightscoutException(response.errorBody()?.string() ?: response.message())
else
throw UnsuccessfullNightscoutException()
} }
override suspend fun updateTreatment(nsTreatment: NSTreatment): CreateUpdateResponse = callWrapper(dispatcher) { override suspend fun updateTreatment(nsTreatment: NSTreatment): CreateUpdateResponse = callWrapper(dispatcher) {
@ -333,20 +351,22 @@ class NSAndroidClientImpl(
deduplicatedIdentifier = null, deduplicatedIdentifier = null,
lastModified = null lastModified = null
) )
} else { } else if (response.code() in 400..499)
throw InvalidParameterNightscoutException(response.errorBody()?.string() ?: response.message())
else
throw UnsuccessfullNightscoutException() throw UnsuccessfullNightscoutException()
} }
}
override suspend fun getFoods(limit: Long): NSAndroidClient.ReadResponse<List<NSFood>> = callWrapper(dispatcher) { override suspend fun getFoods(limit: Long): NSAndroidClient.ReadResponse<List<NSFood>> = callWrapper(dispatcher) {
val response = api.getFoods(limit) val response = api.getFoods(limit)
if (response.isSuccessful) { if (response.isSuccessful) {
return@callWrapper NSAndroidClient.ReadResponse(code = response.raw().networkResponse?.code ?: response.code(), lastServerModified = 0, values = response.body()?.result?.map(RemoteFood::toNSFood).toNotNull()) return@callWrapper NSAndroidClient.ReadResponse(code = response.raw().networkResponse?.code ?: response.code(), lastServerModified = 0, values = response.body()?.result?.map(RemoteFood::toNSFood).toNotNull())
} else { } else if (response.code() in 400..499)
throw InvalidParameterNightscoutException(response.errorBody()?.string() ?: response.message())
else
throw UnsuccessfullNightscoutException() throw UnsuccessfullNightscoutException()
} }
}
/* /*
override suspend fun getFoodsModifiedSince(from: Long, limit: Long): NSAndroidClient.ReadResponse<List<NSFood>> = callWrapper(dispatcher) { override suspend fun getFoodsModifiedSince(from: Long, limit: Long): NSAndroidClient.ReadResponse<List<NSFood>> = callWrapper(dispatcher) {
@ -412,10 +432,11 @@ class NSAndroidClientImpl(
deduplicatedIdentifier = null, deduplicatedIdentifier = null,
lastModified = null lastModified = null
) )
} else { } else if (response.code() in 400..499)
throw InvalidParameterNightscoutException(response.errorBody()?.string() ?: response.message())
else
throw UnsuccessfullNightscoutException() throw UnsuccessfullNightscoutException()
} }
}
override suspend fun createProfileStore(remoteProfileStore: JSONObject): CreateUpdateResponse = callWrapper(dispatcher) { override suspend fun createProfileStore(remoteProfileStore: JSONObject): CreateUpdateResponse = callWrapper(dispatcher) {
remoteProfileStore.put("app", "AAPS") remoteProfileStore.put("app", "AAPS")
@ -438,10 +459,11 @@ class NSAndroidClientImpl(
lastModified = response.body()?.result?.lastModified lastModified = response.body()?.result?.lastModified
) )
} else throw UnsuccessfullNightscoutException() } else throw UnsuccessfullNightscoutException()
} else { } else if (response.code() in 400..499)
throw InvalidParameterNightscoutException(response.errorBody()?.string() ?: response.message())
else
throw UnsuccessfullNightscoutException() throw UnsuccessfullNightscoutException()
} }
}
override suspend fun getLastProfileStore(): NSAndroidClient.ReadResponse<List<JSONObject>> = callWrapper(dispatcher) { override suspend fun getLastProfileStore(): NSAndroidClient.ReadResponse<List<JSONObject>> = callWrapper(dispatcher) {
@ -450,10 +472,11 @@ class NSAndroidClientImpl(
val eTagString = response.headers()["ETag"] val eTagString = response.headers()["ETag"]
val eTag = eTagString?.substring(3, eTagString.length - 1)?.toLong() val eTag = eTagString?.substring(3, eTagString.length - 1)?.toLong()
return@callWrapper NSAndroidClient.ReadResponse(code = response.raw().networkResponse?.code ?: response.code(), lastServerModified = eTag, values = response.body()?.result.toNotNull()) return@callWrapper NSAndroidClient.ReadResponse(code = response.raw().networkResponse?.code ?: response.code(), lastServerModified = eTag, values = response.body()?.result.toNotNull())
} else { } else if (response.code() in 400..499)
throw InvalidParameterNightscoutException(response.errorBody()?.string() ?: response.message())
else
throw UnsuccessfullNightscoutException() throw UnsuccessfullNightscoutException()
} }
}
override suspend fun getProfileModifiedSince(from: Long): NSAndroidClient.ReadResponse<List<JSONObject>> = callWrapper(dispatcher) { override suspend fun getProfileModifiedSince(from: Long): NSAndroidClient.ReadResponse<List<JSONObject>> = callWrapper(dispatcher) {
@ -463,10 +486,11 @@ class NSAndroidClientImpl(
val eTagString = response.headers()["ETag"] val eTagString = response.headers()["ETag"]
val eTag = eTagString?.substring(3, eTagString.length - 1)?.toLong() val eTag = eTagString?.substring(3, eTagString.length - 1)?.toLong()
return@callWrapper NSAndroidClient.ReadResponse(code = response.raw().networkResponse?.code ?: response.code(), lastServerModified = eTag, values = response.body()?.result.toNotNull()) return@callWrapper NSAndroidClient.ReadResponse(code = response.raw().networkResponse?.code ?: response.code(), lastServerModified = eTag, values = response.body()?.result.toNotNull())
} else { } else if (response.code() in 400..499)
throw InvalidParameterNightscoutException(response.errorBody()?.string() ?: response.message())
else
throw UnsuccessfullNightscoutException() throw UnsuccessfullNightscoutException()
} }
}
private suspend fun <T> callWrapper(dispatcher: CoroutineDispatcher, block: suspend () -> T): T = private suspend fun <T> callWrapper(dispatcher: CoroutineDispatcher, block: suspend () -> T): T =

View file

@ -1,3 +1,9 @@
package info.nightscout.sdk.exceptions package info.nightscout.sdk.exceptions
class InvalidFormatNightscoutException : NightscoutException() @Suppress("unused")
class InvalidFormatNightscoutException : NightscoutException {
constructor() : super()
constructor(message: String) : super(message)
constructor(message: String, cause: Throwable) : super(message, cause)
constructor(cause: Throwable?) : super(cause)
}

View file

@ -0,0 +1,9 @@
package info.nightscout.sdk.exceptions
@Suppress("unused")
class InvalidParameterNightscoutException : NightscoutException {
constructor() : super()
constructor(message: String) : super(message)
constructor(message: String, cause: Throwable) : super(message, cause)
constructor(cause: Throwable?) : super(cause)
}

View file

@ -7,7 +7,7 @@ import kotlin.math.abs
/** /**
* Sync the TemporaryTarget from NS * Sync the TemporaryTarget from NS
*/ */
class SyncNsTemporaryTargetTransaction(private val temporaryTargets: List<TemporaryTarget>, private val nsClientMode: Boolean) : class SyncNsTemporaryTargetTransaction(private val temporaryTargets: List<TemporaryTarget>) :
Transaction<SyncNsTemporaryTargetTransaction.TransactionResult>() { Transaction<SyncNsTemporaryTargetTransaction.TransactionResult>() {
override fun run(): TransactionResult { override fun run(): TransactionResult {
@ -28,7 +28,7 @@ class SyncNsTemporaryTargetTransaction(private val temporaryTargets: List<Tempor
database.temporaryTargetDao.updateExistingEntry(current) database.temporaryTargetDao.updateExistingEntry(current)
result.invalidated.add(current) result.invalidated.add(current)
} }
if (current.duration != temporaryTarget.duration && nsClientMode) { if (current.duration != temporaryTarget.duration) {
current.duration = temporaryTarget.duration current.duration = temporaryTarget.duration
database.temporaryTargetDao.updateExistingEntry(current) database.temporaryTargetDao.updateExistingEntry(current)
result.updatedDuration.add(current) result.updatedDuration.add(current)

View file

@ -59,7 +59,6 @@ class ConfigBuilderPlugin @Inject constructor(
), ConfigBuilder { ), ConfigBuilder {
override fun initialize() { override fun initialize() {
activePlugin.loadDefaults()
loadSettings() loadSettings()
setAlwaysEnabledPluginsEnabled() setAlwaysEnabledPluginsEnabled()
rxBus.send(EventAppInitialized()) rxBus.send(EventAppInitialized())
@ -103,18 +102,14 @@ class ConfigBuilderPlugin @Inject constructor(
private fun loadPref(p: PluginBase, type: PluginType) { private fun loadPref(p: PluginBase, type: PluginType) {
val settingEnabled = "ConfigBuilder_" + type.name + "_" + p.javaClass.simpleName + "_Enabled" val settingEnabled = "ConfigBuilder_" + type.name + "_" + p.javaClass.simpleName + "_Enabled"
if (sp.contains(settingEnabled)) p.setPluginEnabled( if (sp.contains(settingEnabled)) p.setPluginEnabled(type, sp.getBoolean(settingEnabled, false))
type, else if (p.getType() == type && (p.pluginDescription.enableByDefault || p.pluginDescription.alwaysEnabled)) {
sp.getBoolean(settingEnabled, false)
) else if (p.getType() == type && (p.pluginDescription.enableByDefault || p.pluginDescription.alwaysEnabled)) {
p.setPluginEnabled(type, true) p.setPluginEnabled(type, true)
} }
aapsLogger.debug(LTag.CONFIGBUILDER, "Loaded: " + settingEnabled + ":" + p.isEnabled(type)) aapsLogger.debug(LTag.CONFIGBUILDER, "Loaded: " + settingEnabled + ":" + p.isEnabled(type))
val settingVisible = "ConfigBuilder_" + type.name + "_" + p.javaClass.simpleName + "_Visible" val settingVisible = "ConfigBuilder_" + type.name + "_" + p.javaClass.simpleName + "_Visible"
if (sp.contains(settingVisible)) p.setFragmentVisible( if (sp.contains(settingVisible)) p.setFragmentVisible(type, sp.getBoolean(settingVisible, false) && sp.getBoolean(settingEnabled, false))
type, else if (p.getType() == type && p.pluginDescription.visibleByDefault) {
sp.getBoolean(settingVisible, false) && sp.getBoolean(settingEnabled, false)
) else if (p.getType() == type && p.pluginDescription.visibleByDefault) {
p.setFragmentVisible(type, true) p.setFragmentVisible(type, true)
} }
aapsLogger.debug(LTag.CONFIGBUILDER, "Loaded: " + settingVisible + ":" + p.isFragmentVisible()) aapsLogger.debug(LTag.CONFIGBUILDER, "Loaded: " + settingVisible + ":" + p.isFragmentVisible())
@ -195,16 +190,16 @@ class ConfigBuilderPlugin @Inject constructor(
override fun processOnEnabledCategoryChanged(changedPlugin: PluginBase, type: PluginType) { override fun processOnEnabledCategoryChanged(changedPlugin: PluginBase, type: PluginType) {
var pluginsInCategory: ArrayList<PluginBase>? = null var pluginsInCategory: ArrayList<PluginBase>? = null
when (type) { when {
PluginType.INSULIN -> pluginsInCategory = activePlugin.getSpecificPluginsListByInterface(Insulin::class.java) type == PluginType.INSULIN -> pluginsInCategory = activePlugin.getSpecificPluginsListByInterface(Insulin::class.java)
PluginType.SENSITIVITY -> pluginsInCategory = activePlugin.getSpecificPluginsListByInterface(Sensitivity::class.java) type == PluginType.SENSITIVITY -> pluginsInCategory = activePlugin.getSpecificPluginsListByInterface(Sensitivity::class.java)
PluginType.SMOOTHING -> pluginsInCategory = activePlugin.getSpecificPluginsListByInterface(Smoothing::class.java) type == PluginType.SMOOTHING -> pluginsInCategory = activePlugin.getSpecificPluginsListByInterface(Smoothing::class.java)
PluginType.APS -> pluginsInCategory = activePlugin.getSpecificPluginsListByInterface(APS::class.java) type == PluginType.APS -> pluginsInCategory = activePlugin.getSpecificPluginsListByInterface(APS::class.java)
PluginType.PROFILE -> pluginsInCategory = activePlugin.getSpecificPluginsListByInterface(ProfileSource::class.java) type == PluginType.PROFILE -> pluginsInCategory = activePlugin.getSpecificPluginsListByInterface(ProfileSource::class.java)
PluginType.BGSOURCE -> pluginsInCategory = activePlugin.getSpecificPluginsListByInterface(BgSource::class.java) type == PluginType.BGSOURCE -> pluginsInCategory = activePlugin.getSpecificPluginsListByInterface(BgSource::class.java)
PluginType.PUMP -> pluginsInCategory = activePlugin.getSpecificPluginsListByInterface(Pump::class.java) type == PluginType.PUMP -> pluginsInCategory = activePlugin.getSpecificPluginsListByInterface(Pump::class.java)
// Process only NSClients // Process only NSClients
PluginType.SYNC -> pluginsInCategory = activePlugin.getSpecificPluginsListByInterface(NsClient::class.java) changedPlugin is NsClient -> pluginsInCategory = activePlugin.getSpecificPluginsListByInterface(NsClient::class.java)
else -> { else -> {
} }

View file

@ -225,9 +225,9 @@ class SWDefinition @Inject constructor(
.add( .add(
SWEventListener(injector, EventSWSyncStatus::class.java) SWEventListener(injector, EventSWSyncStatus::class.java)
.label(R.string.status) .label(R.string.status)
.initialStatus(activePlugin.firstActiveSync?.status ?: "") .initialStatus(activePlugin.activeNsClient?.status ?: "")
) )
.validator { activePlugin.firstActiveSync?.connected == true && activePlugin.firstActiveSync?.hasWritePermission == true } .validator { activePlugin.activeNsClient?.connected == true && activePlugin.activeNsClient?.hasWritePermission == true }
private val screenPatientName get() = SWScreen(injector, R.string.patient_name) private val screenPatientName get() = SWScreen(injector, R.string.patient_name)
.skippable(true) .skippable(true)

View file

@ -1,8 +1,6 @@
package info.nightscout.plugins.sync.nsShared package info.nightscout.plugins.sync.nsShared
import android.os.Bundle import android.os.Bundle
import android.os.Handler
import android.os.HandlerThread
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.Menu import android.view.Menu
import android.view.MenuInflater import android.view.MenuInflater
@ -22,7 +20,6 @@ import info.nightscout.interfaces.plugin.ActivePlugin
import info.nightscout.interfaces.plugin.PluginBase import info.nightscout.interfaces.plugin.PluginBase
import info.nightscout.interfaces.plugin.PluginFragment import info.nightscout.interfaces.plugin.PluginFragment
import info.nightscout.interfaces.sync.DataSyncSelector import info.nightscout.interfaces.sync.DataSyncSelector
import info.nightscout.interfaces.sync.NsClient
import info.nightscout.plugins.sync.R import info.nightscout.plugins.sync.R
import info.nightscout.plugins.sync.databinding.NsClientFragmentBinding import info.nightscout.plugins.sync.databinding.NsClientFragmentBinding
import info.nightscout.plugins.sync.nsShared.events.EventNSClientUpdateGUI import info.nightscout.plugins.sync.nsShared.events.EventNSClientUpdateGUI
@ -60,11 +57,9 @@ class NSClientFragment : DaggerFragment(), MenuProvider, PluginFragment {
override var plugin: PluginBase? = null override var plugin: PluginBase? = null
private val nsClientPlugin private val nsClientPlugin
get() = activePlugin.activeNsClient get() = activePlugin.activeNsClient
private val version: NsClient.Version get() = nsClientPlugin?.version ?: NsClient.Version.NONE
private val disposable = CompositeDisposable() private val disposable = CompositeDisposable()
private var handler = Handler(HandlerThread(this::class.simpleName + "Handler").also { it.start() }.looper)
private var _binding: NsClientFragmentBinding? = null private var _binding: NsClientFragmentBinding? = null
// This property is only valid between onCreateView and // This property is only valid between onCreateView and

View file

@ -325,7 +325,7 @@ class StoreDataForDbImpl @Inject constructor(
SystemClock.sleep(pause) SystemClock.sleep(pause)
if (temporaryTargets.isNotEmpty()) if (temporaryTargets.isNotEmpty())
repository.runTransactionForResult(SyncNsTemporaryTargetTransaction(temporaryTargets, config.NSCLIENT)) repository.runTransactionForResult(SyncNsTemporaryTargetTransaction(temporaryTargets))
.doOnError { .doOnError {
aapsLogger.error(LTag.DATABASE, "Error while saving temporary target", it) aapsLogger.error(LTag.DATABASE, "Error while saving temporary target", it)
} }

View file

@ -18,6 +18,7 @@ import info.nightscout.core.validators.ValidatingEditTextPreference
import info.nightscout.interfaces.Config import info.nightscout.interfaces.Config
import info.nightscout.interfaces.Constants import info.nightscout.interfaces.Constants
import info.nightscout.interfaces.nsclient.NSAlarm import info.nightscout.interfaces.nsclient.NSAlarm
import info.nightscout.interfaces.nsclient.NSSettingsStatus
import info.nightscout.interfaces.plugin.ActivePlugin import info.nightscout.interfaces.plugin.ActivePlugin
import info.nightscout.interfaces.plugin.PluginBase import info.nightscout.interfaces.plugin.PluginBase
import info.nightscout.interfaces.plugin.PluginDescription import info.nightscout.interfaces.plugin.PluginDescription
@ -71,7 +72,8 @@ class NSClientPlugin @Inject constructor(
private val uiInteraction: UiInteraction, private val uiInteraction: UiInteraction,
private val activePlugin: ActivePlugin, private val activePlugin: ActivePlugin,
private val dateUtil: DateUtil, private val dateUtil: DateUtil,
private val profileFunction: ProfileFunction private val profileFunction: ProfileFunction,
private val nsSettingsStatus: NSSettingsStatus
) : NsClient, Sync, PluginBase( ) : NsClient, Sync, PluginBase(
PluginDescription() PluginDescription()
.mainType(PluginType.SYNC) .mainType(PluginType.SYNC)
@ -154,7 +156,6 @@ class NSClientPlugin @Inject constructor(
if (activePlugin.activeBgSource is DoingOwnUploadSource) { if (activePlugin.activeBgSource is DoingOwnUploadSource) {
preferenceFragment.findPreference<SwitchPreference>(rh.gs(info.nightscout.core.utils.R.string.key_do_ns_upload))?.isVisible = false preferenceFragment.findPreference<SwitchPreference>(rh.gs(info.nightscout.core.utils.R.string.key_do_ns_upload))?.isVisible = false
} }
preferenceFragment.findPreference<ValidatingEditTextPreference>(rh.gs(R.string.key_ns_client_token))?.isVisible = false
} }
override val hasWritePermission: Boolean get() = nsClientService?.hasWriteAuth ?: false override val hasWritePermission: Boolean get() = nsClientService?.hasWriteAuth ?: false
@ -180,6 +181,8 @@ class NSClientPlugin @Inject constructor(
} }
} }
override fun detectedNsVersion(): String? = nsSettingsStatus.getVersion()
private fun addToLog(ev: EventNSClientNewLog) { private fun addToLog(ev: EventNSClientNewLog) {
synchronized(listLog) { synchronized(listLog) {
listLog.add(ev) listLog.add(ev)
@ -213,9 +216,6 @@ class NSClientPlugin @Inject constructor(
rxBus.send(EventPreferenceChange(rh.gs(R.string.key_ns_client_paused))) rxBus.send(EventPreferenceChange(rh.gs(R.string.key_ns_client_paused)))
} }
override val version: NsClient.Version
get() = NsClient.Version.V1
override val address: String get() = nsClientService?.nsURL ?: "" override val address: String get() = nsClientService?.nsURL ?: ""
override fun handleClearAlarm(originalAlarm: NSAlarm, silenceTimeInMilliseconds: Long) { override fun handleClearAlarm(originalAlarm: NSAlarm, silenceTimeInMilliseconds: Long) {

View file

@ -16,7 +16,6 @@ import com.google.gson.GsonBuilder
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.annotations.OpenForTesting import info.nightscout.androidaps.annotations.OpenForTesting
import info.nightscout.core.utils.fabric.FabricPrivacy import info.nightscout.core.utils.fabric.FabricPrivacy
import info.nightscout.core.validators.ValidatingEditTextPreference
import info.nightscout.database.ValueWrapper import info.nightscout.database.ValueWrapper
import info.nightscout.database.entities.interfaces.TraceableDBEntry import info.nightscout.database.entities.interfaces.TraceableDBEntry
import info.nightscout.database.impl.AppRepository import info.nightscout.database.impl.AppRepository
@ -111,7 +110,7 @@ class NSClientV3Plugin @Inject constructor(
.pluginIcon(info.nightscout.core.ui.R.drawable.ic_nightscout_syncs) .pluginIcon(info.nightscout.core.ui.R.drawable.ic_nightscout_syncs)
.pluginName(R.string.ns_client_v3) .pluginName(R.string.ns_client_v3)
.shortName(R.string.ns_client_v3_short_name) .shortName(R.string.ns_client_v3_short_name)
.preferencesId(R.xml.pref_ns_client) .preferencesId(R.xml.pref_ns_client_v3)
.description(R.string.description_ns_client_v3), .description(R.string.description_ns_client_v3),
aapsLogger, rh, injector aapsLogger, rh, injector
) { ) {
@ -120,6 +119,7 @@ class NSClientV3Plugin @Inject constructor(
val JOB_NAME: String = this::class.java.simpleName val JOB_NAME: String = this::class.java.simpleName
val REFRESH_INTERVAL = T.secs(30).msecs() val REFRESH_INTERVAL = T.secs(30).msecs()
const val RECORDS_TO_LOAD = 500L
} }
private val disposable = CompositeDisposable() private val disposable = CompositeDisposable()
@ -170,6 +170,7 @@ class NSClientV3Plugin @Inject constructor(
.subscribe({ ev -> .subscribe({ ev ->
nsClientReceiverDelegate.onStatusEvent(ev) nsClientReceiverDelegate.onStatusEvent(ev)
setClient() setClient()
rxBus.send(EventNSClientUpdateGUI())
}, fabricPrivacy::logException) }, fabricPrivacy::logException)
disposable += rxBus disposable += rxBus
.toObservable(EventPreferenceChange::class.java) .toObservable(EventPreferenceChange::class.java)
@ -195,7 +196,10 @@ class NSClientV3Plugin @Inject constructor(
disposable += rxBus disposable += rxBus
.toObservable(EventChargingState::class.java) .toObservable(EventChargingState::class.java)
.observeOn(aapsSchedulers.io) .observeOn(aapsSchedulers.io)
.subscribe({ ev -> nsClientReceiverDelegate.onStatusEvent(ev) }, fabricPrivacy::logException) .subscribe({ ev ->
nsClientReceiverDelegate.onStatusEvent(ev)
rxBus.send(EventNSClientUpdateGUI())
}, fabricPrivacy::logException)
disposable += rxBus disposable += rxBus
.toObservable(EventNSClientResend::class.java) .toObservable(EventNSClientResend::class.java)
.observeOn(aapsSchedulers.io) .observeOn(aapsSchedulers.io)
@ -216,8 +220,9 @@ class NSClientV3Plugin @Inject constructor(
if (it is ValueWrapper.Existing) { if (it is ValueWrapper.Existing) {
if (it.value.timestamp < dateUtil.now() - T.mins(5).plus(T.secs(20)).msecs()) if (it.value.timestamp < dateUtil.now() - T.mins(5).plus(T.secs(20)).msecs())
executeLoop("MAIN_LOOP", forceNew = false) executeLoop("MAIN_LOOP", forceNew = false)
else else {
rxBus.send(EventNSClientNewLog("RECENT", "No need to load")) if (isAllowed) rxBus.send(EventNSClientNewLog("RECENT", "No need to load"))
}
} else executeLoop("MAIN_LOOP", forceNew = false) } else executeLoop("MAIN_LOOP", forceNew = false)
} }
} }
@ -241,7 +246,6 @@ class NSClientV3Plugin @Inject constructor(
preferenceFragment.findPreference<SwitchPreference>(rh.gs(info.nightscout.core.utils.R.string.key_ns_create_announcements_from_carbs_req))?.isVisible = false preferenceFragment.findPreference<SwitchPreference>(rh.gs(info.nightscout.core.utils.R.string.key_ns_create_announcements_from_carbs_req))?.isVisible = false
} }
preferenceFragment.findPreference<SwitchPreference>(rh.gs(R.string.key_ns_receive_tbr_eb))?.isVisible = config.isEngineeringMode() preferenceFragment.findPreference<SwitchPreference>(rh.gs(R.string.key_ns_receive_tbr_eb))?.isVisible = config.isEngineeringMode()
preferenceFragment.findPreference<ValidatingEditTextPreference>(rh.gs(info.nightscout.core.utils.R.string.key_nsclientinternal_api_secret))?.isVisible = false
} }
override val hasWritePermission: Boolean get() = nsAndroidClient?.lastStatus?.apiPermissions?.isFull() ?: false override val hasWritePermission: Boolean get() = nsAndroidClient?.lastStatus?.apiPermissions?.isFull() ?: false
@ -296,7 +300,7 @@ class NSClientV3Plugin @Inject constructor(
rxBus.send(EventPreferenceChange(rh.gs(R.string.key_ns_client_paused))) rxBus.send(EventPreferenceChange(rh.gs(R.string.key_ns_client_paused)))
} }
override val version: NsClient.Version get() = NsClient.Version.V3 override fun detectedNsVersion(): String? = nsAndroidClient?.lastStatus?.version
override val address: String get() = sp.getString(info.nightscout.core.utils.R.string.key_nsclientinternal_url, "") override val address: String get() = sp.getString(info.nightscout.core.utils.R.string.key_nsclientinternal_url, "")

View file

@ -59,9 +59,9 @@ class LoadBgWorker(
if ((nsClientV3Plugin.newestDataOnServer?.collections?.entries ?: Long.MAX_VALUE) > lastLoaded) { if ((nsClientV3Plugin.newestDataOnServer?.collections?.entries ?: Long.MAX_VALUE) > lastLoaded) {
val sgvs: List<NSSgvV3> val sgvs: List<NSSgvV3>
val response: NSAndroidClient.ReadResponse<List<NSSgvV3>>? val response: NSAndroidClient.ReadResponse<List<NSSgvV3>>?
if (isFirstLoad) response = nsAndroidClient.getSgvsNewerThan(lastLoaded, 500) if (isFirstLoad) response = nsAndroidClient.getSgvsNewerThan(lastLoaded, NSClientV3Plugin.RECORDS_TO_LOAD)
else { else {
response = nsAndroidClient.getSgvsModifiedSince(lastLoaded, 500) response = nsAndroidClient.getSgvsModifiedSince(lastLoaded, NSClientV3Plugin.RECORDS_TO_LOAD)
response.lastServerModified?.let { nsClientV3Plugin.lastLoadedSrvModified.collections.entries = it } response.lastServerModified?.let { nsClientV3Plugin.lastLoadedSrvModified.collections.entries = it }
nsClientV3Plugin.storeLastLoadedSrvModified() nsClientV3Plugin.storeLastLoadedSrvModified()
nsClientV3Plugin.scheduleIrregularExecution() // Idea is to run after 5 min after last BG nsClientV3Plugin.scheduleIrregularExecution() // Idea is to run after 5 min after last BG

View file

@ -47,9 +47,9 @@ class LoadTreatmentsWorker(
val response: NSAndroidClient.ReadResponse<List<NSTreatment>>? val response: NSAndroidClient.ReadResponse<List<NSTreatment>>?
if (isFirstLoad) { if (isFirstLoad) {
val lastLoadedIso = dateUtil.toISOString(lastLoaded) val lastLoadedIso = dateUtil.toISOString(lastLoaded)
response = nsAndroidClient.getTreatmentsNewerThan(lastLoadedIso, 500) response = nsAndroidClient.getTreatmentsNewerThan(lastLoadedIso, NSClientV3Plugin.RECORDS_TO_LOAD)
} else { } else {
response = nsAndroidClient.getTreatmentsModifiedSince(lastLoaded, 500) response = nsAndroidClient.getTreatmentsModifiedSince(lastLoaded, NSClientV3Plugin.RECORDS_TO_LOAD)
response.lastServerModified?.let { nsClientV3Plugin.lastLoadedSrvModified.collections.treatments = it } response.lastServerModified?.let { nsClientV3Plugin.lastLoadedSrvModified.collections.treatments = it }
nsClientV3Plugin.storeLastLoadedSrvModified() nsClientV3Plugin.storeLastLoadedSrvModified()
} }

View file

@ -26,15 +26,6 @@
validate:minLength="12" validate:minLength="12"
validate:testType="minLength"/> validate:testType="minLength"/>
<info.nightscout.core.validators.ValidatingEditTextPreference
android:dialogMessage="@string/nsclient_token_dialog_message"
android:dialogTitle="@string/nsclient_token_dialog_title"
android:inputType="textPassword"
android:key="@string/key_ns_client_token"
android:title="@string/nsclient_token_title"
validate:minLength="17"
validate:testType="minLength"/>
<androidx.preference.PreferenceScreen <androidx.preference.PreferenceScreen
android:key="@string/ns_sync_options" android:key="@string/ns_sync_options"
android:title="@string/ns_sync_options"> android:title="@string/ns_sync_options">

View file

@ -0,0 +1,217 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:validate="http://schemas.android.com/apk/res-auto">
<PreferenceCategory
android:key="@string/key_ns_client_settings"
android:title="@string/ns_client_internal_title"
app:initialExpandedChildrenCount="0">
<info.nightscout.core.validators.ValidatingEditTextPreference
android:defaultValue="https://{YOUR-SITE}.azurewebsites.net/"
android:dialogMessage="@string/ns_client_url_dialog_message"
android:inputType="textUri"
android:key="@string/key_nsclientinternal_url"
android:selectAllOnFocus="true"
android:title="@string/ns_client_url_title"
validate:testType="httpsUrl" />
<info.nightscout.core.validators.ValidatingEditTextPreference
android:dialogMessage="@string/nsclient_token_dialog_message"
android:dialogTitle="@string/nsclient_token_dialog_title"
android:inputType="textPassword"
android:key="@string/key_ns_client_token"
android:title="@string/nsclient_token_title"
validate:minLength="17"
validate:testType="minLength"/>
<androidx.preference.PreferenceScreen
android:key="@string/ns_sync_options"
android:title="@string/ns_sync_options">
<SwitchPreference
android:defaultValue="true"
android:key="@string/key_ns_upload"
android:summary="@string/ns_upload_summary"
android:title="@string/ns_upload" />
<SwitchPreference
android:defaultValue="false"
android:key="@string/key_do_ns_upload"
android:title="@string/do_ns_upload_title" />
<SwitchPreference
android:defaultValue="false"
android:key="@string/key_ns_receive_cgm"
android:summary="@string/ns_receive_cgm_summary"
android:title="@string/ns_receive_cgm" />
<SwitchPreference
android:defaultValue="true"
android:key="@string/key_ns_receive_profile_store"
android:summary="@string/ns_receive_profile_store_summary"
android:title="@string/ns_receive_profile_store" />
<SwitchPreference
android:defaultValue="false"
android:key="@string/key_ns_receive_temp_target"
android:summary="@string/ns_receive_temp_target_summary"
android:title="@string/ns_receive_temp_target" />
<SwitchPreference
android:defaultValue="false"
android:key="@string/key_ns_receive_profile_switch"
android:summary="@string/ns_receive_profile_switch_summary"
android:title="@string/ns_receive_profile_switch" />
<SwitchPreference
android:defaultValue="false"
android:key="@string/key_ns_receive_insulin"
android:summary="@string/ns_receive_insulin_summary"
android:title="@string/ns_receive_insulin" />
<SwitchPreference
android:defaultValue="false"
android:key="@string/key_ns_receive_carbs"
android:summary="@string/ns_receive_carbs_summary"
android:title="@string/ns_receive_carbs" />
<SwitchPreference
android:defaultValue="false"
android:key="@string/key_ns_receive_therapy_events"
android:summary="@string/ns_receive_therapy_events_summary"
android:title="@string/ns_receive_therapy_events" />
<SwitchPreference
android:defaultValue="false"
android:key="@string/key_ns_receive_offline_event"
android:summary="@string/ns_receive_offline_event_summary"
android:title="@string/ns_receive_offline_event" />
<SwitchPreference
android:defaultValue="false"
android:key="@string/key_ns_receive_tbr_eb"
android:summary="@string/ns_receive_tbr_eb_summary"
android:title="@string/ns_receive_tbr_eb" />
</androidx.preference.PreferenceScreen>>
<androidx.preference.PreferenceScreen
android:key="@string/ns_alarm_options"
android:title="@string/ns_alarm_options">
<SwitchPreference
android:key="@string/key_ns_alarms"
android:title="@string/ns_alarms" />
<SwitchPreference
android:key="@string/key_ns_announcements"
android:title="@string/ns_announcements" />
<info.nightscout.core.validators.ValidatingEditTextPreference
android:defaultValue="16"
android:digits="0123456789"
android:inputType="number"
android:key="@string/key_ns_alarm_stale_data_value"
android:maxLines="20"
android:selectAllOnFocus="true"
android:singleLine="true"
android:title="@string/ns_alarm_stale_data_value_label"
validate:maxNumber="120"
validate:minNumber="15"
validate:testType="numericRange" />
<info.nightscout.core.validators.ValidatingEditTextPreference
android:defaultValue="31"
android:digits="0123456789"
android:inputType="number"
android:key="@string/key_ns_alarm_urgent_stale_data_value"
android:maxLines="20"
android:selectAllOnFocus="true"
android:singleLine="true"
android:title="@string/ns_alarm_urgent_stale_data_value_label"
validate:maxNumber="180"
validate:minNumber="30"
validate:testType="numericRange" />
</androidx.preference.PreferenceScreen>
<androidx.preference.PreferenceScreen
android:key="@string/connection_settings_title"
android:title="@string/connection_settings_title">
<SwitchPreference
android:defaultValue="true"
android:key="@string/key_ns_cellular"
android:title="@string/ns_cellular" />
<SwitchPreference
android:defaultValue="true"
android:dependency="@string/key_ns_cellular"
android:key="@string/key_ns_allow_roaming"
android:title="@string/ns_allow_roaming" />
<SwitchPreference
android:defaultValue="true"
android:key="@string/key_ns_wifi"
android:title="@string/ns_wifi" />
<EditTextPreference
android:dialogMessage="@string/ns_wifi_allowed_ssids"
android:dependency="@string/key_ns_wifi"
android:inputType="text"
android:key="@string/key_ns_wifi_ssids"
android:title="@string/ns_wifi_ssids" />
<SwitchPreference
android:defaultValue="true"
android:key="@string/key_ns_battery"
android:title="@string/ns_battery" />
<SwitchPreference
android:defaultValue="true"
android:key="@string/key_ns_charging"
android:title="@string/ns_charging" />
</androidx.preference.PreferenceScreen>
<androidx.preference.PreferenceScreen
android:key="nsclient_advanced"
android:title="@string/advancedsettings_title">
<SwitchPreference
android:defaultValue="true"
android:key="@string/key_ns_log_app_started_event"
android:title="@string/ns_log_app_started_event"
android:summary="@string/ns_log_app_started_event"
/>
<SwitchPreference
android:defaultValue="true"
android:key="@string/key_ns_create_announcements_from_errors"
android:summary="@string/ns_create_announcements_from_errors_summary"
android:title="@string/ns_create_announcements_from_errors_title" />
<SwitchPreference
android:defaultValue="false"
android:key="@string/key_ns_create_announcements_from_carbs_req"
android:summary="@string/ns_create_announcements_from_carbs_req_summary"
android:title="@string/ns_create_announcements_from_carbs_req_title" />
<SwitchPreference
android:defaultValue="false"
android:key="@string/key_nsclient_localbroadcasts"
android:summary="@string/ns_local_broadcasts"
android:title="@string/ns_local_broadcasts_title" />
<SwitchPreference
android:defaultValue="false"
android:key="@string/key_ns_sync_slow"
android:title="@string/ns_sync_slow" />
</androidx.preference.PreferenceScreen>
</PreferenceCategory>
</androidx.preference.PreferenceScreen>

View file

@ -251,14 +251,14 @@ class ComboV2Plugin @Inject constructor (
init { init {
ComboCtlLogger.backend = AAPSComboCtlLogger(aapsLogger) ComboCtlLogger.backend = AAPSComboCtlLogger(aapsLogger)
updateComboCtlLogLevel()
_pumpDescription.fillFor(PumpType.ACCU_CHEK_COMBO) _pumpDescription.fillFor(PumpType.ACCU_CHEK_COMBO)
} }
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
updateComboCtlLogLevel()
// Check if there is a pump state in the internal SP. If not, try to // Check if there is a pump state in the internal SP. If not, try to
// copy a pump state from the AAPS main SP. It is possible for example // copy a pump state from the AAPS main SP. It is possible for example
// that AAPS was reinstalled, and the previous settings were imported. // that AAPS was reinstalled, and the previous settings were imported.

View file

@ -7,6 +7,7 @@ import info.nightscout.rx.events.EventDanaRSyncStatus
import info.nightscout.rx.logging.LTag import info.nightscout.rx.logging.LTag
import info.nightscout.shared.utils.T import info.nightscout.shared.utils.T
@Suppress("SpellCheckingInspection")
open class MsgHistoryAll( open class MsgHistoryAll(
injector: HasAndroidInjector injector: HasAndroidInjector
) : MessageBase(injector) { ) : MessageBase(injector) {
@ -17,6 +18,7 @@ open class MsgHistoryAll(
} }
override fun handleMessage(bytes: ByteArray) { override fun handleMessage(bytes: ByteArray) {
try {
val recordCode = intFromBuff(bytes, 0, 1).toByte() val recordCode = intFromBuff(bytes, 0, 1).toByte()
val date = dateFromBuff(bytes, 1) // 3 bytes val date = dateFromBuff(bytes, 1) // 3 bytes
val dailyBasal = intFromBuff(bytes, 4, 2) * 0.01 val dailyBasal = intFromBuff(bytes, 4, 2) * 0.01
@ -148,5 +150,11 @@ open class MsgHistoryAll(
if (recordCode == RecordTypes.RECORD_TYPE_DAILY) if (recordCode == RecordTypes.RECORD_TYPE_DAILY)
pumpSync.createOrUpdateTotalDailyDose(date, dailyBolus, dailyBasal, dailyBolus + dailyBasal, date, activePlugin.activePump.model(), danaPump.serialNumber) pumpSync.createOrUpdateTotalDailyDose(date, dailyBolus, dailyBasal, dailyBolus + dailyBasal, date, activePlugin.activePump.model(), danaPump.serialNumber)
rxBus.send(EventDanaRSyncStatus(dateUtil.dateAndTimeString(danaHistoryRecord.timestamp) + " " + messageType)) rxBus.send(EventDanaRSyncStatus(dateUtil.dateAndTimeString(danaHistoryRecord.timestamp) + " " + messageType))
} catch (e: Exception) {
// DanaR id sometimes producing invalid date in history
// ignore these records
aapsLogger.error(e.stackTraceToString())
return
}
} }
} }