TT & GV new way of upload to NS

This commit is contained in:
Milos Kozak 2021-03-27 23:14:51 +01:00
parent 6aa9a0fe12
commit c9c02458d6
24 changed files with 470 additions and 395 deletions

View file

@ -1,11 +1,10 @@
package info.nightscout.androidaps.plugins.general.nsclient
import androidx.work.ListenableWorker
import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.GlucoseValue
import info.nightscout.androidaps.database.entities.TemporaryTarget
import info.nightscout.androidaps.database.transactions.UpdateTemporaryTargetTransaction
import info.nightscout.androidaps.db.DbRequest
import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.DataSyncSelector
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.AAPSLogger
@ -21,23 +20,13 @@ class DataSyncSelectorImplementation @Inject constructor(
private val dateUtil: DateUtil,
private val profileFunction: ProfileFunction,
private val nsClientPlugin: NSClientPlugin,
private val activePlugin: ActivePluginProvider,
private val appRepository: AppRepository
) : DataSyncSelector {
/*
val updateTempTargetNsId = Runnable {
interfaceIDs.nightscoutId = nsId
repository.runTransactionForResult(UpdateTemporaryTargetTransaction(this))
.doOnError {
aapsLogger.error(LTag.DATABASE, "Error while saving temporary target", it)
ret = ListenableWorker.Result.failure()
}
.blockingGet()
}
*/
override fun resetToNextFullSync() {
sp.remove(R.string.key_ns_temporary_target_last_sync)
sp.remove(R.string.key_ns_glucose_value_last_sync)
}
override fun confirmTempTargetsTimestamp(lastSynced: Long) {
@ -46,37 +35,80 @@ class DataSyncSelectorImplementation @Inject constructor(
}
override fun confirmTempTargetsTimestampIfGreater(lastSynced: Long) {
aapsLogger.debug(LTag.NSCLIENT, "Setting TT data sync from $lastSynced")
if (lastSynced > sp.getLong(R.string.key_ns_temporary_target_last_sync, 0)) {
aapsLogger.debug(LTag.NSCLIENT, ">>> Setting TT data sync from $lastSynced")
sp.putLong(R.string.key_ns_temporary_target_last_sync, lastSynced)
}
if (lastSynced > sp.getLong(R.string.key_ns_temporary_target_last_sync, 0))
confirmTempTargetsTimestamp(lastSynced)
}
// Prepared for v3 (returns all modified after)
override fun changedTempTargets(): List<TemporaryTarget> {
val startTime = sp.getLong(R.string.key_ns_temporary_target_last_sync, 0)
return appRepository.getAllChangedTemporaryTargetsFromTime(startTime, 1).blockingGet().also {
aapsLogger.debug(LTag.NSCLIENT, "Loading TT data for sync from $startTime ${dateUtil.dateAndTimeAndSecondsString(startTime)}. Records ${it.size}")
val startId = sp.getLong(R.string.key_ns_temporary_target_last_sync, 0)
return appRepository.getModifiedTemporaryTargetsDataFromId(startId).blockingGet().also {
aapsLogger.debug(LTag.NSCLIENT, "Loading TT data for sync from $startId. Records ${it.size}")
}
}
override fun processChangedTempTargetsCompat(): Boolean {
val changedTT = changedTempTargets()
changedTT.forEach { tt ->
val startId = sp.getLong(R.string.key_ns_temporary_target_last_sync, 0)
appRepository.getNextSyncElementTemporaryTarget(startId).blockingGet()?.let { tt ->
aapsLogger.info(LTag.DATABASE, "Loading TemporaryTarget data Start: $startId ID: ${tt.first.id} HistoryID: ${tt.second} ")
when {
// removed and not uploaded yet = ignore
!tt.isValid && tt.interfaceIDs.nightscoutId == null -> Any()
!tt.first.isValid && tt.first.interfaceIDs.nightscoutId == null -> Any()
// removed and already uploaded = send for removal
!tt.isValid && tt.interfaceIDs.nightscoutId != null ->
nsClientPlugin.nsClientService?.dbRemove("treatments", tt.interfaceIDs.nightscoutId, tt)
!tt.first.isValid && tt.first.interfaceIDs.nightscoutId != null ->
nsClientPlugin.nsClientService?.dbRemove("treatments", tt.first.interfaceIDs.nightscoutId, DataSyncSelector.PairTemporaryTarget(tt.first, tt.second))
// existing without nsId = create new
tt.isValid && tt.interfaceIDs.nightscoutId == null ->
nsClientPlugin.nsClientService?.dbAdd("treatments", tt.toJson(profileFunction.getUnits()), tt)
tt.first.isValid && tt.first.interfaceIDs.nightscoutId == null ->
nsClientPlugin.nsClientService?.dbAdd("treatments", tt.first.toJson(profileFunction.getUnits()), DataSyncSelector.PairTemporaryTarget(tt.first, tt.second))
// existing with nsId = update
tt.isValid && tt.interfaceIDs.nightscoutId != null ->
nsClientPlugin.nsClientService?.dbUpdate("treatments", tt.interfaceIDs.nightscoutId, tt.toJson(profileFunction.getUnits()), tt)
tt.first.isValid && tt.first.interfaceIDs.nightscoutId != null ->
nsClientPlugin.nsClientService?.dbUpdate("treatments", tt.first.interfaceIDs.nightscoutId, tt.first.toJson(profileFunction.getUnits()), DataSyncSelector.PairTemporaryTarget(tt.first, tt.second))
}
return true
}
return false
}
override fun confirmLastGlucoseValueId(lastSynced: Long) {
aapsLogger.debug(LTag.NSCLIENT, "Setting GlucoseValue data sync from $lastSynced")
sp.putLong(R.string.key_ns_glucose_value_last_sync, lastSynced)
}
override fun confirmLastGlucoseValueIdIfGreater(lastSynced: Long) {
if (lastSynced > sp.getLong(R.string.key_ns_glucose_value_last_sync, 0))
confirmLastGlucoseValueId(lastSynced)
}
// Prepared for v3 (returns all modified after)
override fun changedGlucoseValues(): List<GlucoseValue> {
val startId = sp.getLong(R.string.key_ns_glucose_value_last_sync, 0)
return appRepository.getModifiedBgReadingsDataFromId(startId).blockingGet().also {
aapsLogger.debug(LTag.NSCLIENT, "Loading GlucoseValue data for sync from $startId . Records ${it.size}")
}
}
override fun processChangedGlucoseValuesCompat(): Boolean {
val startId = sp.getLong(R.string.key_ns_glucose_value_last_sync, 0)
appRepository.getNextSyncElementGlucoseValue(startId).blockingGet()?.let { gv ->
aapsLogger.info(LTag.DATABASE, "Loading GlucoseValue data Start: $startId ID: ${gv.first.id} HistoryID: ${gv.second} ")
if (activePlugin.activeBgSource.uploadToNs(gv.first)) {
when {
// removed and not uploaded yet = ignore
!gv.first.isValid && gv.first.interfaceIDs.nightscoutId == null -> Any()
// removed and already uploaded = send for removal
!gv.first.isValid && gv.first.interfaceIDs.nightscoutId != null ->
nsClientPlugin.nsClientService?.dbRemove("entries", gv.first.interfaceIDs.nightscoutId, DataSyncSelector.PairGlucoseValue(gv.first, gv.second))
// existing without nsId = create new
gv.first.isValid && gv.first.interfaceIDs.nightscoutId == null ->
nsClientPlugin.nsClientService?.dbAdd("entries", gv.first.toJson(), DataSyncSelector.PairGlucoseValue(gv.first, gv.second))
// existing with nsId = update
gv.first.isValid && gv.first.interfaceIDs.nightscoutId != null ->
nsClientPlugin.nsClientService?.dbUpdate("entries", gv.first.interfaceIDs.nightscoutId, gv.first.toJson(), DataSyncSelector.PairGlucoseValue(gv.first, gv.second))
}
return true
}
}
return changedTT.isNotEmpty()
return false
}
}
}

View file

@ -1,171 +0,0 @@
package info.nightscout.androidaps.plugins.general.nsclient;
import android.graphics.Paint;
import android.os.Bundle;
import android.text.Spanned;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.ScrollView;
import android.widget.TextView;
import javax.inject.Inject;
import dagger.android.support.DaggerFragment;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.interfaces.UploadQueueAdminInterface;
import info.nightscout.androidaps.database.entities.UserEntry;
import info.nightscout.androidaps.database.entities.UserEntry.*;
import info.nightscout.androidaps.logging.UserEntryLogger;
import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientNewLog;
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart;
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientUpdateGUI;
import info.nightscout.androidaps.utils.FabricPrivacy;
import info.nightscout.androidaps.utils.HtmlHelper;
import info.nightscout.androidaps.utils.alertDialogs.OKDialog;
import info.nightscout.androidaps.utils.resources.ResourceHelper;
import info.nightscout.androidaps.utils.rx.AapsSchedulers;
import info.nightscout.androidaps.utils.sharedPreferences.SP;
import io.reactivex.disposables.CompositeDisposable;
public class NSClientFragment extends DaggerFragment implements View.OnClickListener, CompoundButton.OnCheckedChangeListener {
@Inject NSClientPlugin nsClientPlugin;
@Inject SP sp;
@Inject ResourceHelper resourceHelper;
@Inject RxBusWrapper rxBus;
@Inject UploadQueueAdminInterface uploadQueue;
@Inject FabricPrivacy fabricPrivacy;
@Inject AapsSchedulers aapsSchedulers;
@Inject UserEntryLogger uel;
private final CompositeDisposable disposable = new CompositeDisposable();
private TextView logTextView;
private TextView queueTextView;
private TextView urlTextView;
private TextView statusTextView;
private TextView clearlog;
private TextView restart;
private TextView delivernow;
private TextView clearqueue;
private TextView showqueue;
private ScrollView logScrollview;
private CheckBox autoscrollCheckbox;
private CheckBox pausedCheckbox;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.nsclientinternal_fragment, container, false);
logScrollview = view.findViewById(R.id.nsclientinternal_logscrollview);
autoscrollCheckbox = view.findViewById(R.id.nsclientinternal_autoscroll);
autoscrollCheckbox.setChecked(nsClientPlugin.autoscroll);
autoscrollCheckbox.setOnCheckedChangeListener(this);
pausedCheckbox = view.findViewById(R.id.nsclientinternal_paused);
pausedCheckbox.setChecked(nsClientPlugin.paused);
pausedCheckbox.setOnCheckedChangeListener(this);
logTextView = view.findViewById(R.id.nsclientinternal_log);
queueTextView = view.findViewById(R.id.nsclientinternal_queue);
urlTextView = view.findViewById(R.id.nsclientinternal_url);
statusTextView = view.findViewById(R.id.nsclientinternal_status);
clearlog = view.findViewById(R.id.nsclientinternal_clearlog);
clearlog.setOnClickListener(this);
clearlog.setPaintFlags(clearlog.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
restart = view.findViewById(R.id.nsclientinternal_restart);
restart.setOnClickListener(this);
restart.setPaintFlags(restart.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
delivernow = view.findViewById(R.id.nsclientinternal_delivernow);
delivernow.setOnClickListener(this);
delivernow.setPaintFlags(delivernow.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
clearqueue = view.findViewById(R.id.nsclientinternal_clearqueue);
clearqueue.setOnClickListener(this);
clearqueue.setPaintFlags(clearqueue.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
showqueue = view.findViewById(R.id.nsclientinternal_showqueue);
showqueue.setOnClickListener(this);
showqueue.setPaintFlags(showqueue.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
return view;
}
@Override
public synchronized void onResume() {
super.onResume();
disposable.add(rxBus
.toObservable(EventNSClientUpdateGUI.class)
.observeOn(aapsSchedulers.getMain())
.subscribe(event -> updateGui(), fabricPrivacy::logException)
);
updateGui();
}
@Override
public synchronized void onPause() {
super.onPause();
disposable.clear();
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.nsclientinternal_restart:
rxBus.send(new EventNSClientRestart());
fabricPrivacy.logCustom("NSClientRestart");
break;
case R.id.nsclientinternal_delivernow:
nsClientPlugin.resend("GUI");
fabricPrivacy.logCustom("NSClientDeliverNow");
break;
case R.id.nsclientinternal_clearlog:
nsClientPlugin.clearLog();
break;
case R.id.nsclientinternal_clearqueue:
OKDialog.showConfirmation(getContext(), resourceHelper.gs(R.string.nsclientinternal), resourceHelper.gs(R.string.clearqueueconfirm), () -> {
uel.log(Action.NS_QUEUE_CLEARED);
uploadQueue.clearQueue();
updateGui();
fabricPrivacy.logCustom("NSClientClearQueue");
});
break;
case R.id.nsclientinternal_showqueue:
rxBus.send(new EventNSClientNewLog("QUEUE", uploadQueue.textList()));
break;
}
}
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
switch (buttonView.getId()) {
case R.id.nsclientinternal_paused:
uel.log(isChecked ? Action.NS_PAUSED : Action.NS_RESUME);
nsClientPlugin.pause(isChecked);
updateGui();
fabricPrivacy.logCustom("NSClientPause");
break;
case R.id.nsclientinternal_autoscroll:
sp.putBoolean(R.string.key_nsclientinternal_autoscroll, isChecked);
nsClientPlugin.autoscroll = isChecked;
updateGui();
break;
}
}
protected void updateGui() {
nsClientPlugin.updateLog();
pausedCheckbox.setChecked(sp.getBoolean(R.string.key_nsclientinternal_paused, false));
logTextView.setText(nsClientPlugin.textLog);
if (nsClientPlugin.autoscroll) {
logScrollview.fullScroll(ScrollView.FOCUS_DOWN);
}
urlTextView.setText(nsClientPlugin.url());
Spanned queuetext = HtmlHelper.INSTANCE.fromHtml(resourceHelper.gs(R.string.queue) + " <b>" + uploadQueue.size() + "</b>");
queueTextView.setText(queuetext);
statusTextView.setText(nsClientPlugin.status);
}
}

View file

@ -0,0 +1,121 @@
package info.nightscout.androidaps.plugins.general.nsclient
import android.graphics.Paint
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ScrollView
import dagger.android.support.DaggerFragment
import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.entities.UserEntry
import info.nightscout.androidaps.databinding.NsClientFragmentBinding
import info.nightscout.androidaps.interfaces.DataSyncSelector
import info.nightscout.androidaps.interfaces.UploadQueueAdminInterface
import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientNewLog
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientUpdateGUI
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.HtmlHelper.fromHtml
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.androidaps.utils.sharedPreferences.SP
import io.reactivex.disposables.CompositeDisposable
import javax.inject.Inject
class NSClientFragment : DaggerFragment() {
@Inject lateinit var nsClientPlugin: NSClientPlugin
@Inject lateinit var sp: SP
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var uploadQueue: UploadQueueAdminInterface
@Inject lateinit var fabricPrivacy: FabricPrivacy
@Inject lateinit var aapsSchedulers: AapsSchedulers
@Inject lateinit var dataSyncSelector: DataSyncSelector
@Inject lateinit var uel: UserEntryLogger
private val disposable = CompositeDisposable()
private var _binding: NsClientFragmentBinding? = null
// This property is only valid between onCreateView and
// onDestroyView.
private val binding get() = _binding!!
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
NsClientFragmentBinding.inflate(inflater, container, false).also { _binding = it }.root
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.autoscroll.isChecked = nsClientPlugin.autoscroll
binding.autoscroll.setOnCheckedChangeListener { _, isChecked ->
sp.putBoolean(R.string.key_nsclientinternal_autoscroll, isChecked)
nsClientPlugin.autoscroll = isChecked
updateGui()
}
binding.paused.isChecked = nsClientPlugin.paused
binding.paused.setOnCheckedChangeListener { _, isChecked ->
uel.log(if (isChecked) UserEntry.Action.NS_PAUSED else UserEntry.Action.NS_RESUME)
nsClientPlugin.pause(isChecked)
updateGui()
}
binding.clearLog.setOnClickListener { nsClientPlugin.clearLog() }
binding.clearLog.paintFlags = binding.clearLog.paintFlags or Paint.UNDERLINE_TEXT_FLAG
binding.restart.setOnClickListener { rxBus.send(EventNSClientRestart()) }
binding.restart.paintFlags = binding.restart.paintFlags or Paint.UNDERLINE_TEXT_FLAG
binding.deliverNow.setOnClickListener { nsClientPlugin.resend("GUI") }
binding.deliverNow.paintFlags = binding.deliverNow.paintFlags or Paint.UNDERLINE_TEXT_FLAG
binding.clearQueue.setOnClickListener {
context?.let { context ->
OKDialog.showConfirmation(context, resourceHelper.gs(R.string.nsclientinternal), resourceHelper.gs(R.string.clearqueueconfirm), Runnable {
uel.log(UserEntry.Action.NS_QUEUE_CLEARED)
uploadQueue.clearQueue()
updateGui()
})
}
}
binding.clearQueue.paintFlags = binding.clearQueue.paintFlags or Paint.UNDERLINE_TEXT_FLAG
binding.showQueue.setOnClickListener { rxBus.send(EventNSClientNewLog("QUEUE", uploadQueue.textList())) }
binding.showQueue.paintFlags = binding.showQueue.paintFlags or Paint.UNDERLINE_TEXT_FLAG
binding.fullSync.setOnClickListener {
context?.let { context ->
OKDialog.showConfirmation(context, resourceHelper.gs(R.string.nsclientinternal), resourceHelper.gs(R.string.full_sync), Runnable {
dataSyncSelector.resetToNextFullSync()
})
}
}
binding.fullSync.paintFlags = binding.fullSync.paintFlags or Paint.UNDERLINE_TEXT_FLAG
}
@Synchronized override fun onResume() {
super.onResume()
disposable.add(rxBus
.toObservable(EventNSClientUpdateGUI::class.java)
.observeOn(aapsSchedulers.main)
.subscribe({ updateGui() }, fabricPrivacy::logException)
)
updateGui()
}
@Synchronized override fun onPause() {
super.onPause()
disposable.clear()
}
private fun updateGui() {
if (_binding == null) return
nsClientPlugin.updateLog()
binding.paused.isChecked = sp.getBoolean(R.string.key_nsclientinternal_paused, false)
binding.log.text = nsClientPlugin.textLog
if (nsClientPlugin.autoscroll) binding.logScrollview.fullScroll(ScrollView.FOCUS_DOWN)
binding.url.text = nsClientPlugin.url()
binding.queue.text = fromHtml(resourceHelper.gs(R.string.queue) + " <b>" + uploadQueue.size() + "</b>")
binding.status.text = nsClientPlugin.status
}
}

View file

@ -32,7 +32,7 @@ import dagger.android.HasAndroidInjector;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.database.AppRepository;
import info.nightscout.androidaps.database.entities.TemporaryTarget;
import info.nightscout.androidaps.database.transactions.UpdateNsIdGlucoseValueTransaction;
import info.nightscout.androidaps.database.transactions.UpdateNsIdTemporaryTargetTransaction;
import info.nightscout.androidaps.db.DbRequest;
import info.nightscout.androidaps.events.EventAppExit;
@ -123,6 +123,7 @@ public class NSClientService extends DaggerService {
private final Integer nsHours = 48;
public long lastResendTime = 0;
public long lastAckTime = 0;
public long latestDateInReceivedData = 0;
@ -218,19 +219,38 @@ public class NSClientService extends DaggerService {
}
public void processAddAck(NSAddAck ack) {
lastAckTime = dateUtil._now();
// new room way
if (ack.getOriginalObject() instanceof TemporaryTarget) {
((TemporaryTarget) ack.getOriginalObject()).getInterfaceIDs().setNightscoutId(ack.getId());
if (ack.getOriginalObject() instanceof DataSyncSelector.PairTemporaryTarget) {
DataSyncSelector.PairTemporaryTarget pair = (DataSyncSelector.PairTemporaryTarget) ack.getOriginalObject();
pair.getValue().getInterfaceIDs().setNightscoutId(ack.getId());
disposable.add(repository.runTransactionForResult(new UpdateNsIdTemporaryTargetTransaction((TemporaryTarget) ack.getOriginalObject()))
disposable.add(repository.runTransactionForResult(new UpdateNsIdTemporaryTargetTransaction((pair.getValue())))
.observeOn(aapsSchedulers.getIo())
.subscribe(
result -> aapsLogger.debug(LTag.DATABASE, "Updated ns id of temporary target $originalObject"),
result -> aapsLogger.debug(LTag.DATABASE, "Updated ns id of temporary target " + pair.getValue()),
error -> aapsLogger.error(LTag.DATABASE, "Updated ns id of temporary target failed")
));
dataSyncSelector.confirmTempTargetsTimestampIfGreater(((TemporaryTarget) ack.getOriginalObject()).getDateCreated());
rxBus.send(new EventNSClientNewLog("DBADD", "Acked " + ack.nsClientID));
resend("AddAck");
dataSyncSelector.confirmTempTargetsTimestampIfGreater(pair.getUpdateRecordId());
rxBus.send(new EventNSClientNewLog("DBADD", "Acked " + pair.getValue().getInterfaceIDs().getNightscoutId()));
// Send new if waiting
dataSyncSelector.processChangedTempTargetsCompat();
return;
}
if (ack.getOriginalObject() instanceof DataSyncSelector.PairGlucoseValue) {
DataSyncSelector.PairGlucoseValue pair = (DataSyncSelector.PairGlucoseValue) ack.getOriginalObject();
pair.getValue().getInterfaceIDs().setNightscoutId(ack.getId());
disposable.add(repository.runTransactionForResult(new UpdateNsIdGlucoseValueTransaction(pair.getValue()))
.observeOn(aapsSchedulers.getIo())
.subscribe(
result -> aapsLogger.debug(LTag.DATABASE, "Updated ns id of glucose value " + pair.getValue()),
error -> aapsLogger.error(LTag.DATABASE, "Updated ns id of glucose value failed", error)
));
dataSyncSelector.confirmLastGlucoseValueIdIfGreater(pair.getUpdateRecordId());
rxBus.send(new EventNSClientNewLog("DBADD", "Acked " + pair.getValue().getInterfaceIDs().getNightscoutId()));
// Send new if waiting
dataSyncSelector.processChangedGlucoseValuesCompat();
return;
}
// old way
@ -243,11 +263,22 @@ public class NSClientService extends DaggerService {
}
public void processUpdateAck(NSUpdateAck ack) {
lastAckTime = dateUtil._now();
// new room way
if (ack.getOriginalObject() instanceof TemporaryTarget) {
dataSyncSelector.confirmTempTargetsTimestampIfGreater(((TemporaryTarget) ack.getOriginalObject()).getDateCreated());
if (ack.getOriginalObject() instanceof DataSyncSelector.PairTemporaryTarget) {
DataSyncSelector.PairTemporaryTarget pair = (DataSyncSelector.PairTemporaryTarget) ack.getOriginalObject();
dataSyncSelector.confirmTempTargetsTimestampIfGreater(pair.getUpdateRecordId());
rxBus.send(new EventNSClientNewLog("DBUPDATE/DBREMOVE", "Acked " + ack.get_id()));
resend("UpdateAck");
// Send new if waiting
dataSyncSelector.processChangedTempTargetsCompat();
return;
}
if (ack.getOriginalObject() instanceof DataSyncSelector.PairGlucoseValue) {
DataSyncSelector.PairGlucoseValue pair = (DataSyncSelector.PairGlucoseValue) ack.getOriginalObject();
dataSyncSelector.confirmLastGlucoseValueIdIfGreater(pair.getUpdateRecordId());
rxBus.send(new EventNSClientNewLog("DBUPDATE/DBREMOVE", "Acked " + ack.get_id()));
// Send new if waiting
dataSyncSelector.processChangedGlucoseValuesCompat();
return;
}
// old way
@ -736,7 +767,7 @@ public class NSClientService extends DaggerService {
message.put("_id", _id);
message.put("data", data);
mSocket.emit("dbUpdate", message, new NSUpdateAck("dbUpdate", _id, aapsLogger, rxBus, originalObject));
rxBus.send(new EventNSClientNewLog("DBUPDATE " + collection, "Sent " + originalObject.toString()));
rxBus.send(new EventNSClientNewLog("DBUPDATE " + collection, "Sent " + _id));
} catch (JSONException e) {
aapsLogger.error("Unhandled exception", e);
}
@ -788,7 +819,7 @@ public class NSClientService extends DaggerService {
message.put("collection", collection);
message.put("data", data);
mSocket.emit("dbAdd", message, new NSAddAck(aapsLogger, rxBus, originalObject));
rxBus.send(new EventNSClientNewLog("DBADD " + collection, "Sent " + originalObject.toString()));
rxBus.send(new EventNSClientNewLog("DBADD " + collection, "Sent " + data));
} catch (JSONException e) {
aapsLogger.error("Unhandled exception", e);
}
@ -806,20 +837,24 @@ public class NSClientService extends DaggerService {
handler.post(() -> {
if (mSocket == null || !mSocket.connected()) return;
// for room db I send record by record . this would make the process slow
// if (lastResendTime > System.currentTimeMillis() - 10 * 1000L) {
// aapsLogger.debug(LTag.NSCLIENT, "Skipping resend by lastResendTime: " + ((System.currentTimeMillis() - lastResendTime) / 1000L) + " sec");
// return;
// }
lastResendTime = System.currentTimeMillis();
rxBus.send(new EventNSClientNewLog("QUEUE", "Resend started: " + reason));
if (lastAckTime > System.currentTimeMillis() - 10 * 1000L) {
aapsLogger.debug(LTag.NSCLIENT, "Skipping resend by lastAckTime: " + ((System.currentTimeMillis() - lastAckTime) / 1000L) + " sec");
return;
}
if (dataSyncSelector.processChangedGlucoseValuesCompat()) return;
if (dataSyncSelector.processChangedTempTargetsCompat()) return;
if (uploadQueue.size() == 0)
return;
if (lastResendTime > System.currentTimeMillis() - 10 * 1000L) {
aapsLogger.debug(LTag.NSCLIENT, "Skipping resend by lastResendTime: " + ((System.currentTimeMillis() - lastResendTime) / 1000L) + " sec");
return;
}
lastResendTime = System.currentTimeMillis();
CloseableIterator<DbRequest> iterator;
int maxcount = 30;
try {

View file

@ -37,6 +37,7 @@ class DexcomPlugin @Inject constructor(
injector: HasAndroidInjector,
resourceHelper: ResourceHelper,
aapsLogger: AAPSLogger,
private val sp: SP,
private val dexcomMediator: DexcomMediator,
config: Config
) : PluginBase(PluginDescription()
@ -50,8 +51,6 @@ class DexcomPlugin @Inject constructor(
aapsLogger, resourceHelper, injector
), BgSourceInterface {
private val disposable = CompositeDisposable()
init {
if (!config.NSCLIENT) {
pluginDescription.setDefault()
@ -62,13 +61,18 @@ class DexcomPlugin @Inject constructor(
return true
}
override fun uploadToNs(glucoseValue: GlucoseValue): Boolean =
(glucoseValue.sourceSensor == GlucoseValue.SourceSensor.DEXCOM_G6_NATIVE ||
glucoseValue.sourceSensor == GlucoseValue.SourceSensor.DEXCOM_G5_NATIVE ||
glucoseValue.sourceSensor == GlucoseValue.SourceSensor.DEXCOM_NATIVE_UNKNOWN)
&& sp.getBoolean(R.string.key_dexcomg5_nsupload, false)
override fun onStart() {
super.onStart()
dexcomMediator.requestPermissionIfNeeded()
}
override fun onStop() {
disposable.clear()
super.onStop()
}
@ -138,37 +142,34 @@ class DexcomPlugin @Inject constructor(
} else {
null
}
dexcomPlugin.disposable += repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, calibrations, sensorStartTime)).subscribe({ result ->
result.inserted.forEach {
broadcastToXDrip(it)
if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false)) {
nsUpload.uploadBg(it, sourceSensor.text)
}
aapsLogger.debug(LTag.BGSOURCE, "Inserted bg $it")
repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, calibrations, sensorStartTime))
.doOnError {
aapsLogger.error(LTag.DATABASE, "Error while saving values from Dexcom App", it)
ret = Result.failure()
}
result.updated.forEach {
broadcastToXDrip(it)
if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false)) {
nsUpload.updateBg(it, sourceSensor.text)
.blockingGet()
.also { result ->
result.inserted.forEach {
broadcastToXDrip(it)
aapsLogger.debug(LTag.DATABASE, "Inserted bg $it")
}
aapsLogger.debug(LTag.BGSOURCE, "Updated bg $it")
}
result.sensorInsertionsInserted.forEach {
if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false)) {
nsUpload.uploadEvent(it)
result.updated.forEach {
broadcastToXDrip(it)
aapsLogger.debug(LTag.DATABASE, "Updated bg $it")
}
aapsLogger.debug(LTag.BGSOURCE, "Inserted sensor insertion $it")
}
result.calibrationsInserted.forEach {
if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false)) {
nsUpload.uploadEvent(it)
result.sensorInsertionsInserted.forEach {
if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false)) {
nsUpload.uploadEvent(it)
}
aapsLogger.debug(LTag.DATABASE, "Inserted sensor insertion $it")
}
result.calibrationsInserted.forEach {
if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false)) {
nsUpload.uploadEvent(it)
}
aapsLogger.debug(LTag.DATABASE, "Inserted calibration $it")
}
aapsLogger.debug(LTag.BGSOURCE, "Inserted calibration $it")
}
}, {
aapsLogger.error("Error while saving values from Dexcom App", it)
ret = Result.failure()
})
} catch (e: Exception) {
aapsLogger.error("Error while processing intent from Dexcom App", e)
ret = Result.failure()

View file

@ -30,7 +30,8 @@ import javax.inject.Singleton
class EversensePlugin @Inject constructor(
injector: HasAndroidInjector,
resourceHelper: ResourceHelper,
aapsLogger: AAPSLogger
aapsLogger: AAPSLogger,
private val sp: SP
) : PluginBase(PluginDescription()
.mainType(PluginType.BGSOURCE)
.fragmentClass(BGSourceFragment::class.java.name)
@ -44,6 +45,9 @@ class EversensePlugin @Inject constructor(
override var sensorBatteryLevel = -1
override fun uploadToNs(glucoseValue: GlucoseValue): Boolean =
glucoseValue.sourceSensor == GlucoseValue.SourceSensor.EVERSENSE && sp.getBoolean(R.string.key_dexcomg5_nsupload, false)
// cannot be inner class because of needed injection
class EversenseWorker(
context: Context,
@ -53,9 +57,8 @@ class EversensePlugin @Inject constructor(
@Inject lateinit var injector: HasAndroidInjector
@Inject lateinit var eversensePlugin: EversensePlugin
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var sp: SP
@Inject lateinit var nsUpload: NSUpload
@Inject lateinit var dateUtil: DateUtil
@Inject lateinit var nsUpload: NSUpload
@Inject lateinit var dataWorker: DataWorker
@Inject lateinit var repository: AppRepository
@Inject lateinit var broadcastToXDrip: XDripBroadcast
@ -109,16 +112,14 @@ class EversensePlugin @Inject constructor(
)
repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null))
.doOnError {
aapsLogger.error("Error while saving values from Eversense App", it)
aapsLogger.error(LTag.DATABASE, "Error while saving values from Eversense App", it)
ret = Result.failure()
}
.blockingGet()
.also { savedValues ->
savedValues.inserted.forEach {
broadcastToXDrip(it)
if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false))
nsUpload.uploadBg(it, GlucoseValue.SourceSensor.EVERSENSE.text)
aapsLogger.debug(LTag.BGSOURCE, "Inserted bg $it")
aapsLogger.debug(LTag.DATABASE, "Inserted bg $it")
}
}
}
@ -148,7 +149,7 @@ class EversensePlugin @Inject constructor(
.also { result ->
result.inserted.forEach {
nsUpload.uploadEvent(it)
aapsLogger.debug(LTag.DATABASE, "Inserted bg $it")
aapsLogger.debug(LTag.DATABASE, "Inserted therapy event $it")
}
}
}

View file

@ -14,7 +14,6 @@ import info.nightscout.androidaps.interfaces.PluginDescription
import info.nightscout.androidaps.interfaces.PluginType
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.utils.XDripBroadcast
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP
@ -25,7 +24,8 @@ import javax.inject.Singleton
class GlimpPlugin @Inject constructor(
injector: HasAndroidInjector,
resourceHelper: ResourceHelper,
aapsLogger: AAPSLogger
aapsLogger: AAPSLogger,
private val sp: SP
) : PluginBase(PluginDescription()
.mainType(PluginType.BGSOURCE)
.fragmentClass(BGSourceFragment::class.java.name)
@ -47,8 +47,6 @@ class GlimpPlugin @Inject constructor(
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var repository: AppRepository
@Inject lateinit var broadcastToXDrip: XDripBroadcast
@Inject lateinit var sp: SP
@Inject lateinit var nsUpload: NSUpload
init {
(context.applicationContext as HasAndroidInjector).androidInjector().inject(this)
@ -70,19 +68,21 @@ class GlimpPlugin @Inject constructor(
)
repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null))
.doOnError {
aapsLogger.error("Error while saving values from Glimp App", it)
aapsLogger.error(LTag.DATABASE, "Error while saving values from Glimp App", it)
ret = Result.failure()
}
.blockingGet()
.also { savedValues ->
savedValues.inserted.forEach {
broadcastToXDrip(it)
if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false))
nsUpload.uploadBg(it, GlucoseValue.SourceSensor.GLIMP.text)
aapsLogger.debug(LTag.BGSOURCE, "Inserted bg $it")
aapsLogger.debug(LTag.DATABASE, "Inserted bg $it")
}
}
return ret
}
}
override fun uploadToNs(glucoseValue: GlucoseValue): Boolean =
glucoseValue.sourceSensor == GlucoseValue.SourceSensor.GLIMP && sp.getBoolean(R.string.key_dexcomg5_nsupload, false)
}

