code tweaking, upload profile

This commit is contained in:
Milos Kozak 2019-06-06 22:15:57 +02:00
parent 21a49f731c
commit ba0b7ec83d
13 changed files with 361 additions and 64 deletions

View file

@ -400,6 +400,19 @@ public class Profile {
return getValuesList(isf_v, null, new DecimalFormat("0.0"), getUnits() + MainApp.gs(R.string.profile_per_unit));
}
public ProfileValue[] getIsfs() {
if (isf_v == null)
isf_v = convertToSparseArray(ic);
ProfileValue[] ret = new ProfileValue[isf_v.size()];
for (Integer index = 0; index < isf_v.size(); index++) {
Integer tas = (int) isf_v.keyAt(index);
double value = isf_v.valueAt(index);
ret[index] = new ProfileValue(tas, value);
}
return ret;
}
public double getIc() {
return getIcTimeFromMidnight(secondsFromMidnight());
}
@ -420,6 +433,19 @@ public class Profile {
return getValuesList(ic_v, null, new DecimalFormat("0.0"), MainApp.gs(R.string.profile_carbs_per_unit));
}
public ProfileValue[] getIcs() {
if (ic_v == null)
ic_v = convertToSparseArray(ic);
ProfileValue[] ret = new ProfileValue[ic_v.size()];
for (Integer index = 0; index < ic_v.size(); index++) {
Integer tas = (int) ic_v.keyAt(index);
double value = ic_v.valueAt(index);
ret[index] = new ProfileValue(tas, value);
}
return ret;
}
public double getBasal() {
return getBasalTimeFromMidnight(secondsFromMidnight());
}
@ -441,8 +467,8 @@ public class Profile {
return getValuesList(basal_v, null, new DecimalFormat("0.00"), MainApp.gs(R.string.profile_ins_units_per_hout));
}
public class BasalValue {
public BasalValue(int timeAsSeconds, double value) {
public class ProfileValue {
public ProfileValue(int timeAsSeconds, double value) {
this.timeAsSeconds = timeAsSeconds;
this.value = value;
}
@ -451,15 +477,15 @@ public class Profile {
public double value;
}
public synchronized BasalValue[] getBasalValues() {
public synchronized ProfileValue[] getBasalValues() {
if (basal_v == null)
basal_v = convertToSparseArray(basal);
BasalValue[] ret = new BasalValue[basal_v.size()];
ProfileValue[] ret = new ProfileValue[basal_v.size()];
for (Integer index = 0; index < basal_v.size(); index++) {
Integer tas = (int) basal_v.keyAt(index);
double value = basal_v.valueAt(index);
ret[index] = new BasalValue(tas, value);
ret[index] = new ProfileValue(tas, value);
}
return ret;
}
@ -500,6 +526,34 @@ public class Profile {
return getValueToTime(targetHigh_v, timeAsSeconds);
}
public class TargetValue {
public TargetValue(int timeAsSeconds, double low, double high) {
this.timeAsSeconds = timeAsSeconds;
this.low = low;
this.high = high;
}
public int timeAsSeconds;
public double low;
public double high;
}
public TargetValue[] getTargets() {
if (targetLow_v == null)
targetLow_v = convertToSparseArray(targetLow);
if (targetHigh_v == null)
targetHigh_v = convertToSparseArray(targetHigh);
TargetValue[] ret = new TargetValue[targetLow_v.size()];
for (Integer index = 0; index < targetLow_v.size(); index++) {
Integer tas = (int) targetLow_v.keyAt(index);
double low = targetLow_v.valueAt(index);
double high = targetHigh_v.valueAt(index);
ret[index] = new TargetValue(tas, low, high);
}
return ret;
}
public String getTargetList() {
if (targetLow_v == null)
targetLow_v = convertToSparseArray(targetLow);

View file

@ -1557,6 +1557,24 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
return new ArrayList<>();
}
public List<ProfileSwitch> getProfileSwitchEventsFromTime(long from, long to, boolean ascending) {
try {
Dao<ProfileSwitch, Long> daoProfileSwitch = getDaoProfileSwitch();
List<ProfileSwitch> profileSwitches;
QueryBuilder<ProfileSwitch, Long> queryBuilder = daoProfileSwitch.queryBuilder();
queryBuilder.orderBy("date", ascending);
queryBuilder.limit(100L);
Where where = queryBuilder.where();
where.between("date", from, to);
PreparedQuery<ProfileSwitch> preparedQuery = queryBuilder.prepare();
profileSwitches = daoProfileSwitch.query(preparedQuery);
return profileSwitches;
} catch (SQLException e) {
log.error("Unhandled exception", e);
}
return new ArrayList<>();
}
public boolean createOrUpdate(ProfileSwitch profileSwitch) {
try {
ProfileSwitch old;

View file

@ -1,10 +1,14 @@
package info.nightscout.androidaps.plugins.general.tidepool;
import android.app.Activity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import com.squareup.otto.Subscribe;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
@ -12,9 +16,12 @@ import info.nightscout.androidaps.plugins.common.SubscriberFragment;
import info.nightscout.androidaps.plugins.general.tidepool.comm.TidepoolUploader;
import info.nightscout.androidaps.plugins.general.tidepool.events.EventTidepoolDoUpload;
import info.nightscout.androidaps.plugins.general.tidepool.events.EventTidepoolResetData;
import info.nightscout.androidaps.plugins.general.tidepool.events.EventTidepoolUpdateGUI;
import info.nightscout.androidaps.utils.SP;
public class TidepoolJavaFragment extends SubscriberFragment {
private TextView logTextView;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
@ -34,11 +41,24 @@ public class TidepoolJavaFragment extends SubscriberFragment {
resetStart.setOnClickListener(v4 -> {
SP.putLong(R.string.key_tidepool_last_end, 0);
});
logTextView = view.findViewById(R.id.tidepool_log);
return view;
}
@Subscribe
public void onStatusEvent(final EventTidepoolUpdateGUI ignored) {
updateGUI();
}
@Override
protected void updateGUI() {
Activity activity = getActivity();
if (activity != null)
activity.runOnUiThread(() -> {
TidepoolPlugin.INSTANCE.updateLog();
logTextView.setText(TidepoolPlugin.INSTANCE.getTextLog());
});
}
}
}

View file

@ -2,6 +2,7 @@ package info.nightscout.androidaps.plugins.general.tidepool
import android.text.Html
import com.squareup.otto.Subscribe
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R
import info.nightscout.androidaps.events.EventNetworkChange
@ -10,15 +11,16 @@ import info.nightscout.androidaps.interfaces.PluginBase
import info.nightscout.androidaps.interfaces.PluginDescription
import info.nightscout.androidaps.interfaces.PluginType
import info.nightscout.androidaps.logging.L
import info.nightscout.androidaps.plugins.general.tidepool.comm.Session
import info.nightscout.androidaps.plugins.general.tidepool.comm.TidepoolUploader
import info.nightscout.androidaps.plugins.general.tidepool.events.EventTidepoolDoUpload
import info.nightscout.androidaps.plugins.general.tidepool.events.EventTidepoolResetData
import info.nightscout.androidaps.plugins.general.tidepool.events.EventTidepoolStatus
import info.nightscout.androidaps.plugins.general.tidepool.events.EventTidepoolUpdateGUI
import info.nightscout.androidaps.plugins.general.tidepool.utils.RateLimit
import info.nightscout.androidaps.receivers.ChargingStateReceiver
import info.nightscout.androidaps.utils.SP
import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.ToastUtils
import org.slf4j.LoggerFactory
import java.util.*
@ -33,15 +35,12 @@ object TidepoolPlugin : PluginBase(PluginDescription()
private val log = LoggerFactory.getLogger(L.TIDEPOOL)
private var wifiConnected = false
var session: Session? = null
private val listLog = ArrayList<EventTidepoolStatus>()
internal var textLog = Html.fromHtml("")
var textLog = Html.fromHtml("")
var status = ""
var paused: Boolean = false
internal var autoscroll: Boolean = false
var status = ""
override fun onStart() {
MainApp.bus().register(this)
super.onStart()
@ -53,9 +52,10 @@ object TidepoolPlugin : PluginBase(PluginDescription()
}
fun doUpload() {
if (session == null)
session = TidepoolUploader.doLogin()
else TidepoolUploader.doUpload(session!!)
if (TidepoolUploader.connectionStatus == TidepoolUploader.ConnectionStatus.DISCONNECTED)
TidepoolUploader.doLogin()
else
TidepoolUploader.doUpload()
}
@Suppress("UNUSED_PARAMETER")
@ -77,13 +77,13 @@ object TidepoolPlugin : PluginBase(PluginDescription()
@Suppress("UNUSED_PARAMETER")
@Subscribe
fun onEventTidepoolResetData(ev: EventTidepoolResetData) {
if (session == null)
session = TidepoolUploader.doLogin()
if (session != null) {
TidepoolUploader.deleteDataSet(session!!)
SP.putLong(R.string.key_tidepool_last_end, 0)
TidepoolUploader.doLogin()
if (TidepoolUploader.connectionStatus != TidepoolUploader.ConnectionStatus.CONNECTED) {
log.debug("Not connected for deleteDataset")
return
}
TidepoolUploader.deleteDataSet()
SP.putLong(R.string.key_tidepool_last_end, 0)
TidepoolUploader.doLogin()
}
@Subscribe
@ -95,4 +95,36 @@ object TidepoolPlugin : PluginBase(PluginDescription()
return isEnabled(PluginType.GENERAL) && SP.getBoolean(R.string.key_cloud_storage_tidepool_enable, false)
}
@Subscribe
fun onStatusEvent(ev: EventTidepoolStatus) {
addToLog(ev)
}
@Synchronized
private fun addToLog(ev: EventTidepoolStatus) {
synchronized(listLog) {
listLog.add(ev)
// remove the first line if log is too large
if (listLog.size >= Constants.MAX_LOG_LINES) {
listLog.removeAt(0)
}
}
MainApp.bus().post(EventTidepoolUpdateGUI())
}
@Synchronized
fun updateLog() {
try {
val newTextLog = StringBuilder()
synchronized(listLog) {
for (log in listLog) {
newTextLog.append(log.toPreparedHtml())
}
}
textLog = Html.fromHtml(newTextLog.toString())
} catch (e: OutOfMemoryError) {
ToastUtils.showToastInUiThread(MainApp.instance().applicationContext, "Out of memory!\nStop using this phone !!!", R.raw.error)
}
}
}

View file

@ -31,6 +31,14 @@ object TidepoolUploader {
private var retrofit: Retrofit? = null
var session: Session? = null
enum class ConnectionStatus {
DISCONNECTED, CONNECTING, CONNECTED, FAILED
}
var connectionStatus: ConnectionStatus = TidepoolUploader.ConnectionStatus.DISCONNECTED
fun getRetrofitInstance(): Retrofit? {
if (retrofit == null) {
@ -59,25 +67,38 @@ object TidepoolUploader {
}
@Synchronized
fun doLogin(): Session? {
fun doLogin() {
if (!SP.getBoolean(R.string.key_cloud_storage_tidepool_enable, false)) {
log.debug("Cannot login as disabled by preference")
return null
if (L.isEnabled(L.TIDEPOOL))
log.debug("Cannot login as disabled by preference")
return
}
if (connectionStatus == TidepoolUploader.ConnectionStatus.CONNECTED || connectionStatus == TidepoolUploader.ConnectionStatus.CONNECTING) {
if (L.isEnabled(L.TIDEPOOL))
log.debug("Already connected")
return
}
// TODO failure backoff
extendWakeLock(30000)
val session = Session(AuthRequestMessage.getAuthRequestHeader(), SESSION_TOKEN_HEADER)
if (session.authHeader != null) {
val call = session.service?.getLogin(session.authHeader!!)
session = Session(AuthRequestMessage.getAuthRequestHeader(), SESSION_TOKEN_HEADER)
if (session?.authHeader != null) {
connectionStatus = TidepoolUploader.ConnectionStatus.CONNECTING
status("Connecting")
val call = session!!.service?.getLogin(session?.authHeader!!)
call?.enqueue(TidepoolCallback<AuthReplyMessage>(session, "Login", { startSession(session) }, { loginFailed() }))
return session
call?.enqueue(TidepoolCallback<AuthReplyMessage>(session!!, "Login", {
startSession(session!!)
}, {
connectionStatus = TidepoolUploader.ConnectionStatus.FAILED;
loginFailed()
}))
return
} else {
if (L.isEnabled(L.TIDEPOOL)) log.debug("Cannot do login as user credentials have not been set correctly")
connectionStatus = TidepoolUploader.ConnectionStatus.FAILED;
status("Invalid credentials")
releaseWakeLock()
return null
return
}
}
@ -114,48 +135,70 @@ object TidepoolUploader {
datasetCall.enqueue(TidepoolCallback<List<DatasetReplyMessage>>(session, "Get Open Datasets", {
if (session.datasetReply == null) {
status("New data set")
status("Creating new dataset")
val call = session.service.openDataSet(session.token!!, session.authReply!!.userid!!, OpenDatasetRequestMessage().getBody())
call.enqueue(TidepoolCallback<DatasetReplyMessage>(session, "Open New Dataset", { doUpload(session) }, { releaseWakeLock() }))
call.enqueue(TidepoolCallback<DatasetReplyMessage>(session, "Open New Dataset", {
connectionStatus = TidepoolUploader.ConnectionStatus.CONNECTED;
status("New dataset OK")
releaseWakeLock()
}, {
status("New dataset FAILED")
connectionStatus = TidepoolUploader.ConnectionStatus.FAILED;
releaseWakeLock()
}))
} else {
if (L.isEnabled(L.TIDEPOOL)) log.debug("Existing Dataset: " + session.datasetReply!!.getUploadId())
if (L.isEnabled(L.TIDEPOOL))
log.debug("Existing Dataset: " + session.datasetReply!!.getUploadId())
// TODO: Wouldn't need to do this if we could block on the above `call.enqueue`.
// ie, do the openDataSet conditionally, and then do `doUpload` either way.
status("Appending")
doUpload(session)
connectionStatus = TidepoolUploader.ConnectionStatus.CONNECTED;
status("Appending to existing dataset")
releaseWakeLock()
}
}, { releaseWakeLock() }))
}, {
connectionStatus = TidepoolUploader.ConnectionStatus.FAILED;
status("Open dataset FAILED")
releaseWakeLock()
}))
} else {
log.error("Got login response but cannot determine userid - cannot proceed")
connectionStatus = TidepoolUploader.ConnectionStatus.FAILED;
status("Error userid")
releaseWakeLock()
}
}
fun doUpload(session: Session) {
fun doUpload() {
if (!TidepoolPlugin.enabled()) {
if (L.isEnabled(L.TIDEPOOL))
log.debug("Cannot upload - preference disabled")
return
}
if (session == null) {
log.error("Session is null, cannot proceed")
return
}
extendWakeLock(60000)
session.iterations++
session!!.iterations++
val chunk = UploadChunk.getNext(session)
if (chunk == null) {
log.error("Upload chunk is null, cannot proceed")
releaseWakeLock()
} else if (chunk.length == 2) {
if (L.isEnabled(L.TIDEPOOL)) log.debug("Empty data set - marking as succeeded")
doCompletedAndReleaseWakelock()
if (L.isEnabled(L.TIDEPOOL)) log.debug("Empty dataset - marking as succeeded")
status("No data to upload")
releaseWakeLock()
} else {
val body = RequestBody.create(MediaType.parse("application/json"), chunk)
val call = session.service!!.doUpload(session.token!!, session.datasetReply!!.getUploadId()!!, body)
status("Uploading")
call.enqueue(TidepoolCallback<UploadReplyMessage>(session, "Data Upload", {
UploadChunk.setLastEnd(session.end)
doCompletedAndReleaseWakelock()
val call = session!!.service!!.doUpload(session!!.token!!, session!!.datasetReply!!.getUploadId()!!, body)
call.enqueue(TidepoolCallback<UploadReplyMessage>(session!!, "Data Upload", {
UploadChunk.setLastEnd(session!!.end)
status("Upload completed OK")
releaseWakeLock()
}, {
status("Upload FAILED")
releaseWakeLock()
}))
}
@ -168,15 +211,20 @@ object TidepoolUploader {
MainApp.bus().post(EventTidepoolStatus(status))
}
private fun doCompletedAndReleaseWakelock() {
status("Completed OK")
releaseWakeLock()
}
fun deleteDataSet(session: Session) {
if (session.datasetReply?.id != null) {
val call = session.service?.deleteDataSet(session.token!!, session.datasetReply!!.id!!)
call?.enqueue(TidepoolCallback(session, "Delete Dataset", {}, {}))
fun deleteDataSet() {
if (session?.datasetReply?.id != null) {
extendWakeLock(60000)
val call = session!!.service?.deleteDataSet(session!!.token!!, session!!.datasetReply!!.id!!)
call?.enqueue(TidepoolCallback(session!!, "Delete Dataset", {
connectionStatus = TidepoolUploader.ConnectionStatus.DISCONNECTED
status("Dataset removed OK")
releaseWakeLock()
}, {
connectionStatus = TidepoolUploader.ConnectionStatus.DISCONNECTED
status("Dataset remove FAILED")
releaseWakeLock()
}))
} else {
log.error("Got login response but cannot determine dataseId - cannot proceed")
}

View file

@ -18,7 +18,10 @@ object UploadChunk {
private val log = LoggerFactory.getLogger(L.TIDEPOOL)
fun getNext(session: Session): String? {
fun getNext(session: Session?): String? {
if (session == null)
return null
session.start = getLastEnd()
session.end = Math.min(session.start + MAX_UPLOAD_SIZE, DateUtil.now())
@ -48,6 +51,7 @@ object UploadChunk {
records.addAll(getBloodTests(start, end))
records.addAll(getBasals(start, end))
records.addAll(getBgReadings(start, end))
records.addAll(getProfiles(start, end))
return GsonInstance.defaultGsonInstance().toJson(records)
}
@ -116,4 +120,16 @@ object UploadChunk {
return BasalElement.fromTemporaryBasals(tbrs)
}
internal fun getProfiles(start: Long, end: Long): List<ProfileElement> {
val pss = MainApp.getDbHelper().getProfileSwitchEventsFromTime(start, end, true)
if (L.isEnabled(L.TIDEPOOL))
log.debug("${pss.size} ProfileSwitches selected for upload")
val results = LinkedList<ProfileElement>()
for (ps in pss) {
val pe = ProfileElement(ps)
results.add(pe)
}
return results
}
}

View file

@ -19,6 +19,7 @@ class BloodGlucoseElement(careportalEvent: CareportalEvent)
var value: Int = 0
init {
type = "cbg"
subType = "manual" // TODO
var json = if (careportalEvent.json != null) JSONObject(careportalEvent.json) else JSONObject()
value = Profile.toMgdl(JsonHelper.safeGetDouble(json, "glucose"), JsonHelper.safeGetString(json, "units", Constants.MGDL)).toInt()

View file

@ -0,0 +1,88 @@
package info.nightscout.androidaps.plugins.general.tidepool.elements
import com.google.gson.annotations.Expose
import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.db.ProfileSwitch
import java.util.*
import kotlin.collections.ArrayList
class ProfileElement(ps: ProfileSwitch)
: BaseElement(ps.date, UUID.nameUUIDFromBytes(("AAPS-profile" + ps.date).toByteArray()).toString()) {
@Expose
internal var activeSchedule = "Normal"
@Expose
internal var basalSchedules: BasalProfile = BasalProfile()
@Expose
internal var units: Units = Units()
@Expose
internal var bgTargets: TargetProfile = TargetProfile()
@Expose
internal var carbRatios: IcProfile = IcProfile()
@Expose
internal var insulinSensitivities: IsfProfile = IsfProfile()
init {
type = "pumpSettings";
val profile: Profile = ps.getProfileObject()!!
for (br in profile.basalValues)
basalSchedules.Normal.add(BasalRate(br.timeAsSeconds * 1000, br.value))
for (target in profile.targets)
bgTargets.Normal.add(Target(target.timeAsSeconds * 1000, Profile.toMgdl(target.low, profile.units), Profile.toMgdl(target.high, profile.units)))
for (ic in profile.ics)
carbRatios.Normal.add(Ratio(ic.timeAsSeconds * 1000, ic.value))
for (isf in profile.isfs)
insulinSensitivities.Normal.add(Ratio(isf.timeAsSeconds * 1000, Profile.toMgdl(isf.value, profile.units)))
}
inner class BasalProfile internal constructor(
@field:Expose
internal var Normal: ArrayList<BasalRate> = ArrayList() // must be the same var name as activeSchedule
)
inner class BasalRate internal constructor(
@field:Expose
internal var start: Int,
@field:Expose
internal var rate: Double
)
inner class Units internal constructor(
@field:Expose
internal var carb: String = "grams",
@field:Expose
internal var bg: String = "mg/dL"
)
inner class TargetProfile internal constructor(
@field:Expose
internal var Normal: ArrayList<Target> = ArrayList() // must be the same var name as activeSchedule
)
inner class Target internal constructor(
@field:Expose
internal var start: Int,
@field:Expose
internal var low: Double,
@field:Expose
internal var high: Double
)
inner class IcProfile internal constructor(
@field:Expose
internal var Normal: ArrayList<Ratio> = ArrayList() // must be the same var name as activeSchedule
)
inner class IsfProfile internal constructor(
@field:Expose
internal var Normal: ArrayList<Ratio> = ArrayList() // must be the same var name as activeSchedule
)
inner class Ratio internal constructor(
@field:Expose
internal var start: Int,
@field:Expose
internal var amount: Double
)
}

View file

@ -1,6 +1,22 @@
package info.nightscout.androidaps.plugins.general.tidepool.events
import info.nightscout.androidaps.events.Event
import info.nightscout.androidaps.utils.DateUtil
import java.text.SimpleDateFormat
class EventTidepoolStatus (val status: String) : Event() {
var date : Long = DateUtil.now()
internal var timeFormat = SimpleDateFormat("HH:mm:ss")
fun toPreparedHtml(): StringBuilder {
val stringBuilder = StringBuilder()
stringBuilder.append(timeFormat.format(date))
stringBuilder.append(" <b>")
stringBuilder.append(status)
stringBuilder.append("</b> ")
stringBuilder.append("<br>")
return stringBuilder
}
}

View file

@ -0,0 +1,6 @@
package info.nightscout.androidaps.plugins.general.tidepool.events;
import info.nightscout.androidaps.events.Event;
public class EventTidepoolUpdateGUI extends Event {
}

View file

@ -29,7 +29,7 @@ class OpenDatasetRequestMessage : BaseMessage() {
@Expose
var deviceManufacturers = arrayOf(((ConfigBuilderPlugin.getPlugin().activeBgSource ?: SourceNSClientPlugin.getPlugin()) as PluginBase).name)
@Expose
var deviceModel = arrayOf(((ConfigBuilderPlugin.getPlugin().activeBgSource ?: SourceNSClientPlugin.getPlugin()) as PluginBase).name)
var deviceModel = ((ConfigBuilderPlugin.getPlugin().activeBgSource ?: SourceNSClientPlugin.getPlugin()) as PluginBase).name
@Expose
var deviceTags = arrayOf("bgm", "cgm", "insulin-pump")
@Expose
@ -45,7 +45,7 @@ class OpenDatasetRequestMessage : BaseMessage() {
@Expose
val name = BuildConfig.APPLICATION_ID
@Expose
val version = "0.1.0" // TODO: const it
val version = BuildConfig.VERSION_NAME
}
inner class Deduplicator {

View file

@ -417,8 +417,8 @@ public class LocalInsightPlugin extends PluginBase implements PumpInterface, Con
MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED));
List<BasalProfileBlock> profileBlocks = new ArrayList<>();
for (int i = 0; i < profile.getBasalValues().length; i++) {
Profile.BasalValue basalValue = profile.getBasalValues()[i];
Profile.BasalValue nextValue = null;
Profile.ProfileValue basalValue = profile.getBasalValues()[i];
Profile.ProfileValue nextValue = null;
if (profile.getBasalValues().length > i + 1)
nextValue = profile.getBasalValues()[i + 1];
BasalProfileBlock profileBlock = new BasalProfileBlock();
@ -471,8 +471,8 @@ public class LocalInsightPlugin extends PluginBase implements PumpInterface, Con
if (activeBasalProfile != BasalProfile.PROFILE_1) return false;
for (int i = 0; i < profileBlocks.size(); i++) {
BasalProfileBlock profileBlock = profileBlocks.get(i);
Profile.BasalValue basalValue = profile.getBasalValues()[i];
Profile.BasalValue nextValue = null;
Profile.ProfileValue basalValue = profile.getBasalValues()[i];
Profile.ProfileValue nextValue = null;
if (profile.getBasalValues().length > i + 1)
nextValue = profile.getBasalValues()[i + 1];
if (profileBlock.getDuration() * 60 != (nextValue != null ? nextValue.timeAsSeconds : 24 * 60 * 60) - basalValue.timeAsSeconds)

View file

@ -12,8 +12,6 @@ import org.slf4j.LoggerFactory;
import java.util.LinkedList;
import javax.annotation.Nullable;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.DetailedBolusInfo;
@ -388,10 +386,10 @@ public class CommandQueue {
}
// Compare with pump limits
Profile.BasalValue[] basalValues = profile.getBasalValues();
Profile.ProfileValue[] basalValues = profile.getBasalValues();
PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump();
for (Profile.BasalValue basalValue : basalValues) {
for (Profile.ProfileValue basalValue : basalValues) {
if (basalValue.value < pump.getPumpDescription().basalMinimumRate) {
Notification notification = new Notification(Notification.BASAL_VALUE_BELOW_MINIMUM, MainApp.gs(R.string.basalvaluebelowminimum), Notification.URGENT);
MainApp.bus().post(new EventNewNotification(notification));