cleanup, hook to preferences change

This commit is contained in:
Milos Kozak 2019-06-07 11:07:08 +02:00
parent 01006b32ce
commit 643ddfae52
8 changed files with 111 additions and 79 deletions

View file

@ -30,7 +30,7 @@ public class TidepoolJavaFragment extends SubscriberFragment {
Button login = view.findViewById(R.id.tidepool_login);
login.setOnClickListener(v1 -> {
TidepoolUploader.INSTANCE.doLogin();
TidepoolUploader.INSTANCE.doLogin(false);
});
Button uploadnow = view.findViewById(R.id.tidepool_uploadnow);
uploadnow.setOnClickListener(v2 -> MainApp.bus().post(new EventTidepoolDoUpload()));

View file

@ -6,6 +6,8 @@ import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R
import info.nightscout.androidaps.events.EventNetworkChange
import info.nightscout.androidaps.events.EventNewBG
import info.nightscout.androidaps.events.EventPreferenceChange
import info.nightscout.androidaps.interfaces.PluginBase
import info.nightscout.androidaps.interfaces.PluginDescription
import info.nightscout.androidaps.interfaces.PluginType
@ -16,8 +18,8 @@ import info.nightscout.androidaps.plugins.general.tidepool.events.EventTidepoolR
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.iob.iobCobCalculator.events.EventAutosensCalculationFinished
import info.nightscout.androidaps.receivers.ChargingStateReceiver
import info.nightscout.androidaps.receivers.NetworkChangeReceiver
import info.nightscout.androidaps.utils.SP
import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.ToastUtils
@ -33,13 +35,11 @@ object TidepoolPlugin : PluginBase(PluginDescription()
.description(R.string.description_tidepool)
) {
private val log = LoggerFactory.getLogger(L.TIDEPOOL)
private var wifiConnected = false
private val listLog = ArrayList<EventTidepoolStatus>()
@Suppress("DEPRECATION") // API level 24 to replace call
var textLog = Html.fromHtml("")
var paused: Boolean = false
override fun onStart() {
MainApp.bus().register(this)
super.onStart()
@ -52,17 +52,19 @@ object TidepoolPlugin : PluginBase(PluginDescription()
fun doUpload() {
if (TidepoolUploader.connectionStatus == TidepoolUploader.ConnectionStatus.DISCONNECTED)
TidepoolUploader.doLogin()
TidepoolUploader.doLogin(true)
else
TidepoolUploader.doUpload()
}
@Suppress("UNUSED_PARAMETER")
@Subscribe
fun onStatusEvent(ev: EventAutosensCalculationFinished) {
fun onStatusEvent(ev: EventNewBG) {
if (ev.bgReading!!.date!! < TidepoolUploader.getLastEnd())
TidepoolUploader.setLastEnd(ev.bgReading!!.date!!)
if (isEnabled(PluginType.GENERAL)
&& (!SP.getBoolean(R.string.key_tidepool_only_while_charging, false) || ChargingStateReceiver.isCharging())
&& (!SP.getBoolean(R.string.key_tidepool_only_while_unmetered, false) || wifiConnected)
&& (!SP.getBoolean(R.string.key_tidepool_only_while_unmetered, false) || NetworkChangeReceiver.isWifiConnected())
&& RateLimit.ratelimit("tidepool-new-data-upload", T.mins(4).secs().toInt()))
doUpload()
}
@ -73,6 +75,15 @@ object TidepoolPlugin : PluginBase(PluginDescription()
doUpload()
}
@Subscribe
fun onEventPreferenceChange(ev: EventPreferenceChange) {
if (ev.isChanged(R.string.key_tidepool_dev_servers)
|| ev.isChanged(R.string.key_tidepool_username)
|| ev.isChanged(R.string.key_tidepool_password)
)
TidepoolUploader.resetInstance()
}
@Suppress("UNUSED_PARAMETER")
@Subscribe
fun onEventTidepoolResetData(ev: EventTidepoolResetData) {
@ -87,7 +98,7 @@ object TidepoolPlugin : PluginBase(PluginDescription()
@Subscribe
fun onEventNetworkChange(ev: EventNetworkChange) {
wifiConnected = ev.wifiConnected
// TODO start upload on wifi connect
}
@Subscribe
@ -116,6 +127,7 @@ object TidepoolPlugin : PluginBase(PluginDescription()
newTextLog.append(log.toPreparedHtml())
}
}
@Suppress("DEPRECATION") // API level 24 to replace call
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

@ -6,11 +6,12 @@ import info.nightscout.androidaps.BuildConfig
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R
import info.nightscout.androidaps.logging.L
import info.nightscout.androidaps.plugins.general.tidepool.TidepoolPlugin
import info.nightscout.androidaps.plugins.general.tidepool.events.EventTidepoolStatus
import info.nightscout.androidaps.plugins.general.tidepool.messages.*
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.OKDialog
import info.nightscout.androidaps.utils.SP
import info.nightscout.androidaps.utils.T
import okhttp3.MediaType
import okhttp3.OkHttpClient
import okhttp3.RequestBody
@ -64,10 +65,11 @@ object TidepoolUploader {
retrofit = null
if (L.isEnabled(L.TIDEPOOL))
log.debug("Instance reset")
connectionStatus = TidepoolUploader.ConnectionStatus.DISCONNECTED
}
@Synchronized
fun doLogin() {
fun doLogin(doUpload: Boolean = false) {
if (connectionStatus == TidepoolUploader.ConnectionStatus.CONNECTED || connectionStatus == TidepoolUploader.ConnectionStatus.CONNECTING) {
if (L.isEnabled(L.TIDEPOOL))
log.debug("Already connected")
@ -78,11 +80,11 @@ object TidepoolUploader {
session = Session(AuthRequestMessage.getAuthRequestHeader(), SESSION_TOKEN_HEADER)
if (session?.authHeader != null) {
connectionStatus = TidepoolUploader.ConnectionStatus.CONNECTING
status("Connecting")
MainApp.bus().post(EventTidepoolStatus(("Connecting")))
val call = session!!.service?.getLogin(session?.authHeader!!)
call?.enqueue(TidepoolCallback<AuthReplyMessage>(session!!, "Login", {
startSession(session!!)
startSession(session!!, doUpload)
}, {
connectionStatus = TidepoolUploader.ConnectionStatus.FAILED;
loginFailed()
@ -91,7 +93,7 @@ object TidepoolUploader {
} 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")
MainApp.bus().post(EventTidepoolStatus(("Invalid credentials")))
releaseWakeLock()
return
}
@ -119,7 +121,7 @@ object TidepoolUploader {
releaseWakeLock()
}
fun startSession(session: Session) {
fun startSession(session: Session, doUpload: Boolean = false) {
extendWakeLock(30000)
if (session.authReply?.userid != null) {
// See if we already have an open data set to write to
@ -128,14 +130,15 @@ object TidepoolUploader {
datasetCall.enqueue(TidepoolCallback<List<DatasetReplyMessage>>(session, "Get Open Datasets", {
if (session.datasetReply == null) {
status("Creating new dataset")
MainApp.bus().post(EventTidepoolStatus(("Creating new dataset")))
val call = session.service.openDataSet(session.token!!, session.authReply!!.userid!!, OpenDatasetRequestMessage().getBody())
call.enqueue(TidepoolCallback<DatasetReplyMessage>(session, "Open New Dataset", {
connectionStatus = TidepoolUploader.ConnectionStatus.CONNECTED;
status("New dataset OK")
MainApp.bus().post(EventTidepoolStatus(("New dataset OK")))
if (doUpload) doUpload()
releaseWakeLock()
}, {
status("New dataset FAILED")
MainApp.bus().post(EventTidepoolStatus(("New dataset FAILED")))
connectionStatus = TidepoolUploader.ConnectionStatus.FAILED;
releaseWakeLock()
}))
@ -145,18 +148,19 @@ object TidepoolUploader {
// 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.
connectionStatus = TidepoolUploader.ConnectionStatus.CONNECTED;
status("Appending to existing dataset")
MainApp.bus().post(EventTidepoolStatus(("Appending to existing dataset")))
if (doUpload) doUpload()
releaseWakeLock()
}
}, {
connectionStatus = TidepoolUploader.ConnectionStatus.FAILED;
status("Open dataset FAILED")
MainApp.bus().post(EventTidepoolStatus(("Open dataset FAILED")))
releaseWakeLock()
}))
} else {
log.error("Got login response but cannot determine userid - cannot proceed")
connectionStatus = TidepoolUploader.ConnectionStatus.FAILED;
status("Error userid")
MainApp.bus().post(EventTidepoolStatus(("Error userid")))
releaseWakeLock()
}
}
@ -175,43 +179,36 @@ object TidepoolUploader {
releaseWakeLock()
} else if (chunk.length == 2) {
if (L.isEnabled(L.TIDEPOOL)) log.debug("Empty dataset - marking as succeeded")
status("No data to upload")
MainApp.bus().post(EventTidepoolStatus(("No data to upload")))
releaseWakeLock()
} else {
val body = RequestBody.create(MediaType.parse("application/json"), chunk)
status("Uploading")
MainApp.bus().post(EventTidepoolStatus(("Uploading")))
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")
setLastEnd(session!!.end)
MainApp.bus().post(EventTidepoolStatus(("Upload completed OK")))
releaseWakeLock()
}, {
status("Upload FAILED")
MainApp.bus().post(EventTidepoolStatus(("Upload FAILED")))
releaseWakeLock()
}))
}
}
fun status(status: String) {
if (L.isEnabled(L.TIDEPOOL))
log.debug("New status: $status")
MainApp.bus().post(EventTidepoolStatus(status))
}
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")
MainApp.bus().post(EventTidepoolStatus(("Dataset removed OK")))
releaseWakeLock()
}, {
connectionStatus = TidepoolUploader.ConnectionStatus.DISCONNECTED
status("Dataset remove FAILED")
MainApp.bus().post(EventTidepoolStatus(("Dataset remove FAILED")))
releaseWakeLock()
}))
} else {
@ -219,6 +216,23 @@ object TidepoolUploader {
}
}
fun getLastEnd(): Long {
val result = SP.getLong(R.string.key_tidepool_last_end, 0)
return Math.max(result, DateUtil.now() - T.months(2).msecs())
}
fun setLastEnd(time: Long) {
if (time > getLastEnd()) {
SP.putLong(R.string.key_tidepool_last_end, time)
val friendlyEnd = DateUtil.dateAndTimeString(time)
MainApp.bus().post(EventTidepoolStatus(("Marking uploaded data up to $friendlyEnd")))
if (L.isEnabled(L.TIDEPOOL)) log.debug("Updating last end to: " + DateUtil.dateAndTimeString(time))
} else {
if (L.isEnabled(L.TIDEPOOL)) log.debug("Cannot set last end to: " + DateUtil.dateAndTimeString(time) + " vs " + DateUtil.dateAndTimeString(getLastEnd()))
}
}
@Synchronized
private fun extendWakeLock(ms: Long) {
if (wl == null) {

View file

@ -1,13 +1,12 @@
package info.nightscout.androidaps.plugins.general.tidepool.comm
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R
import info.nightscout.androidaps.logging.L
import info.nightscout.androidaps.plugins.general.tidepool.elements.*
import info.nightscout.androidaps.plugins.general.tidepool.events.EventTidepoolStatus
import info.nightscout.androidaps.plugins.general.tidepool.utils.GsonInstance
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.SP
import info.nightscout.androidaps.utils.T
import org.slf4j.LoggerFactory
import java.util.*
@ -22,13 +21,13 @@ object UploadChunk {
if (session == null)
return null
session.start = getLastEnd()
session.start = TidepoolUploader.getLastEnd()
session.end = Math.min(session.start + MAX_UPLOAD_SIZE, DateUtil.now())
val result = get(session.start, session.end)
if (result.length < 3) {
if (L.isEnabled(L.TIDEPOOL)) log.debug("No records in this time period, setting start to best end time")
setLastEnd(Math.max(session.end, getOldestRecordTimeStamp()))
TidepoolUploader.setLastEnd(Math.max(session.end, getOldestRecordTimeStamp()))
}
return result
}
@ -56,22 +55,6 @@ object UploadChunk {
return GsonInstance.defaultGsonInstance().toJson(records)
}
fun getLastEnd(): Long {
val result = SP.getLong(R.string.key_tidepool_last_end, 0)
return Math.max(result, DateUtil.now() - T.months(2).msecs())
}
fun setLastEnd(time: Long) {
if (time > getLastEnd()) {
SP.putLong(R.string.key_tidepool_last_end, time)
val friendlyEnd = DateUtil.dateAndTimeString(time)
TidepoolUploader.status("Marking uploaded data up to $friendlyEnd")
if (L.isEnabled(L.TIDEPOOL)) log.debug("Updating last end to: " + DateUtil.dateAndTimeString(time))
} else {
if (L.isEnabled(L.TIDEPOOL)) log.debug("Cannot set last end to: " + DateUtil.dateAndTimeString(time) + " vs " + DateUtil.dateAndTimeString(getLastEnd()))
}
}
// numeric limits must match max time windows
private fun getOldestRecordTimeStamp(): Long {
@ -99,39 +82,41 @@ object UploadChunk {
return result
}
internal fun getBloodTests(start: Long, end: Long): List<BloodGlucoseElement> {
val readings = MainApp.getDbHelper().getCareportalEvents(start, end, true)
if (L.isEnabled(L.TIDEPOOL))
log.debug("${readings.size} CPs selected for upload")
return BloodGlucoseElement.fromCareportalEvents(readings)
val selection = BloodGlucoseElement.fromCareportalEvents(readings)
if (selection.isNotEmpty())
MainApp.bus().post(EventTidepoolStatus("${selection.size} BGs selected for upload"))
return selection
}
internal fun getBgReadings(start: Long, end: Long): List<SensorGlucoseElement> {
val readings = MainApp.getDbHelper().getBgreadingsDataFromTime(start, end, true)
if (L.isEnabled(L.TIDEPOOL))
log.debug("${readings.size} BGs selected for upload")
return SensorGlucoseElement.fromBgReadings(readings)
val selection = SensorGlucoseElement.fromBgReadings(readings)
if (selection.isNotEmpty())
MainApp.bus().post(EventTidepoolStatus("${selection.size} CGMs selected for upload"))
return selection
}
internal fun getBasals(start: Long, end: Long): List<BasalElement> {
val tbrs = MainApp.getDbHelper().getTemporaryBasalsDataFromTime(start, end, true)
if (L.isEnabled(L.TIDEPOOL))
log.debug("${tbrs.size} TBRs selected for upload")
return BasalElement.fromTemporaryBasals(tbrs)
val selection = BasalElement.fromTemporaryBasals(tbrs)
if (selection.isNotEmpty())
MainApp.bus().post(EventTidepoolStatus("${selection.size} TBRs selected for upload"))
return selection
}
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>()
val selection = LinkedList<ProfileElement>()
for (ps in pss) {
val pe = ProfileElement(ps)
results.add(pe)
selection.add(pe)
}
return results
if (selection.size > 0)
MainApp.bus().post(EventTidepoolStatus("${selection.size} ProfileSwitches selected for upload"))
return selection
}
}

View file

@ -1,13 +1,23 @@
package info.nightscout.androidaps.plugins.general.tidepool.events
import info.nightscout.androidaps.events.Event
import info.nightscout.androidaps.logging.L
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.LocaleHelper
import org.slf4j.LoggerFactory
import java.text.SimpleDateFormat
class EventTidepoolStatus (val status: String) : Event() {
var date : Long = DateUtil.now()
class EventTidepoolStatus(val status: String) : Event() {
private val log = LoggerFactory.getLogger(L.TIDEPOOL)
internal var timeFormat = SimpleDateFormat("HH:mm:ss")
var date: Long = DateUtil.now()
init {
if (L.isEnabled(L.TIDEPOOL))
log.debug("New status: $status")
}
internal var timeFormat = SimpleDateFormat("HH:mm:ss", LocaleHelper.getLocale())
fun toPreparedHtml(): StringBuilder {
val stringBuilder = StringBuilder()

View file

@ -21,6 +21,8 @@ public class NetworkChangeReceiver extends BroadcastReceiver {
private static Logger log = LoggerFactory.getLogger(L.CORE);
private static EventNetworkChange lastEvent = null;
@Override
public void onReceive(final Context context, final Intent intent) {
EventNetworkChange event = grabNetworkStatus(context);
@ -61,6 +63,11 @@ public class NetworkChangeReceiver extends BroadcastReceiver {
log.debug("NETCHANGE: Disconnected.");
}
lastEvent = event;
return event;
}
public static boolean isWifiConnected() {
return lastEvent != null && lastEvent.wifiConnected;
}
}

View file

@ -121,7 +121,7 @@ public class FabricPrivacy {
.replace(".net/", ":");
MainApp.getFirebaseAnalytics().setUserProperty("Mode", BuildConfig.APPLICATION_ID + "-" + closedLoopEnabled);
MainApp.getFirebaseAnalytics().setUserProperty("Language", LocaleHelper.getLanguage(MainApp.instance()));
MainApp.getFirebaseAnalytics().setUserProperty("Language", LocaleHelper.getLanguage());
MainApp.getFirebaseAnalytics().setUserProperty("Version", BuildConfig.VERSION);
MainApp.getFirebaseAnalytics().setUserProperty("HEAD", BuildConfig.HEAD);
MainApp.getFirebaseAnalytics().setUserProperty("Remote", remote);

View file

@ -21,17 +21,17 @@ public class LocaleHelper {
private static final String SELECTED_LANGUAGE = "Locale.Helper.Selected.Language";
public static void onCreate(Context context) {
String lang = getPersistedData(context, Locale.getDefault().getLanguage());
String lang = getPersistedData(Locale.getDefault().getLanguage());
setLocale(context, lang);
}
public static void onCreate(Context context, String defaultLanguage) {
String lang = getPersistedData(context, defaultLanguage);
String lang = getPersistedData(defaultLanguage);
setLocale(context, lang);
}
public static String getLanguage(Context context) {
return getPersistedData(context, Locale.getDefault().getLanguage());
public static String getLanguage() {
return getPersistedData(Locale.getDefault().getLanguage());
}
public static void setLocale(Context context, String language) {
@ -39,7 +39,7 @@ public class LocaleHelper {
updateResources(context, language);
}
private static String getPersistedData(Context context, String defaultLanguage) {
private static String getPersistedData(String defaultLanguage) {
return SP.getString(SELECTED_LANGUAGE, defaultLanguage);
}
@ -62,4 +62,8 @@ public class LocaleHelper {
resources.updateConfiguration(configuration, resources.getDisplayMetrics());
}
public static Locale getLocale() {
return new Locale(getPersistedData("en"));
}
}