View file

@ -14,7 +14,6 @@ import info.nightscout.androidaps.interfaces.PluginDescription
import info.nightscout.androidaps.interfaces.PluginType
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.receivers.DataWorker
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.XDripBroadcast
@ -29,7 +28,8 @@ import javax.inject.Singleton
class MM640gPlugin @Inject constructor(
injector: HasAndroidInjector,
resourceHelper: ResourceHelper,
aapsLogger: AAPSLogger
aapsLogger: AAPSLogger,
private val sp: SP
) : PluginBase(PluginDescription()
.mainType(PluginType.BGSOURCE)
.fragmentClass(BGSourceFragment::class.java.name)
@ -48,8 +48,6 @@ class MM640gPlugin @Inject constructor(
@Inject lateinit var mM640gPlugin: MM640gPlugin
@Inject lateinit var injector: HasAndroidInjector
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var sp: SP
@Inject lateinit var nsUpload: NSUpload
@Inject lateinit var dateUtil: DateUtil
@Inject lateinit var dataWorker: DataWorker
@Inject lateinit var repository: AppRepository
@ -88,18 +86,16 @@ class MM640gPlugin @Inject constructor(
}
repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null))
.doOnError {
aapsLogger.error("Error while saving values from Eversense App", it)
aapsLogger.error(LTag.DATABASE, "Error while saving values from Eversense App", it)
ret = Result.failure()
}
.blockingGet()
.also { savedValues ->
savedValues.all().forEach {
broadcastToXDrip(it)
if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false))
nsUpload.uploadBg(it, GlucoseValue.SourceSensor.MM_600_SERIES.text)
aapsLogger.debug(LTag.BGSOURCE, "Inserted bg $it")
savedValues.all().forEach {
broadcastToXDrip(it)
aapsLogger.debug(LTag.DATABASE, "Inserted bg $it")
}
}
}
} catch (e: JSONException) {
aapsLogger.error("Exception: ", e)
ret = Result.failure()
@ -109,4 +105,8 @@ class MM640gPlugin @Inject constructor(
return ret
}
}
override fun uploadToNs(glucoseValue: GlucoseValue): Boolean =
glucoseValue.sourceSensor == GlucoseValue.SourceSensor.MM_600_SERIES && sp.getBoolean(R.string.key_dexcomg5_nsupload, false)
}

