code tweaking, upload profile
This commit is contained in:
parent
21a49f731c
commit
ba0b7ec83d
13 changed files with 361 additions and 64 deletions
|
@ -400,6 +400,19 @@ public class Profile {
|
||||||
return getValuesList(isf_v, null, new DecimalFormat("0.0"), getUnits() + MainApp.gs(R.string.profile_per_unit));
|
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() {
|
public double getIc() {
|
||||||
return getIcTimeFromMidnight(secondsFromMidnight());
|
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));
|
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() {
|
public double getBasal() {
|
||||||
return getBasalTimeFromMidnight(secondsFromMidnight());
|
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));
|
return getValuesList(basal_v, null, new DecimalFormat("0.00"), MainApp.gs(R.string.profile_ins_units_per_hout));
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BasalValue {
|
public class ProfileValue {
|
||||||
public BasalValue(int timeAsSeconds, double value) {
|
public ProfileValue(int timeAsSeconds, double value) {
|
||||||
this.timeAsSeconds = timeAsSeconds;
|
this.timeAsSeconds = timeAsSeconds;
|
||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
@ -451,15 +477,15 @@ public class Profile {
|
||||||
public double value;
|
public double value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized BasalValue[] getBasalValues() {
|
public synchronized ProfileValue[] getBasalValues() {
|
||||||
if (basal_v == null)
|
if (basal_v == null)
|
||||||
basal_v = convertToSparseArray(basal);
|
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++) {
|
for (Integer index = 0; index < basal_v.size(); index++) {
|
||||||
Integer tas = (int) basal_v.keyAt(index);
|
Integer tas = (int) basal_v.keyAt(index);
|
||||||
double value = basal_v.valueAt(index);
|
double value = basal_v.valueAt(index);
|
||||||
ret[index] = new BasalValue(tas, value);
|
ret[index] = new ProfileValue(tas, value);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -500,6 +526,34 @@ public class Profile {
|
||||||
return getValueToTime(targetHigh_v, timeAsSeconds);
|
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() {
|
public String getTargetList() {
|
||||||
if (targetLow_v == null)
|
if (targetLow_v == null)
|
||||||
targetLow_v = convertToSparseArray(targetLow);
|
targetLow_v = convertToSparseArray(targetLow);
|
||||||
|
|
|
@ -1557,6 +1557,24 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
return new ArrayList<>();
|
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) {
|
public boolean createOrUpdate(ProfileSwitch profileSwitch) {
|
||||||
try {
|
try {
|
||||||
ProfileSwitch old;
|
ProfileSwitch old;
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
package info.nightscout.androidaps.plugins.general.tidepool;
|
package info.nightscout.androidaps.plugins.general.tidepool;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.squareup.otto.Subscribe;
|
||||||
|
|
||||||
import info.nightscout.androidaps.MainApp;
|
import info.nightscout.androidaps.MainApp;
|
||||||
import info.nightscout.androidaps.R;
|
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.comm.TidepoolUploader;
|
||||||
import info.nightscout.androidaps.plugins.general.tidepool.events.EventTidepoolDoUpload;
|
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.EventTidepoolResetData;
|
||||||
|
import info.nightscout.androidaps.plugins.general.tidepool.events.EventTidepoolUpdateGUI;
|
||||||
import info.nightscout.androidaps.utils.SP;
|
import info.nightscout.androidaps.utils.SP;
|
||||||
|
|
||||||
public class TidepoolJavaFragment extends SubscriberFragment {
|
public class TidepoolJavaFragment extends SubscriberFragment {
|
||||||
|
private TextView logTextView;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
|
@ -34,11 +41,24 @@ public class TidepoolJavaFragment extends SubscriberFragment {
|
||||||
resetStart.setOnClickListener(v4 -> {
|
resetStart.setOnClickListener(v4 -> {
|
||||||
SP.putLong(R.string.key_tidepool_last_end, 0);
|
SP.putLong(R.string.key_tidepool_last_end, 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
logTextView = view.findViewById(R.id.tidepool_log);
|
||||||
|
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onStatusEvent(final EventTidepoolUpdateGUI ignored) {
|
||||||
|
updateGUI();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void updateGUI() {
|
protected void updateGUI() {
|
||||||
|
Activity activity = getActivity();
|
||||||
|
if (activity != null)
|
||||||
|
activity.runOnUiThread(() -> {
|
||||||
|
TidepoolPlugin.INSTANCE.updateLog();
|
||||||
|
logTextView.setText(TidepoolPlugin.INSTANCE.getTextLog());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -2,6 +2,7 @@ package info.nightscout.androidaps.plugins.general.tidepool
|
||||||
|
|
||||||
import android.text.Html
|
import android.text.Html
|
||||||
import com.squareup.otto.Subscribe
|
import com.squareup.otto.Subscribe
|
||||||
|
import info.nightscout.androidaps.Constants
|
||||||
import info.nightscout.androidaps.MainApp
|
import info.nightscout.androidaps.MainApp
|
||||||
import info.nightscout.androidaps.R
|
import info.nightscout.androidaps.R
|
||||||
import info.nightscout.androidaps.events.EventNetworkChange
|
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.PluginDescription
|
||||||
import info.nightscout.androidaps.interfaces.PluginType
|
import info.nightscout.androidaps.interfaces.PluginType
|
||||||
import info.nightscout.androidaps.logging.L
|
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.comm.TidepoolUploader
|
||||||
import info.nightscout.androidaps.plugins.general.tidepool.events.EventTidepoolDoUpload
|
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.EventTidepoolResetData
|
||||||
import info.nightscout.androidaps.plugins.general.tidepool.events.EventTidepoolStatus
|
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.plugins.general.tidepool.utils.RateLimit
|
||||||
import info.nightscout.androidaps.receivers.ChargingStateReceiver
|
import info.nightscout.androidaps.receivers.ChargingStateReceiver
|
||||||
import info.nightscout.androidaps.utils.SP
|
import info.nightscout.androidaps.utils.SP
|
||||||
import info.nightscout.androidaps.utils.T
|
import info.nightscout.androidaps.utils.T
|
||||||
|
import info.nightscout.androidaps.utils.ToastUtils
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
@ -33,15 +35,12 @@ object TidepoolPlugin : PluginBase(PluginDescription()
|
||||||
private val log = LoggerFactory.getLogger(L.TIDEPOOL)
|
private val log = LoggerFactory.getLogger(L.TIDEPOOL)
|
||||||
private var wifiConnected = false
|
private var wifiConnected = false
|
||||||
|
|
||||||
var session: Session? = null
|
|
||||||
|
|
||||||
private val listLog = ArrayList<EventTidepoolStatus>()
|
private val listLog = ArrayList<EventTidepoolStatus>()
|
||||||
internal var textLog = Html.fromHtml("")
|
var textLog = Html.fromHtml("")
|
||||||
|
var status = ""
|
||||||
|
|
||||||
var paused: Boolean = false
|
var paused: Boolean = false
|
||||||
internal var autoscroll: Boolean = false
|
|
||||||
|
|
||||||
var status = ""
|
|
||||||
override fun onStart() {
|
override fun onStart() {
|
||||||
MainApp.bus().register(this)
|
MainApp.bus().register(this)
|
||||||
super.onStart()
|
super.onStart()
|
||||||
|
@ -53,9 +52,10 @@ object TidepoolPlugin : PluginBase(PluginDescription()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun doUpload() {
|
fun doUpload() {
|
||||||
if (session == null)
|
if (TidepoolUploader.connectionStatus == TidepoolUploader.ConnectionStatus.DISCONNECTED)
|
||||||
session = TidepoolUploader.doLogin()
|
TidepoolUploader.doLogin()
|
||||||
else TidepoolUploader.doUpload(session!!)
|
else
|
||||||
|
TidepoolUploader.doUpload()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("UNUSED_PARAMETER")
|
@Suppress("UNUSED_PARAMETER")
|
||||||
|
@ -77,13 +77,13 @@ object TidepoolPlugin : PluginBase(PluginDescription()
|
||||||
@Suppress("UNUSED_PARAMETER")
|
@Suppress("UNUSED_PARAMETER")
|
||||||
@Subscribe
|
@Subscribe
|
||||||
fun onEventTidepoolResetData(ev: EventTidepoolResetData) {
|
fun onEventTidepoolResetData(ev: EventTidepoolResetData) {
|
||||||
if (session == null)
|
if (TidepoolUploader.connectionStatus != TidepoolUploader.ConnectionStatus.CONNECTED) {
|
||||||
session = TidepoolUploader.doLogin()
|
log.debug("Not connected for deleteDataset")
|
||||||
if (session != null) {
|
return
|
||||||
TidepoolUploader.deleteDataSet(session!!)
|
|
||||||
SP.putLong(R.string.key_tidepool_last_end, 0)
|
|
||||||
TidepoolUploader.doLogin()
|
|
||||||
}
|
}
|
||||||
|
TidepoolUploader.deleteDataSet()
|
||||||
|
SP.putLong(R.string.key_tidepool_last_end, 0)
|
||||||
|
TidepoolUploader.doLogin()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
|
@ -95,4 +95,36 @@ object TidepoolPlugin : PluginBase(PluginDescription()
|
||||||
return isEnabled(PluginType.GENERAL) && SP.getBoolean(R.string.key_cloud_storage_tidepool_enable, false)
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -31,6 +31,14 @@ object TidepoolUploader {
|
||||||
|
|
||||||
private var retrofit: Retrofit? = null
|
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? {
|
fun getRetrofitInstance(): Retrofit? {
|
||||||
if (retrofit == null) {
|
if (retrofit == null) {
|
||||||
|
|
||||||
|
@ -59,25 +67,38 @@ object TidepoolUploader {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
fun doLogin(): Session? {
|
fun doLogin() {
|
||||||
if (!SP.getBoolean(R.string.key_cloud_storage_tidepool_enable, false)) {
|
if (!SP.getBoolean(R.string.key_cloud_storage_tidepool_enable, false)) {
|
||||||
log.debug("Cannot login as disabled by preference")
|
if (L.isEnabled(L.TIDEPOOL))
|
||||||
return null
|
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
|
// TODO failure backoff
|
||||||
extendWakeLock(30000)
|
extendWakeLock(30000)
|
||||||
val session = Session(AuthRequestMessage.getAuthRequestHeader(), SESSION_TOKEN_HEADER)
|
session = Session(AuthRequestMessage.getAuthRequestHeader(), SESSION_TOKEN_HEADER)
|
||||||
if (session.authHeader != null) {
|
if (session?.authHeader != null) {
|
||||||
val call = session.service?.getLogin(session.authHeader!!)
|
connectionStatus = TidepoolUploader.ConnectionStatus.CONNECTING
|
||||||
status("Connecting")
|
status("Connecting")
|
||||||
|
val call = session!!.service?.getLogin(session?.authHeader!!)
|
||||||
|
|
||||||
call?.enqueue(TidepoolCallback<AuthReplyMessage>(session, "Login", { startSession(session) }, { loginFailed() }))
|
call?.enqueue(TidepoolCallback<AuthReplyMessage>(session!!, "Login", {
|
||||||
return session
|
startSession(session!!)
|
||||||
|
}, {
|
||||||
|
connectionStatus = TidepoolUploader.ConnectionStatus.FAILED;
|
||||||
|
loginFailed()
|
||||||
|
}))
|
||||||
|
return
|
||||||
} else {
|
} else {
|
||||||
if (L.isEnabled(L.TIDEPOOL)) log.debug("Cannot do login as user credentials have not been set correctly")
|
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")
|
status("Invalid credentials")
|
||||||
releaseWakeLock()
|
releaseWakeLock()
|
||||||
return null
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,48 +135,70 @@ object TidepoolUploader {
|
||||||
|
|
||||||
datasetCall.enqueue(TidepoolCallback<List<DatasetReplyMessage>>(session, "Get Open Datasets", {
|
datasetCall.enqueue(TidepoolCallback<List<DatasetReplyMessage>>(session, "Get Open Datasets", {
|
||||||
if (session.datasetReply == null) {
|
if (session.datasetReply == null) {
|
||||||
status("New data set")
|
status("Creating new dataset")
|
||||||
val call = session.service.openDataSet(session.token!!, session.authReply!!.userid!!, OpenDatasetRequestMessage().getBody())
|
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 {
|
} 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`.
|
// 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.
|
// ie, do the openDataSet conditionally, and then do `doUpload` either way.
|
||||||
status("Appending")
|
connectionStatus = TidepoolUploader.ConnectionStatus.CONNECTED;
|
||||||
doUpload(session)
|
status("Appending to existing dataset")
|
||||||
|
releaseWakeLock()
|
||||||
}
|
}
|
||||||
}, { releaseWakeLock() }))
|
}, {
|
||||||
|
connectionStatus = TidepoolUploader.ConnectionStatus.FAILED;
|
||||||
|
status("Open dataset FAILED")
|
||||||
|
releaseWakeLock()
|
||||||
|
}))
|
||||||
} else {
|
} else {
|
||||||
log.error("Got login response but cannot determine userid - cannot proceed")
|
log.error("Got login response but cannot determine userid - cannot proceed")
|
||||||
|
connectionStatus = TidepoolUploader.ConnectionStatus.FAILED;
|
||||||
status("Error userid")
|
status("Error userid")
|
||||||
releaseWakeLock()
|
releaseWakeLock()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun doUpload(session: Session) {
|
fun doUpload() {
|
||||||
if (!TidepoolPlugin.enabled()) {
|
if (!TidepoolPlugin.enabled()) {
|
||||||
if (L.isEnabled(L.TIDEPOOL))
|
if (L.isEnabled(L.TIDEPOOL))
|
||||||
log.debug("Cannot upload - preference disabled")
|
log.debug("Cannot upload - preference disabled")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if (session == null) {
|
||||||
|
log.error("Session is null, cannot proceed")
|
||||||
|
return
|
||||||
|
}
|
||||||
extendWakeLock(60000)
|
extendWakeLock(60000)
|
||||||
session.iterations++
|
session!!.iterations++
|
||||||
val chunk = UploadChunk.getNext(session)
|
val chunk = UploadChunk.getNext(session)
|
||||||
if (chunk == null) {
|
if (chunk == null) {
|
||||||
log.error("Upload chunk is null, cannot proceed")
|
log.error("Upload chunk is null, cannot proceed")
|
||||||
releaseWakeLock()
|
releaseWakeLock()
|
||||||
} else if (chunk.length == 2) {
|
} else if (chunk.length == 2) {
|
||||||
if (L.isEnabled(L.TIDEPOOL)) log.debug("Empty data set - marking as succeeded")
|
if (L.isEnabled(L.TIDEPOOL)) log.debug("Empty dataset - marking as succeeded")
|
||||||
doCompletedAndReleaseWakelock()
|
status("No data to upload")
|
||||||
|
releaseWakeLock()
|
||||||
} else {
|
} else {
|
||||||
val body = RequestBody.create(MediaType.parse("application/json"), chunk)
|
val body = RequestBody.create(MediaType.parse("application/json"), chunk)
|
||||||
|
|
||||||
val call = session.service!!.doUpload(session.token!!, session.datasetReply!!.getUploadId()!!, body)
|
|
||||||
status("Uploading")
|
status("Uploading")
|
||||||
call.enqueue(TidepoolCallback<UploadReplyMessage>(session, "Data Upload", {
|
val call = session!!.service!!.doUpload(session!!.token!!, session!!.datasetReply!!.getUploadId()!!, body)
|
||||||
UploadChunk.setLastEnd(session.end)
|
call.enqueue(TidepoolCallback<UploadReplyMessage>(session!!, "Data Upload", {
|
||||||
doCompletedAndReleaseWakelock()
|
UploadChunk.setLastEnd(session!!.end)
|
||||||
|
status("Upload completed OK")
|
||||||
|
releaseWakeLock()
|
||||||
}, {
|
}, {
|
||||||
|
status("Upload FAILED")
|
||||||
releaseWakeLock()
|
releaseWakeLock()
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
@ -168,15 +211,20 @@ object TidepoolUploader {
|
||||||
MainApp.bus().post(EventTidepoolStatus(status))
|
MainApp.bus().post(EventTidepoolStatus(status))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun doCompletedAndReleaseWakelock() {
|
|
||||||
status("Completed OK")
|
|
||||||
releaseWakeLock()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun deleteDataSet(session: Session) {
|
fun deleteDataSet() {
|
||||||
if (session.datasetReply?.id != null) {
|
if (session?.datasetReply?.id != null) {
|
||||||
val call = session.service?.deleteDataSet(session.token!!, session.datasetReply!!.id!!)
|
extendWakeLock(60000)
|
||||||
call?.enqueue(TidepoolCallback(session, "Delete Dataset", {}, {}))
|
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 {
|
} else {
|
||||||
log.error("Got login response but cannot determine dataseId - cannot proceed")
|
log.error("Got login response but cannot determine dataseId - cannot proceed")
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,10 @@ object UploadChunk {
|
||||||
|
|
||||||
private val log = LoggerFactory.getLogger(L.TIDEPOOL)
|
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.start = getLastEnd()
|
||||||
session.end = Math.min(session.start + MAX_UPLOAD_SIZE, DateUtil.now())
|
session.end = Math.min(session.start + MAX_UPLOAD_SIZE, DateUtil.now())
|
||||||
|
|
||||||
|
@ -48,6 +51,7 @@ object UploadChunk {
|
||||||
records.addAll(getBloodTests(start, end))
|
records.addAll(getBloodTests(start, end))
|
||||||
records.addAll(getBasals(start, end))
|
records.addAll(getBasals(start, end))
|
||||||
records.addAll(getBgReadings(start, end))
|
records.addAll(getBgReadings(start, end))
|
||||||
|
records.addAll(getProfiles(start, end))
|
||||||
|
|
||||||
return GsonInstance.defaultGsonInstance().toJson(records)
|
return GsonInstance.defaultGsonInstance().toJson(records)
|
||||||
}
|
}
|
||||||
|
@ -116,4 +120,16 @@ object UploadChunk {
|
||||||
return BasalElement.fromTemporaryBasals(tbrs)
|
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
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -19,6 +19,7 @@ class BloodGlucoseElement(careportalEvent: CareportalEvent)
|
||||||
var value: Int = 0
|
var value: Int = 0
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
type = "cbg"
|
||||||
subType = "manual" // TODO
|
subType = "manual" // TODO
|
||||||
var json = if (careportalEvent.json != null) JSONObject(careportalEvent.json) else JSONObject()
|
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()
|
value = Profile.toMgdl(JsonHelper.safeGetDouble(json, "glucose"), JsonHelper.safeGetString(json, "units", Constants.MGDL)).toInt()
|
||||||
|
|
|
@ -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
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
|
@ -1,6 +1,22 @@
|
||||||
package info.nightscout.androidaps.plugins.general.tidepool.events
|
package info.nightscout.androidaps.plugins.general.tidepool.events
|
||||||
|
|
||||||
import info.nightscout.androidaps.events.Event
|
import info.nightscout.androidaps.events.Event
|
||||||
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
|
||||||
class EventTidepoolStatus (val status: String) : Event() {
|
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
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.tidepool.events;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.events.Event;
|
||||||
|
|
||||||
|
public class EventTidepoolUpdateGUI extends Event {
|
||||||
|
}
|
|
@ -29,7 +29,7 @@ class OpenDatasetRequestMessage : BaseMessage() {
|
||||||
@Expose
|
@Expose
|
||||||
var deviceManufacturers = arrayOf(((ConfigBuilderPlugin.getPlugin().activeBgSource ?: SourceNSClientPlugin.getPlugin()) as PluginBase).name)
|
var deviceManufacturers = arrayOf(((ConfigBuilderPlugin.getPlugin().activeBgSource ?: SourceNSClientPlugin.getPlugin()) as PluginBase).name)
|
||||||
@Expose
|
@Expose
|
||||||
var deviceModel = arrayOf(((ConfigBuilderPlugin.getPlugin().activeBgSource ?: SourceNSClientPlugin.getPlugin()) as PluginBase).name)
|
var deviceModel = ((ConfigBuilderPlugin.getPlugin().activeBgSource ?: SourceNSClientPlugin.getPlugin()) as PluginBase).name
|
||||||
@Expose
|
@Expose
|
||||||
var deviceTags = arrayOf("bgm", "cgm", "insulin-pump")
|
var deviceTags = arrayOf("bgm", "cgm", "insulin-pump")
|
||||||
@Expose
|
@Expose
|
||||||
|
@ -45,7 +45,7 @@ class OpenDatasetRequestMessage : BaseMessage() {
|
||||||
@Expose
|
@Expose
|
||||||
val name = BuildConfig.APPLICATION_ID
|
val name = BuildConfig.APPLICATION_ID
|
||||||
@Expose
|
@Expose
|
||||||
val version = "0.1.0" // TODO: const it
|
val version = BuildConfig.VERSION_NAME
|
||||||
}
|
}
|
||||||
|
|
||||||
inner class Deduplicator {
|
inner class Deduplicator {
|
||||||
|
|
|
@ -417,8 +417,8 @@ public class LocalInsightPlugin extends PluginBase implements PumpInterface, Con
|
||||||
MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED));
|
MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED));
|
||||||
List<BasalProfileBlock> profileBlocks = new ArrayList<>();
|
List<BasalProfileBlock> profileBlocks = new ArrayList<>();
|
||||||
for (int i = 0; i < profile.getBasalValues().length; i++) {
|
for (int i = 0; i < profile.getBasalValues().length; i++) {
|
||||||
Profile.BasalValue basalValue = profile.getBasalValues()[i];
|
Profile.ProfileValue basalValue = profile.getBasalValues()[i];
|
||||||
Profile.BasalValue nextValue = null;
|
Profile.ProfileValue nextValue = null;
|
||||||
if (profile.getBasalValues().length > i + 1)
|
if (profile.getBasalValues().length > i + 1)
|
||||||
nextValue = profile.getBasalValues()[i + 1];
|
nextValue = profile.getBasalValues()[i + 1];
|
||||||
BasalProfileBlock profileBlock = new BasalProfileBlock();
|
BasalProfileBlock profileBlock = new BasalProfileBlock();
|
||||||
|
@ -471,8 +471,8 @@ public class LocalInsightPlugin extends PluginBase implements PumpInterface, Con
|
||||||
if (activeBasalProfile != BasalProfile.PROFILE_1) return false;
|
if (activeBasalProfile != BasalProfile.PROFILE_1) return false;
|
||||||
for (int i = 0; i < profileBlocks.size(); i++) {
|
for (int i = 0; i < profileBlocks.size(); i++) {
|
||||||
BasalProfileBlock profileBlock = profileBlocks.get(i);
|
BasalProfileBlock profileBlock = profileBlocks.get(i);
|
||||||
Profile.BasalValue basalValue = profile.getBasalValues()[i];
|
Profile.ProfileValue basalValue = profile.getBasalValues()[i];
|
||||||
Profile.BasalValue nextValue = null;
|
Profile.ProfileValue nextValue = null;
|
||||||
if (profile.getBasalValues().length > i + 1)
|
if (profile.getBasalValues().length > i + 1)
|
||||||
nextValue = profile.getBasalValues()[i + 1];
|
nextValue = profile.getBasalValues()[i + 1];
|
||||||
if (profileBlock.getDuration() * 60 != (nextValue != null ? nextValue.timeAsSeconds : 24 * 60 * 60) - basalValue.timeAsSeconds)
|
if (profileBlock.getDuration() * 60 != (nextValue != null ? nextValue.timeAsSeconds : 24 * 60 * 60) - basalValue.timeAsSeconds)
|
||||||
|
|
|
@ -12,8 +12,6 @@ import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.MainApp;
|
import info.nightscout.androidaps.MainApp;
|
||||||
import info.nightscout.androidaps.R;
|
import info.nightscout.androidaps.R;
|
||||||
import info.nightscout.androidaps.data.DetailedBolusInfo;
|
import info.nightscout.androidaps.data.DetailedBolusInfo;
|
||||||
|
@ -388,10 +386,10 @@ public class CommandQueue {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compare with pump limits
|
// Compare with pump limits
|
||||||
Profile.BasalValue[] basalValues = profile.getBasalValues();
|
Profile.ProfileValue[] basalValues = profile.getBasalValues();
|
||||||
PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump();
|
PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump();
|
||||||
|
|
||||||
for (Profile.BasalValue basalValue : basalValues) {
|
for (Profile.ProfileValue basalValue : basalValues) {
|
||||||
if (basalValue.value < pump.getPumpDescription().basalMinimumRate) {
|
if (basalValue.value < pump.getPumpDescription().basalMinimumRate) {
|
||||||
Notification notification = new Notification(Notification.BASAL_VALUE_BELOW_MINIMUM, MainApp.gs(R.string.basalvaluebelowminimum), Notification.URGENT);
|
Notification notification = new Notification(Notification.BASAL_VALUE_BELOW_MINIMUM, MainApp.gs(R.string.basalvaluebelowminimum), Notification.URGENT);
|
||||||
MainApp.bus().post(new EventNewNotification(notification));
|
MainApp.bus().post(new EventNewNotification(notification));
|
||||||
|
|
Loading…
Reference in a new issue