View file

@ -17,7 +17,6 @@ import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.general.nsclient.NSClientPlugin
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.plugins.general.nsclient.data.NSSgv
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification
@ -61,6 +60,8 @@ class NSClientSourcePlugin @Inject constructor(
return isAdvancedFilteringEnabled
}
override fun uploadToNs(glucoseValue: GlucoseValue): Boolean = false
private fun detectSource(glucoseValue: GlucoseValue) {
if (glucoseValue.timestamp > lastBGTimeStamp) {
isAdvancedFilteringEnabled = arrayOf(
@ -85,7 +86,6 @@ class NSClientSourcePlugin @Inject constructor(
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var sp: SP
@Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var nsUpload: NSUpload
@Inject lateinit var dateUtil: DateUtil
@Inject lateinit var dataWorker: DataWorker
@Inject lateinit var repository: AppRepository
@ -103,7 +103,7 @@ class NSClientSourcePlugin @Inject constructor(
timestamp = sgv.mills ?: return null,
value = sgv.mgdl?.toDouble() ?: return null,
noise = null,
raw = sgv.filtered?.toDouble() ?: sgv.mgdl?.toDouble(),
raw = sgv.filtered?.toDouble() ?: sgv.mgdl?.toDouble(),
trendArrow = GlucoseValue.TrendArrow.fromString(sgv.direction),
nightscoutId = sgv.id,
sourceSensor = GlucoseValue.SourceSensor.fromString(sgv.device)
@ -140,7 +140,7 @@ class NSClientSourcePlugin @Inject constructor(
repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null, !nsClientSourcePlugin.isEnabled()))
.doOnError {
aapsLogger.error("Error while saving values from NSClient App", it)
aapsLogger.error(LTag.DATABASE, "Error while saving values from NSClient App", it)
ret = Result.failure()
}
.blockingGet()
@ -148,12 +148,12 @@ class NSClientSourcePlugin @Inject constructor(
result.updated.forEach {
broadcastToXDrip(it)
nsClientSourcePlugin.detectSource(it)
aapsLogger.debug(LTag.BGSOURCE, "Updated bg $it")
aapsLogger.debug(LTag.DATABASE, "Updated bg $it")
}
result.inserted.forEach {
broadcastToXDrip(it)
nsClientSourcePlugin.detectSource(it)
aapsLogger.debug(LTag.BGSOURCE, "Inserted bg $it")
aapsLogger.debug(LTag.DATABASE, "Inserted bg $it")
}
}
} catch (e: Exception) {

View file

@ -15,7 +15,6 @@ import info.nightscout.androidaps.interfaces.PluginDescription
import info.nightscout.androidaps.interfaces.PluginType
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.utils.JsonHelper.safeGetString
import info.nightscout.androidaps.utils.XDripBroadcast
import info.nightscout.androidaps.utils.resources.ResourceHelper
@ -29,7 +28,8 @@ import javax.inject.Singleton
class PoctechPlugin @Inject constructor(
injector: HasAndroidInjector,
resourceHelper: ResourceHelper,
aapsLogger: AAPSLogger
aapsLogger: AAPSLogger,
private val sp: SP
) : PluginBase(PluginDescription()
.mainType(PluginType.BGSOURCE)
.fragmentClass(BGSourceFragment::class.java.name)
@ -49,8 +49,6 @@ class PoctechPlugin @Inject constructor(
@Inject lateinit var injector: HasAndroidInjector
@Inject lateinit var poctechPlugin: PoctechPlugin
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var sp: SP
@Inject lateinit var nsUpload: NSUpload
@Inject lateinit var repository: AppRepository
@Inject lateinit var broadcastToXDrip: XDripBroadcast
@ -81,16 +79,14 @@ class PoctechPlugin @Inject constructor(
}
repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null))
.doOnError {
aapsLogger.error("Error while saving values from Poctech App", it)
aapsLogger.error(LTag.DATABASE, "Error while saving values from Poctech App", it)
ret = Result.failure()
}
.blockingGet()
.also { savedValues ->
savedValues.inserted.forEach {
broadcastToXDrip(it)
if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false))
nsUpload.uploadBg(it, GlucoseValue.SourceSensor.POCTECH_NATIVE.text)
aapsLogger.debug(LTag.BGSOURCE, "Inserted bg $it")
aapsLogger.debug(LTag.DATABASE, "Inserted bg $it")
}
}
} catch (e: JSONException) {
@ -100,4 +96,8 @@ class PoctechPlugin @Inject constructor(
return ret
}
}
override fun uploadToNs(glucoseValue: GlucoseValue): Boolean =
glucoseValue.sourceSensor == GlucoseValue.SourceSensor.POCTECH_NATIVE && sp.getBoolean(R.string.key_dexcomg5_nsupload, false)
}

View file

@ -13,7 +13,6 @@ import info.nightscout.androidaps.interfaces.PluginDescription
import info.nightscout.androidaps.interfaces.PluginType
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.T
@ -38,7 +37,6 @@ class RandomBgPlugin @Inject constructor(
private val virtualPumpPlugin: VirtualPumpPlugin,
private val buildHelper: BuildHelper,
private val sp: SP,
private val nsUpload: NSUpload,
private val dateUtil: DateUtil,
private val repository: AppRepository,
private val xDripBroadcast: XDripBroadcast
@ -74,6 +72,9 @@ class RandomBgPlugin @Inject constructor(
return true
}
override fun uploadToNs(glucoseValue: GlucoseValue): Boolean =
glucoseValue.sourceSensor == GlucoseValue.SourceSensor.RANDOM && sp.getBoolean(R.string.key_dexcomg5_nsupload, false)
override fun onStart() {
super.onStart()
loopHandler.postDelayed(refreshLoop, T.mins(interval).msecs())
@ -107,16 +108,13 @@ class RandomBgPlugin @Inject constructor(
trendArrow = GlucoseValue.TrendArrow.NONE,
sourceSensor = GlucoseValue.SourceSensor.RANDOM
)
disposable += repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null)).subscribe({ savedValues ->
savedValues.inserted.forEach {
xDripBroadcast(it)
if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false))
nsUpload.uploadBg(it, GlucoseValue.SourceSensor.RANDOM.text)
aapsLogger.debug(LTag.DATABASE, "Inserted bg $it")
}
}, {
aapsLogger.error(LTag.DATABASE, "Error while saving values from Random plugin", it)
})
aapsLogger.debug(LTag.DATABASE, "Generated BG: $bgMgdl ${Date()}")
disposable += repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null))
.subscribe({ savedValues ->
savedValues.inserted.forEach {
xDripBroadcast(it)
aapsLogger.debug(LTag.DATABASE, "Inserted bg $it")
}
}, { aapsLogger.error(LTag.DATABASE, "Error while saving values from Random plugin", it) }
)
}
}

View file

@ -25,7 +25,8 @@ import javax.inject.Singleton
class TomatoPlugin @Inject constructor(
injector: HasAndroidInjector,
resourceHelper: ResourceHelper,
aapsLogger: AAPSLogger
aapsLogger: AAPSLogger,
private val sp: SP
) : PluginBase(PluginDescription()
.mainType(PluginType.BGSOURCE)
.fragmentClass(BGSourceFragment::class.java.name)
@ -71,19 +72,21 @@ class TomatoPlugin @Inject constructor(
)
repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null))
.doOnError {
aapsLogger.error("Error while saving values from Tomato App", it)
aapsLogger.error(LTag.DATABASE, "Error while saving values from Tomato App", it)
ret = Result.failure()
}
.blockingGet()
.also { savedValues ->
savedValues.inserted.forEach {
broadcastToXDrip(it)
if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false))
nsUpload.uploadBg(it, GlucoseValue.SourceSensor.LIBRE_1_TOMATO.text)
aapsLogger.debug(LTag.BGSOURCE, "Inserted bg $it")
aapsLogger.debug(LTag.DATABASE, "Inserted bg $it")
}
}
return ret
}
}
override fun uploadToNs(glucoseValue: GlucoseValue): Boolean =
glucoseValue.sourceSensor == GlucoseValue.SourceSensor.LIBRE_1_TOMATO && sp.getBoolean(R.string.key_dexcomg5_nsupload, false)
}

View file

@ -37,6 +37,8 @@ class XdripPlugin @Inject constructor(
private var advancedFiltering = false
override var sensorBatteryLevel = -1
override fun uploadToNs(glucoseValue: GlucoseValue): Boolean = false
override fun advancedFilteringSupported(): Boolean {
return advancedFiltering
}
@ -87,14 +89,14 @@ class XdripPlugin @Inject constructor(
)
repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null))
.doOnError {
aapsLogger.error(LTag.DATABASE, "Error while saving values from Eversense App", it)
aapsLogger.error(LTag.DATABASE, "Error while saving values from Xdrip", it)
ret = Result.failure()
}
.blockingGet()
.also { savedValues ->
savedValues.all().forEach {
xdripPlugin.detectSource(it)
aapsLogger.debug(LTag.BGSOURCE, "Inserted bg $it")
aapsLogger.debug(LTag.DATABASE, "Inserted bg $it")
}
}
xdripPlugin.sensorBatteryLevel = bundle.getInt(Intents.EXTRA_SENSOR_BATTERY, -1)

View file

@ -626,7 +626,7 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
Treatment treatment = new Treatment();
treatment.date = detailedBolusInfo.timestamp;
treatment.source = (detailedBolusInfo.getPumpType() == PumpType.USER) ? Source.USER : Source.PUMP;
treatment.pumpId = detailedBolusInfo.getBolusPumpId();
treatment.pumpId = detailedBolusInfo.getBolusPumpId() != null ? detailedBolusInfo.getBolusPumpId() : 0;
treatment.insulin = detailedBolusInfo.insulin;
treatment.isValid = detailedBolusInfo.getBolusType() != DetailedBolusInfo.BolusType.PRIMING;
treatment.isSMB = detailedBolusInfo.getBolusType() == DetailedBolusInfo.BolusType.SMB;
@ -650,7 +650,7 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
Treatment carbsTreatment = new Treatment();
carbsTreatment.source = (detailedBolusInfo.getPumpType() == PumpType.USER) ? Source.USER : Source.PUMP;
carbsTreatment.pumpId = detailedBolusInfo.getCarbsPumpId(); // but this should never happen
carbsTreatment.pumpId = detailedBolusInfo.getCarbsPumpId() != null ? detailedBolusInfo.getCarbsPumpId() : 0; // but this should never happen
carbsTreatment.date = detailedBolusInfo.timestamp + detailedBolusInfo.carbTime * 60 * 1000L + 1000L; // add 1 sec to make them different records
carbsTreatment.carbs = detailedBolusInfo.carbs;

View file

@ -1,14 +1,10 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".plugins.general.nsclient.NSClientFragment">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
@ -24,11 +20,12 @@
android:text="@string/nsclientinternal_url" />
<TextView
android:id="@+id/nsclientinternal_url"
android:id="@+id/url"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:autoLink="web" />
android:autoLink="web"
tools:ignore="RtlHardcoded" />
</LinearLayout>
@ -42,18 +39,19 @@
android:gravity="center_horizontal">
<CheckBox
android:id="@+id/nsclientinternal_paused"
android:id="@+id/paused"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/paused" />
<CheckBox
android:id="@+id/nsclientinternal_autoscroll"
android:id="@+id/autoscroll"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginRight="10dp"
android:text="@string/nsclientinternal_autoscroll" />
android:text="@string/nsclientinternal_autoscroll"
tools:ignore="RtlHardcoded" />
</LinearLayout>
@ -68,21 +66,23 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="5dp"
android:text="@string/status" />
android:text="@string/status"
tools:ignore="RtlHardcoded" />
<TextView
android:id="@+id/nsclientinternal_status"
android:id="@+id/status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="normal|bold" />
<TextView
android:id="@+id/nsclientinternal_queue"
android:id="@+id/queue"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginRight="5dp"
android:text="@string/queue"
android:textAlignment="viewEnd" />
android:textAlignment="viewEnd"
tools:ignore="RtlHardcoded" />
</LinearLayout>
@ -96,7 +96,7 @@
android:layout_marginTop="10dp">
<TextView
android:id="@+id/nsclientinternal_clearlog"
android:id="@+id/clear_log"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
@ -106,7 +106,7 @@
android:textStyle="normal|bold" />
<TextView
android:id="@+id/nsclientinternal_restart"
android:id="@+id/restart"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
@ -116,7 +116,7 @@
android:textStyle="normal|bold" />
<TextView
android:id="@+id/nsclientinternal_delivernow"
android:id="@+id/deliver_now"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
@ -126,7 +126,7 @@
android:textStyle="normal|bold" />
<TextView
android:id="@+id/nsclientinternal_clearqueue"
android:id="@+id/clear_queue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
@ -136,7 +136,7 @@
android:textStyle="normal|bold" />
<TextView
android:id="@+id/nsclientinternal_showqueue"
android:id="@+id/show_queue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
@ -145,23 +145,30 @@
android:textColor="@android:color/holo_orange_light"
android:textStyle="normal|bold" />
<TextView
android:id="@+id/full_sync"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/full_sync"
android:textAlignment="center"
android:textColor="@android:color/holo_orange_light"
android:textStyle="normal|bold" />
</LinearLayout>
<ScrollView
android:id="@+id/nsclientinternal_logscrollview"
android:id="@+id/log_scrollview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp">
<TextView
android:id="@+id/nsclientinternal_log"
android:id="@+id/log"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="" />
</ScrollView>
</LinearLayout>
</FrameLayout>
</LinearLayout>

View file

@ -34,6 +34,7 @@
<string name="key_absorption_category_settings" translatable="false">absorption_category_settings</string>
<string name="key_insulin_oref_peak_settings" translatable="false">insulin_oref_peak_settings</string>
<string name="key_ns_temporary_target_last_sync" translatable="false">ns_temporary_target_last_sync</string>
<string name="key_ns_glucose_value_last_sync" translatable="false">ns_glucose_value_last_sync</string>
<string name="treatmentssafety_title">Treatments safety</string>
<string name="treatmentssafety_maxbolus_title">Max allowed bolus [U]</string>
@ -1127,6 +1128,7 @@
<string name="profile_max_daily_basal_value">Maximal profile basal value</string>
<string name="current_basal_value">Current basal value</string>
<string name="profile_carbs_ratio_value">Profile carbs ratio value</string>
<string name="full_sync">Full sync</string>
</resources>

View file

@ -1,5 +1,7 @@
package info.nightscout.androidaps.interfaces
import info.nightscout.androidaps.database.entities.GlucoseValue
/**
* Created by mike on 20.06.2016.
*/
@ -8,4 +10,5 @@ interface BgSourceInterface {
fun advancedFilteringSupported(): Boolean = false
val sensorBatteryLevel: Int
get() = -1
fun uploadToNs(glucoseValue: GlucoseValue) : Boolean
}

View file

@ -1,16 +1,24 @@
package info.nightscout.androidaps.interfaces
import info.nightscout.androidaps.database.entities.GlucoseValue
import info.nightscout.androidaps.database.entities.TemporaryTarget
import info.nightscout.androidaps.db.DbRequest
interface DataSyncSelector {
data class PairTemporaryTarget(val value: TemporaryTarget, val updateRecordId: Long)
data class PairGlucoseValue(val value: GlucoseValue, val updateRecordId: Long)
fun resetToNextFullSync()
fun confirmTempTargetsTimestamp(lastSynced: Long)
fun confirmTempTargetsTimestampIfGreater(lastSynced: Long)
fun changedTempTargets() : List<TemporaryTarget>
// Until NS v3
fun processChangedTempTargetsCompat(): Boolean
fun confirmLastGlucoseValueId(lastSynced: Long)
fun confirmLastGlucoseValueIdIfGreater(lastSynced: Long)
fun changedGlucoseValues() : List<GlucoseValue>
// Until NS v3
fun processChangedGlucoseValuesCompat(): Boolean
}

View file

@ -434,38 +434,6 @@ public class NSUpload {
uploadQueue.add(new DbRequest("dbAdd", "treatments", data, date.getTime()));
}
public void uploadBg(GlucoseValue reading, String source) {
JSONObject data = new JSONObject();
try {
data.put("device", source);
data.put("date", reading.getTimestamp());
data.put("dateString", DateUtil.toISOString(reading.getTimestamp()));
data.put("sgv", reading.getValue());
data.put("direction", reading.getTrendArrow().getText());
data.put("type", "sgv");
} catch (JSONException e) {
aapsLogger.error("Unhandled exception", e);
}
uploadQueue.add(new DbRequest("dbAdd", "entries", data, reading.getTimestamp()));
}
public void updateBg(GlucoseValue reading, String source) {
JSONObject data = new JSONObject();
try {
data.put("device", source);
data.put("date", reading.getTimestamp());
data.put("dateString", DateUtil.toISOString(reading.getTimestamp()));
data.put("sgv", reading.getValue());
data.put("direction", reading.getTrendArrow().getText());
data.put("type", "sgv");
if (reading.getInterfaceIDs().getNightscoutId() != null) {
uploadQueue.add(new DbRequest("dbUpdate", "entries", reading.getInterfaceIDs().getNightscoutId(), data, System.currentTimeMillis()));
}
} catch (JSONException e) {
aapsLogger.error("Unhandled exception", e);
}
}
public void uploadAppStart() {
if (sp.getBoolean(R.string.key_ns_logappstartedevent, true)) {
JSONObject data = new JSONObject();

View file

@ -0,0 +1,15 @@
package info.nightscout.androidaps.utils.extensions
import info.nightscout.androidaps.database.entities.GlucoseValue
import info.nightscout.androidaps.utils.DateUtil
import org.json.JSONObject
fun GlucoseValue.toJson() : JSONObject =
JSONObject()
.put("device", sourceSensor.text)
.put("date", timestamp)
.put("dateString", DateUtil.toISOString(timestamp))
.put("sgv", value)
.put("direction", trendArrow.text)
.put("type", "sgv")
.put("NSCLIENT_ID", System.currentTimeMillis()) // Fake to be accepted by WS

View file

@ -75,6 +75,25 @@ open class AppRepository @Inject internal constructor(
database.glucoseValueDao.getModifiedFrom(lastId)
.subscribeOn(Schedulers.io())
/*
* returns a Pair of the next entity to sync and the ID of the "update".
* The update id might either be the entry id itself if it is a new entry - or the id
* of the update ("historic") entry. The sync counter should be incremented to that id if it was synced successfully.
*
* It is a Maybe as there might be no next element.
* */
fun getNextSyncElementGlucoseValue(id: Long): Maybe<Pair<GlucoseValue, Long>> =
database.glucoseValueDao.getNextModifiedOrNewAfter(id)
.flatMap { nextIdElement ->
val nextIdElemReferenceId = nextIdElement.referenceId
if (nextIdElemReferenceId == null) {
Maybe.just(nextIdElement to nextIdElement.id)
} else {
database.glucoseValueDao.getCurrentFromHistoric(nextIdElemReferenceId)
.map { it to nextIdElement.id}
}
}
fun getBgReadingsCorrespondingLastHistoryRecord(lastId: Long): GlucoseValue? =
database.glucoseValueDao.getLastHistoryRecord(lastId)
@ -84,6 +103,25 @@ open class AppRepository @Inject internal constructor(
.subscribeOn(Schedulers.io())
// TEMP TARGETS
/*
* returns a Pair of the next entity to sync and the ID of the "update".
* The update id might either be the entry id itself if it is a new entry - or the id
* of the update ("historic") entry. The sync counter should be incremented to that id if it was synced successfully.
*
* It is a Maybe as there might be no next element.
* */
fun getNextSyncElementTemporaryTarget(id: Long): Maybe<Pair<TemporaryTarget, Long>> =
database.temporaryTargetDao.getNextModifiedOrNewAfter(id)
.flatMap { nextIdElement ->
val nextIdElemReferenceId = nextIdElement.referenceId
if (nextIdElemReferenceId == null) {
Maybe.just(nextIdElement to nextIdElement.id)
} else {
database.temporaryTargetDao.getCurrentFromHistoric(nextIdElemReferenceId)
.map { it to nextIdElement.id}
}
}
fun compatGetTemporaryTargetData(): Single<List<TemporaryTarget>> =
database.temporaryTargetDao.getTemporaryTargetData()
.subscribeOn(Schedulers.io())
@ -93,21 +131,11 @@ open class AppRepository @Inject internal constructor(
.map { if (!ascending) it.reversed() else it }
.subscribeOn(Schedulers.io())
fun getAllChangedTemporaryTargetsFromTime(timestamp: Long, amount: Int): Single<List<TemporaryTarget>> =
database.temporaryTargetDao.getAllChangedFromTime(timestamp, amount)
.subscribeOn(Schedulers.io())
fun getTemporaryTargetDataIncludingInvalidFromTime(timestamp: Long, ascending: Boolean): Single<List<TemporaryTarget>> =
database.temporaryTargetDao.getTemporaryTargetDataIncludingInvalidFromTime(timestamp)
.map { if (!ascending) it.reversed() else it }
.subscribeOn(Schedulers.io())
fun findTemporaryTargetByNSIdSingle(nsId: String): TemporaryTarget? =
database.temporaryTargetDao.findByNSId(nsId)
fun findTemporaryTargetByTimestamp(timestamp: Long): TemporaryTarget? =
database.temporaryTargetDao.findByTimestamp(timestamp)
fun getModifiedTemporaryTargetsDataFromId(lastId: Long): Single<List<TemporaryTarget>> =
database.temporaryTargetDao.getModifiedFrom(lastId)
.subscribeOn(Schedulers.io())

View file

@ -37,6 +37,14 @@ internal interface GlucoseValueDao : TraceableDao<GlucoseValue> {
@Query("SELECT * FROM $TABLE_GLUCOSE_VALUES WHERE referenceId = :id ORDER BY id DESC LIMIT 1")
fun getLastHistoryRecord(id: Long): GlucoseValue?
// This query will be used with v3 to get all changed records
@Query("SELECT * FROM $TABLE_GLUCOSE_VALUES WHERE id > :id AND referenceId IS NULL OR id IN (SELECT DISTINCT referenceId FROM $TABLE_GLUCOSE_VALUES WHERE id > :id) ORDER BY id ASC")
fun getModifiedFrom(id: Long): Single<List<GlucoseValue>>
// for WS we need 1 record only
@Query("SELECT * FROM $TABLE_GLUCOSE_VALUES WHERE id > :id ORDER BY id ASC limit 1")
fun getNextModifiedOrNewAfter(id: Long): Maybe<GlucoseValue>
@Query("SELECT * FROM $TABLE_GLUCOSE_VALUES WHERE id = :referenceId")
fun getCurrentFromHistoric(referenceId: Long): Maybe<GlucoseValue>
}

View file

@ -17,15 +17,9 @@ internal interface TemporaryTargetDao : TraceableDao<TemporaryTarget> {
@Query("DELETE FROM $TABLE_TEMPORARY_TARGETS")
override fun deleteAllEntries()
@Query("SELECT * FROM $TABLE_TEMPORARY_TARGETS WHERE dateCreated > :timestamp AND referenceId IS NULL ORDER BY timestamp ASC LIMIT :amount")
fun getAllChangedFromTime(timestamp: Long, amount: Int): Single<List<TemporaryTarget>>
@Query("SELECT * FROM $TABLE_TEMPORARY_TARGETS WHERE nightscoutId = :nsId AND referenceId IS NULL")
fun findByNSId(nsId: String): TemporaryTarget?
@Query("SELECT * FROM $TABLE_TEMPORARY_TARGETS WHERE timestamp = :timestamp AND referenceId IS NULL")
fun findByTimestamp(timestamp: Long): TemporaryTarget?
@Query("SELECT * FROM $TABLE_TEMPORARY_TARGETS WHERE timestamp <= :timestamp AND (timestamp + duration) > :timestamp AND referenceId IS NULL AND isValid = 1 ORDER BY timestamp DESC LIMIT 1")
fun getTemporaryTargetActiveAt(timestamp: Long): Maybe<TemporaryTarget>
@ -41,6 +35,14 @@ internal interface TemporaryTargetDao : TraceableDao<TemporaryTarget> {
@Query("SELECT * FROM $TABLE_TEMPORARY_TARGETS WHERE referenceId = :id ORDER BY id DESC LIMIT 1")
fun getLastHistoryRecord(id: Long): TemporaryTarget?
// This query will be used with v3 to get all changed records
@Query("SELECT * FROM $TABLE_TEMPORARY_TARGETS WHERE id > :id AND referenceId IS NULL OR id IN (SELECT DISTINCT referenceId FROM $TABLE_TEMPORARY_TARGETS WHERE id > :id) ORDER BY id ASC")
fun getModifiedFrom(id: Long): Single<List<TemporaryTarget>>
// for WS we need 1 record only
@Query("SELECT * FROM $TABLE_TEMPORARY_TARGETS WHERE id > :id ORDER BY id ASC limit 1")
fun getNextModifiedOrNewAfter(id: Long): Maybe<TemporaryTarget>
@Query("SELECT * FROM $TABLE_TEMPORARY_TARGETS WHERE id = :referenceId")
fun getCurrentFromHistoric(referenceId: Long): Maybe<TemporaryTarget>
}

View file

@ -0,0 +1,12 @@
package info.nightscout.androidaps.database.transactions
import info.nightscout.androidaps.database.entities.GlucoseValue
class UpdateNsIdGlucoseValueTransaction(val glucoseValue: GlucoseValue) : Transaction<Unit>() {
override fun run() {
val current = database.glucoseValueDao.findById(glucoseValue.id)
if (current != null && current.interfaceIDs.nightscoutId != glucoseValue.interfaceIDs.nightscoutId)
database.glucoseValueDao.updateExistingEntry(glucoseValue)
}
}