DataWorker, NSDeviceStatus -> kt

This commit is contained in:
Milos Kozak 2021-03-20 12:30:57 +01:00
parent 8be3ccc989
commit e53c91fc58
22 changed files with 617 additions and 722 deletions

View file

@ -105,11 +105,8 @@ class MainApp : DaggerApplication() {
filter.addAction(Intents.ACTION_NEW_TREATMENT) filter.addAction(Intents.ACTION_NEW_TREATMENT)
filter.addAction(Intents.ACTION_CHANGED_TREATMENT) filter.addAction(Intents.ACTION_CHANGED_TREATMENT)
filter.addAction(Intents.ACTION_REMOVED_TREATMENT) filter.addAction(Intents.ACTION_REMOVED_TREATMENT)
filter.addAction(Intents.ACTION_NEW_SGV)
filter.addAction(Intents.ACTION_NEW_PROFILE)
filter.addAction(Intents.ACTION_NEW_MBG) filter.addAction(Intents.ACTION_NEW_MBG)
filter.addAction(Intents.ACTION_NEW_CAL) filter.addAction(Intents.ACTION_NEW_CAL)
filter.addAction(Intents.ACTION_FOOD)
LocalBroadcastManager.getInstance(this).registerReceiver(DataReceiver(), filter) LocalBroadcastManager.getInstance(this).registerReceiver(DataReceiver(), filter)
filter = IntentFilter() filter = IntentFilter()
filter.addAction(Intent.ACTION_TIME_CHANGED) filter.addAction(Intent.ACTION_TIME_CHANGED)

View file

@ -163,7 +163,7 @@ class DataBroadcastPlugin @Inject constructor(
bundle.putString("enacted", loopPlugin.lastRun?.request?.json().toString()) bundle.putString("enacted", loopPlugin.lastRun?.request?.json().toString())
} }
} else { //NSClient or remote } else { //NSClient or remote
val data = NSDeviceStatus.deviceStatusOpenAPSData val data = nsDeviceStatus.deviceStatusOpenAPSData
if (data.clockSuggested != 0L && data.suggested != null) { if (data.clockSuggested != 0L && data.suggested != null) {
bundle.putLong("suggestedTimeStamp", data.clockSuggested) bundle.putLong("suggestedTimeStamp", data.clockSuggested)
bundle.putString("suggested", data.suggested.toString()) bundle.putString("suggested", data.suggested.toString())

View file

@ -13,8 +13,7 @@ import info.nightscout.androidaps.interfaces.PluginDescription
import info.nightscout.androidaps.interfaces.PluginType import info.nightscout.androidaps.interfaces.PluginType
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.receivers.BundleStore import info.nightscout.androidaps.receivers.DataWorker
import info.nightscout.androidaps.receivers.DataReceiver
import info.nightscout.androidaps.utils.JsonHelper import info.nightscout.androidaps.utils.JsonHelper
import info.nightscout.androidaps.utils.extensions.foodFromJson import info.nightscout.androidaps.utils.extensions.foodFromJson
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
@ -49,21 +48,19 @@ class FoodPlugin @Inject constructor(
@Inject lateinit var aapsLogger: AAPSLogger @Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var repository: AppRepository @Inject lateinit var repository: AppRepository
@Inject lateinit var sp: SP @Inject lateinit var sp: SP
@Inject lateinit var bundleStore: BundleStore @Inject lateinit var dataWorker: DataWorker
init { init {
(context.applicationContext as HasAndroidInjector).androidInjector().inject(this) (context.applicationContext as HasAndroidInjector).androidInjector().inject(this)
} }
override fun doWork(): Result { override fun doWork(): Result {
aapsLogger.debug(LTag.DATAFOOD, "Received Food Data: $inputData}") val foods = dataWorker.pickupJSONArray(inputData.getLong(DataWorker.STORE_KEY, -1))
val bundle = bundleStore.pickup(inputData.getLong(DataReceiver.STORE_KEY, -1))
?: return Result.failure() ?: return Result.failure()
aapsLogger.debug(LTag.DATAFOOD, "Received Food Data: $foods")
var ret = Result.success() var ret = Result.success()
val foodsString = bundle.getString("foods") ?: return Result.failure()
val foods = JSONArray(foodsString)
for (index in 0 until foods.length()) { for (index in 0 until foods.length()) {
val jsonFood: JSONObject = foods.getJSONObject(index) val jsonFood: JSONObject = foods.getJSONObject(index)

View file

@ -433,7 +433,7 @@ public class NSClientPlugin extends PluginBase {
// room Therapy Event // room Therapy Event
TherapyEvent therapyEvent = therapyEventFromNsIdForInvalidating(_id); TherapyEvent therapyEvent = therapyEventFromNsIdForInvalidating(_id);
disposable.add(repository.runTransactionForResult(new SyncTherapyEventTransaction(therapyEvent)).subscribe( disposable.add(repository.runTransactionForResult(new SyncTherapyEventTransaction(therapyEvent)).subscribe(
result -> result.getInvalidated().forEach(record -> uel.log(Action.CAREPORTAL_DELETED_FROM_NS, record.getNote() , new ValueWithUnit(record.getTimestamp(), Units.Timestamp, true), new ValueWithUnit(record.getType().getText(), Units.TherapyEvent))), result -> result.getInvalidated().forEach(record -> uel.log(Action.CAREPORTAL_DELETED_FROM_NS, record.getNote() != null ? record.getNote() : "" , new ValueWithUnit(record.getTimestamp(), Units.Timestamp, true), new ValueWithUnit(record.getType().getText(), Units.TherapyEvent))),
error -> aapsLogger.error(LTag.DATABASE, "Error while removing therapy event", error))); error -> aapsLogger.error(LTag.DATABASE, "Error while removing therapy event", error)));
// new DB model // new DB model
EventNsTreatment evtTreatment = new EventNsTreatment(EventNsTreatment.Companion.getREMOVE(), json); EventNsTreatment evtTreatment = new EventNsTreatment(EventNsTreatment.Companion.getREMOVE(), json);
@ -493,8 +493,8 @@ public class NSClientPlugin extends PluginBase {
disposable.add(repository.runTransactionForResult(new SyncTherapyEventTransaction(therapyEvent)) disposable.add(repository.runTransactionForResult(new SyncTherapyEventTransaction(therapyEvent))
.subscribe( .subscribe(
result -> { result -> {
result.getInserted().forEach(record -> uel.log(Action.CAREPORTAL_FROM_NS, record.getNote() , new ValueWithUnit(record.getTimestamp(), Units.Timestamp, true), new ValueWithUnit(record.getType().getText(), Units.TherapyEvent))); result.getInserted().forEach(record -> uel.log(Action.CAREPORTAL_FROM_NS, record.getNote() != null ? record.getNote() : "", new ValueWithUnit(record.getTimestamp(), Units.Timestamp, true), new ValueWithUnit(record.getType().getText(), Units.TherapyEvent)));
result.getInvalidated().forEach(record -> uel.log(Action.CAREPORTAL_DELETED_FROM_NS, record.getNote() , new ValueWithUnit(record.getTimestamp(), Units.Timestamp, true), new ValueWithUnit(record.getType().getText(), Units.TherapyEvent))); result.getInvalidated().forEach(record -> uel.log(Action.CAREPORTAL_DELETED_FROM_NS, record.getNote() != null ? record.getNote() : "" , new ValueWithUnit(record.getTimestamp(), Units.Timestamp, true), new ValueWithUnit(record.getType().getText(), Units.TherapyEvent)));
}, },
error -> aapsLogger.error(LTag.DATABASE, "Error while saving therapy event", error))); error -> aapsLogger.error(LTag.DATABASE, "Error while saving therapy event", error)));
} else { } else {

View file

@ -7,13 +7,10 @@ import androidx.annotation.NonNull;
import androidx.work.Worker; import androidx.work.Worker;
import androidx.work.WorkerParameters; import androidx.work.WorkerParameters;
import androidx.annotation.NonNull;
import javax.inject.Inject; import javax.inject.Inject;
import dagger.android.HasAndroidInjector; import dagger.android.HasAndroidInjector;
import info.nightscout.androidaps.receivers.BundleStore; import info.nightscout.androidaps.receivers.DataWorker;
import info.nightscout.androidaps.receivers.DataReceiver;
// cannot be inner class because of needed injection // cannot be inner class because of needed injection
public class NSClientWorker extends Worker { public class NSClientWorker extends Worker {
@ -26,14 +23,14 @@ public class NSClientWorker extends Worker {
} }
@Inject NSClientPlugin nsClientPlugin; @Inject NSClientPlugin nsClientPlugin;
@Inject BundleStore bundleStore; @Inject DataWorker dataWorker;
@NonNull @NonNull
@Override @Override
public Result doWork() { public Result doWork() {
Bundle bundle = bundleStore.pickup(getInputData().getLong(DataReceiver.STORE_KEY, -1)); Bundle bundle = dataWorker.pickupBundle(getInputData().getLong(DataWorker.STORE_KEY, -1));
if (bundle == null) return Result.failure(); if (bundle == null) return Result.failure();
String action = getInputData().getString(DataReceiver.ACTION_KEY); String action = getInputData().getString(DataWorker.ACTION_KEY);
nsClientPlugin.handleNewDataFromNSClient(action, bundle); nsClientPlugin.handleNewDataFromNSClient(action, bundle);
return Result.success(); return Result.success();
} }

View file

@ -1,481 +0,0 @@
package info.nightscout.androidaps.plugins.general.nsclient.data;
import android.text.Spanned;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.inject.Inject;
import javax.inject.Singleton;
import dagger.android.HasAndroidInjector;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.interfaces.ConfigInterface;
import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.logging.LTag;
import info.nightscout.androidaps.plugins.aps.loop.APSResult;
import info.nightscout.androidaps.plugins.configBuilder.RunningConfiguration;
import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.HtmlHelper;
import info.nightscout.androidaps.utils.Round;
import info.nightscout.androidaps.utils.resources.ResourceHelper;
import info.nightscout.androidaps.utils.sharedPreferences.SP;
/**
* Created by mike on 25.06.2017.
*/
/*
{
"_id": "594fdcec327b83c81b6b8c0f",
"device": "openaps://Sony D5803",
"pump": {
"battery": {
"percent": 100
},
"status": {
"status": "normal",
"timestamp": "2017-06-25T15:50:14Z"
},
"extended": {
"Version": "1.5-ac98852-2017.06.25",
"PumpIOB": 1.13,
"LastBolus": "25. 6. 2017 17:25:00",
"LastBolusAmount": 0.3,
"BaseBasalRate": 0.4,
"ActiveProfile": "2016 +30%"
},
"reservoir": 109,
"clock": "2017-06-25T15:55:10Z"
},
"openaps": {
"suggested": {
"temp": "absolute",
"bg": 115.9,
"tick": "+5",
"eventualBG": 105,
"snoozeBG": 105,
"predBGs": {
"IOB": [116, 114, 112, 110, 109, 107, 106, 105, 105, 104, 104, 104, 104, 104, 104, 104, 104, 105, 105, 105, 105, 105, 106, 106, 106, 106, 106, 107]
},
"COB": 0,
"IOB": -0.035,
"reason": "COB: 0, Dev: -18, BGI: 0.43, ISF: 216, Target: 99; Eventual BG 105 > 99 but Min. Delta -2.60 < Exp. Delta 0.1; setting current basal of 0.4 as temp. Suggested rate is same as profile rate, no temp basal is active, doing nothing",
"timestamp": "2017-06-25T15:55:10Z"
},
"iob": {
"iob": -0.035,
"basaliob": -0.035,
"activity": -0.0004,
"time": "2017-06-25T15:55:10Z"
}
},
"uploaderBattery": 93,
"created_at": "2017-06-25T15:55:10Z",
"NSCLIENT_ID": 1498406118857
}
*/
@Singleton
public class NSDeviceStatus {
private final AAPSLogger aapsLogger;
private final SP sp;
private final ResourceHelper resourceHelper;
private final NSSettingsStatus nsSettingsStatus;
private final ConfigInterface config;
private final RunningConfiguration runningConfiguration;
private JSONObject data = null;
@Inject
public NSDeviceStatus(
AAPSLogger aapsLogger,
SP sp,
ResourceHelper resourceHelper,
NSSettingsStatus nsSettingsStatus,
ConfigInterface config,
RunningConfiguration runningConfiguration
) {
this.aapsLogger = aapsLogger;
this.sp = sp;
this.resourceHelper = resourceHelper;
this.nsSettingsStatus = nsSettingsStatus;
this.config = config;
this.runningConfiguration = runningConfiguration;
}
public void handleNewData(JSONArray devicestatuses) {
aapsLogger.debug(LTag.NSCLIENT, "Got NS devicestatus: $devicestatuses}");
for (int i = 0; i < devicestatuses.length(); i++) {
try {
JSONObject devicestatusJson = devicestatuses.getJSONObject(i);
if (devicestatusJson != null) {
setData(devicestatusJson);
if (devicestatusJson.has("pump")) {
// Objectives 0
sp.putBoolean(R.string.key_ObjectivespumpStatusIsAvailableInNS, true);
}
if (devicestatusJson.has("configuration") && config.getNSCLIENT()) {
// copy configuration of Insulin and Sensitivity from main AAPS
runningConfiguration.apply(devicestatusJson.getJSONObject("configuration"));
}
}
} catch (JSONException jsonException) {
jsonException.printStackTrace();
}
}
}
public NSDeviceStatus setData(JSONObject obj) {
this.data = obj;
updatePumpData();
updateOpenApsData(obj);
updateUploaderData(obj);
return this;
}
public String getDevice() {
try {
if (data.has("device")) {
String device = data.getString("device");
if (device.startsWith("openaps://")) {
device = device.substring(10);
return device;
}
}
} catch (JSONException e) {
aapsLogger.error("Unhandled exception", e);
}
return "";
}
public static class Levels {
static int URGENT = 2;
static int WARN = 1;
static int INFO = 0;
int LOW = -1;
int LOWEST = -2;
static int NONE = -3;
}
// ***** PUMP DATA ******
private DeviceStatusPumpData deviceStatusPumpData = null;
public Spanned getExtendedPumpStatus() {
if (deviceStatusPumpData != null && deviceStatusPumpData.extended != null)
return deviceStatusPumpData.extended;
return HtmlHelper.INSTANCE.fromHtml("");
}
public Spanned getPumpStatus() {
//String[] ALL_STATUS_FIELDS = {"reservoir", "battery", "clock", "status", "device"};
StringBuilder string = new StringBuilder();
string.append("<span style=\"color:" + resourceHelper.gcs(R.color.defaulttext) + "\">");
string.append(resourceHelper.gs(R.string.pump));
string.append(": </span>");
if (deviceStatusPumpData == null)
return HtmlHelper.INSTANCE.fromHtml("");
// test warning level
int level = Levels.INFO;
long now = System.currentTimeMillis();
if (deviceStatusPumpData.clock + nsSettingsStatus.extendedPumpSettings("urgentClock") * 60 * 1000L < now)
level = Levels.URGENT;
else if (deviceStatusPumpData.reservoir < nsSettingsStatus.extendedPumpSettings("urgentRes"))
level = Levels.URGENT;
else if (deviceStatusPumpData.isPercent && deviceStatusPumpData.percent < nsSettingsStatus.extendedPumpSettings("urgentBattP"))
level = Levels.URGENT;
else if (!deviceStatusPumpData.isPercent && deviceStatusPumpData.voltage < nsSettingsStatus.extendedPumpSettings("urgentBattV"))
level = Levels.URGENT;
else if (deviceStatusPumpData.clock + nsSettingsStatus.extendedPumpSettings("warnClock") * 60 * 1000L < now)
level = Levels.WARN;
else if (deviceStatusPumpData.reservoir < nsSettingsStatus.extendedPumpSettings("warnRes"))
level = Levels.WARN;
else if (deviceStatusPumpData.isPercent && deviceStatusPumpData.percent < nsSettingsStatus.extendedPumpSettings("warnBattP"))
level = Levels.WARN;
else if (!deviceStatusPumpData.isPercent && deviceStatusPumpData.voltage < nsSettingsStatus.extendedPumpSettings("warnBattV"))
level = Levels.WARN;
string.append("<span style=\"color:");
if (level == Levels.INFO) string.append("white\">");
if (level == Levels.WARN) string.append("yellow\">");
if (level == Levels.URGENT) string.append("red\">");
String fields = nsSettingsStatus.pumpExtendedSettingsFields();
if (fields.contains("reservoir")) {
string.append((int) deviceStatusPumpData.reservoir).append("U ");
}
if (fields.contains("battery") && deviceStatusPumpData.isPercent) {
string.append(deviceStatusPumpData.percent).append("% ");
}
if (fields.contains("battery") && !deviceStatusPumpData.isPercent) {
string.append(Round.roundTo(deviceStatusPumpData.voltage, 0.001d)).append(" ");
}
if (fields.contains("clock")) {
string.append(DateUtil.minAgo(resourceHelper, deviceStatusPumpData.clock)).append(" ");
}
if (fields.contains("status")) {
string.append(deviceStatusPumpData.status).append(" ");
}
if (fields.contains("device")) {
string.append(getDevice()).append(" ");
}
string.append("</span>"); // color
return HtmlHelper.INSTANCE.fromHtml(string.toString());
}
static class DeviceStatusPumpData {
long clock = 0L;
boolean isPercent = false;
int percent = 0;
double voltage = 0;
String status = "N/A";
double reservoir = 0d;
Spanned extended = null;
}
private void updatePumpData() {
try {
JSONObject pump = data != null && data.has("pump") ? data.getJSONObject("pump") : new JSONObject();
long clock = 0L;
if (pump.has("clock"))
clock = DateUtil.fromISODateString(pump.getString("clock")).getTime();
// check if this is new data
if (clock == 0 || deviceStatusPumpData != null && clock < deviceStatusPumpData.clock)
return;
// create new status and process data
deviceStatusPumpData = new DeviceStatusPumpData();
deviceStatusPumpData.clock = clock;
if (pump.has("status") && pump.getJSONObject("status").has("status"))
deviceStatusPumpData.status = pump.getJSONObject("status").getString("status");
if (pump.has("reservoir"))
deviceStatusPumpData.reservoir = pump.getDouble("reservoir");
if (pump.has("battery") && pump.getJSONObject("battery").has("percent")) {
deviceStatusPumpData.isPercent = true;
deviceStatusPumpData.percent = pump.getJSONObject("battery").getInt("percent");
} else if (pump.has("battery") && pump.getJSONObject("battery").has("voltage")) {
deviceStatusPumpData.isPercent = false;
deviceStatusPumpData.voltage = pump.getJSONObject("battery").getDouble("voltage");
}
if (pump.has("extended")) {
JSONObject extendedJson = pump.getJSONObject("extended");
StringBuilder exteneded = new StringBuilder();
Iterator<?> keys = extendedJson.keys();
while (keys.hasNext()) {
String key = (String) keys.next();
String value = extendedJson.getString(key);
exteneded.append("<b>").append(key).append(":</b> ").append(value).append("<br>");
}
deviceStatusPumpData.extended = HtmlHelper.INSTANCE.fromHtml(exteneded.toString());
}
} catch (Exception e) {
aapsLogger.error("Unhandled exception", e);
}
}
// ********* OpenAPS data ***********
public static DeviceStatusOpenAPSData deviceStatusOpenAPSData = new DeviceStatusOpenAPSData();
public static class DeviceStatusOpenAPSData {
public long clockSuggested = 0L;
public long clockEnacted = 0L;
public JSONObject suggested = null;
public JSONObject enacted = null;
}
private void updateOpenApsData(JSONObject object) {
try {
JSONObject openaps = object.has("openaps") ? object.getJSONObject("openaps") : new JSONObject();
JSONObject suggested = openaps.has("suggested") ? openaps.getJSONObject("suggested") : new JSONObject();
JSONObject enacted = openaps.has("enacted") ? openaps.getJSONObject("enacted") : new JSONObject();
long clock = 0L;
if (suggested.has("timestamp"))
clock = DateUtil.fromISODateString(suggested.getString("timestamp")).getTime();
// check if this is new data
if (clock != 0 && clock > deviceStatusOpenAPSData.clockSuggested) {
deviceStatusOpenAPSData.suggested = suggested;
deviceStatusOpenAPSData.clockSuggested = clock;
}
clock = 0L;
if (enacted.has("timestamp"))
clock = DateUtil.fromISODateString(enacted.getString("timestamp")).getTime();
// check if this is new data
if (clock != 0 && clock > deviceStatusOpenAPSData.clockEnacted) {
deviceStatusOpenAPSData.enacted = enacted;
deviceStatusOpenAPSData.clockEnacted = clock;
}
} catch (Exception e) {
aapsLogger.error("Unhandled exception", e);
}
}
public Spanned getOpenApsStatus() {
StringBuilder string = new StringBuilder();
string.append("<span style=\"color:" + resourceHelper.gcs(R.color.defaulttext) + "\">");
string.append(resourceHelper.gs(R.string.openaps_short));
string.append(": </span>");
// test warning level
int level = Levels.INFO;
long now = System.currentTimeMillis();
if (deviceStatusOpenAPSData.clockSuggested != 0 && deviceStatusOpenAPSData.clockSuggested + sp.getInt(R.string.key_nsalarm_urgent_staledatavalue, 31) * 60 * 1000L < now)
level = Levels.URGENT;
else if (deviceStatusOpenAPSData.clockSuggested != 0 && deviceStatusOpenAPSData.clockSuggested + sp.getInt(R.string.key_nsalarm_staledatavalue, 16) * 60 * 1000L < now)
level = Levels.WARN;
string.append("<span style=\"color:");
if (level == Levels.INFO) string.append("white\">");
if (level == Levels.WARN) string.append("yellow\">");
if (level == Levels.URGENT) string.append("red\">");
if (deviceStatusOpenAPSData.clockSuggested != 0) {
string.append(DateUtil.minAgo(resourceHelper, deviceStatusOpenAPSData.clockSuggested)).append(" ");
}
string.append("</span>"); // color
return HtmlHelper.INSTANCE.fromHtml(string.toString());
}
public static long getOpenApsTimestamp() {
if (deviceStatusOpenAPSData.clockSuggested != 0) {
return deviceStatusOpenAPSData.clockSuggested;
} else {
return -1;
}
}
public Spanned getExtendedOpenApsStatus() {
StringBuilder string = new StringBuilder();
try {
if (deviceStatusOpenAPSData.enacted != null && deviceStatusOpenAPSData.clockEnacted != deviceStatusOpenAPSData.clockSuggested)
string.append("<b>").append(DateUtil.minAgo(resourceHelper, deviceStatusOpenAPSData.clockEnacted)).append("</b> ").append(deviceStatusOpenAPSData.enacted.getString("reason")).append("<br>");
if (deviceStatusOpenAPSData.suggested != null)
string.append("<b>").append(DateUtil.minAgo(resourceHelper, deviceStatusOpenAPSData.clockSuggested)).append("</b> ").append(deviceStatusOpenAPSData.suggested.getString("reason")).append("<br>");
return HtmlHelper.INSTANCE.fromHtml(string.toString());
} catch (JSONException e) {
aapsLogger.error("Unhandled exception", e);
}
return HtmlHelper.INSTANCE.fromHtml("");
}
// ********* Uploader data ***********
private static final HashMap<String, Uploader> uploaders = new HashMap<>();
static class Uploader {
long clock = 0L;
int battery = 0;
}
private void updateUploaderData(JSONObject object) {
try {
long clock = 0L;
if (object.has("mills"))
clock = object.getLong("mills");
else if (object.has("created_at"))
clock = DateUtil.fromISODateString(object.getString("created_at")).getTime();
String device = getDevice();
Integer battery = null;
if (object.has("uploaderBattery"))
battery = object.getInt("uploaderBattery");
else if (object.has("uploader")) {
if (object.getJSONObject("uploader").has("battery"))
battery = object.getJSONObject("uploader").getInt("battery");
}
Uploader uploader = uploaders.get(device);
// check if this is new data
if (clock != 0 && battery != null && (uploader == null || clock > uploader.clock)) {
if (uploader == null)
uploader = new Uploader();
uploader.battery = battery;
uploader.clock = clock;
uploaders.put(device, uploader);
}
} catch (Exception e) {
aapsLogger.error("Unhandled exception", e);
}
}
public String getUploaderStatus() {
Iterator iter = uploaders.entrySet().iterator();
int minBattery = 100;
while (iter.hasNext()) {
Map.Entry pair = (Map.Entry) iter.next();
Uploader uploader = (Uploader) pair.getValue();
if (minBattery > uploader.battery)
minBattery = uploader.battery;
}
return minBattery + "%";
}
public Spanned getUploaderStatusSpanned() {
StringBuilder string = new StringBuilder();
string.append("<span style=\"color:" + resourceHelper.gcs(R.color.defaulttext) + "\">");
string.append(resourceHelper.gs(R.string.uploader_short));
string.append(": </span>");
Iterator iter = uploaders.entrySet().iterator();
int minBattery = 100;
while (iter.hasNext()) {
Map.Entry pair = (Map.Entry) iter.next();
Uploader uploader = (Uploader) pair.getValue();
if (minBattery > uploader.battery)
minBattery = uploader.battery;
}
string.append(minBattery);
string.append("%");
return HtmlHelper.INSTANCE.fromHtml(string.toString());
}
public Spanned getExtendedUploaderStatus() {
StringBuilder string = new StringBuilder();
Iterator iter = uploaders.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry pair = (Map.Entry) iter.next();
Uploader uploader = (Uploader) pair.getValue();
String device = (String) pair.getKey();
string.append("<b>").append(device).append(":</b> ").append(uploader.battery).append("%<br>");
}
return HtmlHelper.INSTANCE.fromHtml(string.toString());
}
public static APSResult getAPSResult(HasAndroidInjector injector) {
APSResult result = new APSResult(injector);
result.setJson(deviceStatusOpenAPSData.suggested);
result.setDate(deviceStatusOpenAPSData.clockSuggested);
return result;
}
}

View file

@ -0,0 +1,396 @@
package info.nightscout.androidaps.plugins.general.nsclient.data
import android.text.Spanned
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R
import info.nightscout.androidaps.interfaces.ConfigInterface
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.aps.loop.APSResult
import info.nightscout.androidaps.plugins.configBuilder.RunningConfiguration
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.HtmlHelper.fromHtml
import info.nightscout.androidaps.utils.Round
import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP
import org.json.JSONArray
import org.json.JSONException
import org.json.JSONObject
import java.util.*
import javax.inject.Inject
import javax.inject.Singleton
/*
{
"_id": "594fdcec327b83c81b6b8c0f",
"device": "openaps://Sony D5803",
"pump": {
"battery": {
"percent": 100
},
"status": {
"status": "normal",
"timestamp": "2017-06-25T15:50:14Z"
},
"extended": {
"Version": "1.5-ac98852-2017.06.25",
"PumpIOB": 1.13,
"LastBolus": "25. 6. 2017 17:25:00",
"LastBolusAmount": 0.3,
"BaseBasalRate": 0.4,
"ActiveProfile": "2016 +30%"
},
"reservoir": 109,
"clock": "2017-06-25T15:55:10Z"
},
"openaps": {
"suggested": {
"temp": "absolute",
"bg": 115.9,
"tick": "+5",
"eventualBG": 105,
"snoozeBG": 105,
"predBGs": {
"IOB": [116, 114, 112, 110, 109, 107, 106, 105, 105, 104, 104, 104, 104, 104, 104, 104, 104, 105, 105, 105, 105, 105, 106, 106, 106, 106, 106, 107]
},
"COB": 0,
"IOB": -0.035,
"reason": "COB: 0, Dev: -18, BGI: 0.43, ISF: 216, Target: 99; Eventual BG 105 > 99 but Min. Delta -2.60 < Exp. Delta 0.1; setting current basal of 0.4 as temp. Suggested rate is same as profile rate, no temp basal is active, doing nothing",
"timestamp": "2017-06-25T15:55:10Z"
},
"iob": {
"iob": -0.035,
"basaliob": -0.035,
"activity": -0.0004,
"time": "2017-06-25T15:55:10Z"
}
},
"uploaderBattery": 93,
"created_at": "2017-06-25T15:55:10Z",
"NSCLIENT_ID": 1498406118857
}
*/
@Suppress("SpellCheckingInspection")
@Singleton
class NSDeviceStatus @Inject constructor(
private val aapsLogger: AAPSLogger,
private val sp: SP,
private val resourceHelper: ResourceHelper,
private val nsSettingsStatus: NSSettingsStatus,
private val config: ConfigInterface,
private val dateUtil: DateUtil,
private val runningConfiguration: RunningConfiguration
) {
private var data: JSONObject? = null
fun handleNewData(deviceStatuses: JSONArray) {
aapsLogger.debug(LTag.NSCLIENT, "Got NS deviceStatus: \$deviceStatuses}")
try {
for (i in 0 until deviceStatuses.length()) {
val devicestatusJson = deviceStatuses.getJSONObject(i)
if (devicestatusJson != null) {
setData(devicestatusJson)
if (devicestatusJson.has("pump")) {
// Objectives 0
sp.putBoolean(R.string.key_ObjectivespumpStatusIsAvailableInNS, true)
}
if (devicestatusJson.has("configuration") && config.NSCLIENT) {
// copy configuration of Insulin and Sensitivity from main AAPS
runningConfiguration.apply(devicestatusJson.getJSONObject("configuration"))
}
}
}
} catch (jsonException: JSONException) {
jsonException.printStackTrace()
}
}
private fun setData(obj: JSONObject): NSDeviceStatus {
data = obj
updatePumpData()
updateOpenApsData(obj)
updateUploaderData(obj)
return this
}
val device: String
get() {
try {
if (data!!.has("device")) {
var device = data!!.getString("device")
if (device.startsWith("openaps://")) {
device = device.substring(10)
return device
}
}
} catch (e: JSONException) {
aapsLogger.error("Unhandled exception", e)
}
return ""
}
enum class Levels(val level: Int) {
URGENT(2),
WARN(1),
INFO(0);
fun toColor(): String =
when (level) {
INFO.level -> "white"
WARN.level -> "yellow"
URGENT.level -> "red"
else -> "white"
}
}
// ***** PUMP DATA ******
private var deviceStatusPumpData: DeviceStatusPumpData? = null
val extendedPumpStatus: Spanned
get() = deviceStatusPumpData?.extended ?: fromHtml("")
val pumpStatus: Spanned
// test warning level // color
get() {
val pumpData = deviceStatusPumpData ?: return fromHtml("")
//String[] ALL_STATUS_FIELDS = {"reservoir", "battery", "clock", "status", "device"};
val string = StringBuilder()
.append("<span style=\"color:${resourceHelper.gcs(R.color.defaulttext)}\">")
.append(resourceHelper.gs(R.string.pump))
.append(": </span>")
// test warning level
val level = when {
pumpData.clock + nsSettingsStatus.extendedPumpSettings("urgentClock") * 60 * 1000L < dateUtil._now() -> Levels.URGENT
pumpData.reservoir < nsSettingsStatus.extendedPumpSettings("urgentRes") -> Levels.URGENT
pumpData.isPercent && pumpData.percent < nsSettingsStatus.extendedPumpSettings("urgentBattP") -> Levels.URGENT
!pumpData.isPercent && pumpData.voltage < nsSettingsStatus.extendedPumpSettings("urgentBattV") -> Levels.URGENT
pumpData.clock + nsSettingsStatus.extendedPumpSettings("warnClock") * 60 * 1000L < dateUtil._now() -> Levels.WARN
pumpData.reservoir < nsSettingsStatus.extendedPumpSettings("warnRes") -> Levels.WARN
pumpData.isPercent && pumpData.percent < nsSettingsStatus.extendedPumpSettings("warnBattP") -> Levels.WARN
!pumpData.isPercent && pumpData.voltage < nsSettingsStatus.extendedPumpSettings("warnBattV") -> Levels.WARN
else -> Levels.INFO
}
string.append("<span style=\"color:${level.toColor()}\">")
val fields = nsSettingsStatus.pumpExtendedSettingsFields()
if (fields.contains("reservoir")) string.append(pumpData.reservoir.toInt()).append("U ")
if (fields.contains("battery") && pumpData.isPercent) string.append(pumpData.percent).append("% ")
if (fields.contains("battery") && !pumpData.isPercent) string.append(Round.roundTo(pumpData.voltage, 0.001)).append(" ")
if (fields.contains("clock")) string.append(DateUtil.minAgo(resourceHelper, pumpData.clock)).append(" ")
if (fields.contains("status")) string.append(pumpData.status).append(" ")
if (fields.contains("device")) string.append(device).append(" ")
string.append("</span>") // color
return fromHtml(string.toString())
}
internal class DeviceStatusPumpData {
var clock = 0L
var isPercent = false
var percent = 0
var voltage = 0.0
var status = "N/A"
var reservoir = 0.0
var extended: Spanned? = null
}
private fun updatePumpData() {
try {
val data = this.data ?: return
val pump = if (data.has("pump")) data.getJSONObject("pump") else JSONObject()
val clock = if (pump.has("clock")) DateUtil.fromISODateString(pump.getString("clock")).time else 0L
// check if this is new data
if (clock == 0L || deviceStatusPumpData != null && clock < deviceStatusPumpData!!.clock) return
// create new status and process data
val deviceStatusPumpData = DeviceStatusPumpData()
deviceStatusPumpData.clock = clock
if (pump.has("status") && pump.getJSONObject("status").has("status")) deviceStatusPumpData.status = pump.getJSONObject("status").getString("status")
if (pump.has("reservoir")) deviceStatusPumpData.reservoir = pump.getDouble("reservoir")
if (pump.has("battery") && pump.getJSONObject("battery").has("percent")) {
deviceStatusPumpData.isPercent = true
deviceStatusPumpData.percent = pump.getJSONObject("battery").getInt("percent")
} else if (pump.has("battery") && pump.getJSONObject("battery").has("voltage")) {
deviceStatusPumpData.isPercent = false
deviceStatusPumpData.voltage = pump.getJSONObject("battery").getDouble("voltage")
}
if (pump.has("extended")) {
val extendedJson = pump.getJSONObject("extended")
val extended = StringBuilder()
val keys: Iterator<*> = extendedJson.keys()
while (keys.hasNext()) {
val key = keys.next() as String
val value = extendedJson.getString(key)
extended.append("<b>").append(key).append(":</b> ").append(value).append("<br>")
}
deviceStatusPumpData.extended = fromHtml(extended.toString())
}
this.deviceStatusPumpData = deviceStatusPumpData
} catch (e: Exception) {
aapsLogger.error("Unhandled exception", e)
}
}
class DeviceStatusOpenAPSData {
var clockSuggested = 0L
var clockEnacted = 0L
var suggested: JSONObject? = null
var enacted: JSONObject? = null
}
private fun updateOpenApsData(jsonObject: JSONObject) {
try {
val openAps = if (jsonObject.has("openaps")) jsonObject.getJSONObject("openaps") else JSONObject()
val suggested = if (openAps.has("suggested")) openAps.getJSONObject("suggested") else JSONObject()
val enacted = if (openAps.has("enacted")) openAps.getJSONObject("enacted") else JSONObject()
var clock = if (suggested.has("timestamp")) DateUtil.fromISODateString(suggested.getString("timestamp")).time else 0L
// check if this is new data
if (clock != 0L && clock > deviceStatusOpenAPSData.clockSuggested) {
deviceStatusOpenAPSData.suggested = suggested
deviceStatusOpenAPSData.clockSuggested = clock
}
clock = if (enacted.has("timestamp")) DateUtil.fromISODateString(enacted.getString("timestamp")).time else 0L
// check if this is new data
if (clock != 0L && clock > deviceStatusOpenAPSData.clockEnacted) {
deviceStatusOpenAPSData.enacted = enacted
deviceStatusOpenAPSData.clockEnacted = clock
}
} catch (e: Exception) {
aapsLogger.error("Unhandled exception", e)
}
}
val openApsStatus: Spanned
get() {
val string = StringBuilder()
.append("<span style=\"color:${resourceHelper.gcs(R.color.defaulttext)}\">")
.append(resourceHelper.gs(R.string.openaps_short))
.append(": </span>")
// test warning level
val level = when {
deviceStatusOpenAPSData.clockSuggested + T.mins(sp.getLong(R.string.key_nsalarm_urgent_staledatavalue, 31)).msecs() < dateUtil._now() -> Levels.URGENT
deviceStatusOpenAPSData.clockSuggested + T.mins(sp.getLong(R.string.key_nsalarm_staledatavalue, 16)).msecs() < dateUtil._now() -> Levels.WARN
else -> Levels.INFO
}
string.append("<span style=\"color:${level.toColor()}\">")
if (deviceStatusOpenAPSData.clockSuggested != 0L) string.append(DateUtil.minAgo(resourceHelper, deviceStatusOpenAPSData.clockSuggested)).append(" ")
string.append("</span>") // color
return fromHtml(string.toString())
}
val extendedOpenApsStatus: Spanned
get() {
val string = StringBuilder()
try {
if (deviceStatusOpenAPSData.enacted != null && deviceStatusOpenAPSData.clockEnacted != deviceStatusOpenAPSData.clockSuggested) string.append("<b>").append(DateUtil.minAgo(resourceHelper, deviceStatusOpenAPSData.clockEnacted)).append("</b> ").append(deviceStatusOpenAPSData.enacted!!.getString("reason")).append("<br>")
if (deviceStatusOpenAPSData.suggested != null) string.append("<b>").append(DateUtil.minAgo(resourceHelper, deviceStatusOpenAPSData.clockSuggested)).append("</b> ").append(deviceStatusOpenAPSData.suggested!!.getString("reason")).append("<br>")
return fromHtml(string.toString())
} catch (e: JSONException) {
aapsLogger.error("Unhandled exception", e)
}
return fromHtml("")
}
internal class Uploader {
var clock = 0L
var battery = 0
}
private fun updateUploaderData(jsonObject: JSONObject) {
try {
val clock =
when {
jsonObject.has("mills") -> jsonObject.getLong("mills")
jsonObject.has("created_at") -> DateUtil.fromISODateString(jsonObject.getString("created_at")).time
else -> 0L
}
val device = device
val battery: Int =
when {
jsonObject.has("uploaderBattery") -> jsonObject.getInt("uploaderBattery")
jsonObject.has("uploader") && jsonObject.getJSONObject("uploader").has("battery") -> jsonObject.getJSONObject("uploader").getInt("battery")
else -> 0
}
var uploader = uploaderMap[device]
// check if this is new data
if (clock != 0L && battery != 0 && (uploader == null || clock > uploader.clock)) {
if (uploader == null) uploader = Uploader()
uploader.battery = battery
uploader.clock = clock
uploaderMap[device] = uploader
}
} catch (e: Exception) {
aapsLogger.error("Unhandled exception", e)
}
}
val uploaderStatus: String
get() {
val iterator: Iterator<*> = uploaderMap.entries.iterator()
var minBattery = 100
while (iterator.hasNext()) {
val pair = iterator.next() as Map.Entry<*, *>
val uploader = pair.value as Uploader
if (minBattery > uploader.battery) minBattery = uploader.battery
}
return "$minBattery%"
}
val uploaderStatusSpanned: Spanned
get() {
val string = StringBuilder()
string.append("<span style=\"color:${resourceHelper.gcs(R.color.defaulttext)}\">")
string.append(resourceHelper.gs(R.string.uploader_short))
string.append(": </span>")
val iterator: Iterator<*> = uploaderMap.entries.iterator()
var minBattery = 100
while (iterator.hasNext()) {
val pair = iterator.next() as Map.Entry<*, *>
val uploader = pair.value as Uploader
if (minBattery > uploader.battery) minBattery = uploader.battery
}
string.append(minBattery)
string.append("%")
return fromHtml(string.toString())
}
val extendedUploaderStatus: Spanned
get() {
val string = StringBuilder()
val iterator: Iterator<*> = uploaderMap.entries.iterator()
while (iterator.hasNext()) {
val pair = iterator.next() as Map.Entry<*, *>
val uploader = pair.value as Uploader
val device = pair.key as String
string.append("<b>").append(device).append(":</b> ").append(uploader.battery).append("%<br>")
}
return fromHtml(string.toString())
}
// ********* OpenAPS data ***********
var deviceStatusOpenAPSData = DeviceStatusOpenAPSData()
val openApsTimestamp: Long
get() =
if (deviceStatusOpenAPSData.clockSuggested != 0L) {
deviceStatusOpenAPSData.clockSuggested
} else {
-1
}
// ********* Uploader data ***********
private val uploaderMap = HashMap<String, Uploader>()
fun getAPSResult(injector: HasAndroidInjector): APSResult {
val result = APSResult(injector)
result.json = deviceStatusOpenAPSData.suggested
result.date = deviceStatusOpenAPSData.clockSuggested
return result
}
}

View file

@ -11,6 +11,7 @@ import android.os.PowerManager;
import android.os.SystemClock; import android.os.SystemClock;
import androidx.localbroadcastmanager.content.LocalBroadcastManager; import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import androidx.work.OneTimeWorkRequest;
import com.google.common.base.Charsets; import com.google.common.base.Charsets;
import com.google.common.hash.Hashing; import com.google.common.hash.Hashing;
@ -41,6 +42,7 @@ import info.nightscout.androidaps.interfaces.ProfileStore;
import info.nightscout.androidaps.logging.AAPSLogger; import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.logging.LTag; import info.nightscout.androidaps.logging.LTag;
import info.nightscout.androidaps.plugins.bus.RxBusWrapper; import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
import info.nightscout.androidaps.plugins.general.food.FoodPlugin;
import info.nightscout.androidaps.plugins.general.nsclient.NSClientPlugin; import info.nightscout.androidaps.plugins.general.nsclient.NSClientPlugin;
import info.nightscout.androidaps.plugins.general.nsclient.UploadQueue; import info.nightscout.androidaps.plugins.general.nsclient.UploadQueue;
import info.nightscout.androidaps.plugins.general.nsclient.acks.NSAddAck; import info.nightscout.androidaps.plugins.general.nsclient.acks.NSAddAck;
@ -60,6 +62,9 @@ import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNo
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; import info.nightscout.androidaps.plugins.general.overview.notifications.Notification;
import info.nightscout.androidaps.plugins.general.overview.notifications.NotificationWithAction; import info.nightscout.androidaps.plugins.general.overview.notifications.NotificationWithAction;
import info.nightscout.androidaps.plugins.profile.ns.NSProfilePlugin;
import info.nightscout.androidaps.plugins.source.NSClientSourcePlugin;
import info.nightscout.androidaps.receivers.DataWorker;
import info.nightscout.androidaps.services.Intents; import info.nightscout.androidaps.services.Intents;
import info.nightscout.androidaps.utils.DateUtil; import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.FabricPrivacy; import info.nightscout.androidaps.utils.FabricPrivacy;
@ -90,6 +95,7 @@ public class NSClientService extends DaggerService {
@Inject Config config; @Inject Config config;
@Inject DateUtil dateUtil; @Inject DateUtil dateUtil;
@Inject UploadQueue uploadQueue; @Inject UploadQueue uploadQueue;
@Inject DataWorker dataWorker;
private final CompositeDisposable disposable = new CompositeDisposable(); private final CompositeDisposable disposable = new CompositeDisposable();
@ -534,16 +540,6 @@ public class NSClientService extends DaggerService {
boolean isFull = !isDelta; boolean isFull = !isDelta;
rxBus.send(new EventNSClientNewLog("DATA", "Data packet #" + dataCounter++ + (isDelta ? " delta" : " full"))); rxBus.send(new EventNSClientNewLog("DATA", "Data packet #" + dataCounter++ + (isDelta ? " delta" : " full")));
if (data.has("profiles")) {
JSONArray profiles = data.getJSONArray("profiles");
if (profiles.length() > 0) {
JSONObject profile = (JSONObject) profiles.get(profiles.length() - 1);
profileStore = new ProfileStore(injector, profile);
broadcastProfile = true;
rxBus.send(new EventNSClientNewLog("PROFILE", "profile received"));
}
}
if (data.has("status")) { if (data.has("status")) {
JSONObject status = data.getJSONObject("status"); JSONObject status = data.getJSONObject("status");
nsSettingsStatus.setData(status); nsSettingsStatus.setData(status);
@ -558,30 +554,48 @@ public class NSClientService extends DaggerService {
} }
nsSettingsStatus.handleNewData(nightscoutVersionName, nightscoutVersionCode, status); nsSettingsStatus.handleNewData(nightscoutVersionName, nightscoutVersionCode, status);
/* Other received data to 2016/02/10 /* Other received data to 2016/02/10
{ {
status: 'ok' status: 'ok'
, name: env.name , name: env.name
, version: env.version , version: env.version
, versionNum: versionNum (for ver 1.2.3 contains 10203) , versionNum: versionNum (for ver 1.2.3 contains 10203)
, serverTime: new Date().toISOString() , serverTime: new Date().toISOString()
, apiEnabled: apiEnabled , apiEnabled: apiEnabled
, careportalEnabled: apiEnabled && env.settings.enable.indexOf('careportal') > -1 , careportalEnabled: apiEnabled && env.settings.enable.indexOf('careportal') > -1
, boluscalcEnabled: apiEnabled && env.settings.enable.indexOf('boluscalc') > -1 , boluscalcEnabled: apiEnabled && env.settings.enable.indexOf('boluscalc') > -1
, head: env.head , head: env.head
, settings: env.settings , settings: env.settings
, extendedSettings: ctx.plugins && ctx.plugins.extendedClientSettings ? ctx.plugins.extendedClientSettings(env.extendedSettings) : {} , extendedSettings: ctx.plugins && ctx.plugins.extendedClientSettings ? ctx.plugins.extendedClientSettings(env.extendedSettings) : {}
, activeProfile ..... calculated from treatments or missing , activeProfile ..... calculated from treatments or missing
} }
*/ */
} else if (!isDelta) { } else if (!isDelta) {
rxBus.send(new EventNSClientNewLog("ERROR", "Unsupported Nightscout version !!!!")); rxBus.send(new EventNSClientNewLog("ERROR", "Unsupported Nightscout version !!!!"));
} }
// If new profile received or change detected broadcast it // If new profile received or change detected broadcast it
if (broadcastProfile && profileStore != null) { if (data.has("profiles")) {
handleNewProfile(profileStore, isDelta); JSONArray profiles = data.getJSONArray("profiles");
rxBus.send(new EventNSClientNewLog("PROFILE", "broadcasting")); if (profiles.length() > 0) {
// take the newest
JSONObject profileStoreJson = (JSONObject) profiles.get(profiles.length() - 1);
rxBus.send(new EventNSClientNewLog("PROFILE", "profile received"));
dataWorker.enqueue(
new OneTimeWorkRequest.Builder(NSProfilePlugin.NSProfileWorker.class)
.setInputData(dataWorker.storeInputData(profileStoreJson, null))
.build());
if (sp.getBoolean(R.string.key_nsclient_localbroadcasts, false)) {
Bundle bundle = new Bundle();
bundle.putString("profile", profileStoreJson.toString());
bundle.putBoolean("delta", isDelta);
Intent intent = new Intent(Intents.ACTION_NEW_PROFILE);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
sendBroadcast(intent);
}
}
} }
if (data.has("treatments")) { if (data.has("treatments")) {
@ -635,8 +649,12 @@ public class NSClientService extends DaggerService {
} }
if (data.has("food")) { if (data.has("food")) {
JSONArray foods = data.getJSONArray("food"); JSONArray foods = data.getJSONArray("food");
if (foods.length() > 0) rxBus.send(new EventNSClientNewLog("DATA", "received " + foods.length() + " foods")); if (foods.length() > 0)
handleFood(foods, isDelta); rxBus.send(new EventNSClientNewLog("DATA", "received " + foods.length() + " foods"));
dataWorker.enqueue(
new OneTimeWorkRequest.Builder(FoodPlugin.FoodWorker.class)
.setInputData(dataWorker.storeInputData(foods, null))
.build());
} }
if (data.has("mbgs")) { if (data.has("mbgs")) {
JSONArray mbgs = data.getJSONArray("mbgs"); JSONArray mbgs = data.getJSONArray("mbgs");
@ -664,24 +682,23 @@ public class NSClientService extends DaggerService {
JSONArray sgvs = data.getJSONArray("sgvs"); JSONArray sgvs = data.getJSONArray("sgvs");
if (sgvs.length() > 0) if (sgvs.length() > 0)
rxBus.send(new EventNSClientNewLog("DATA", "received " + sgvs.length() + " sgvs")); rxBus.send(new EventNSClientNewLog("DATA", "received " + sgvs.length() + " sgvs"));
for (int index = 0; index < sgvs.length(); index++) {
JSONObject jsonSgv = sgvs.getJSONObject(index); dataWorker.enqueue(new OneTimeWorkRequest.Builder(NSClientSourcePlugin.NSClientSourceWorker.class)
// rxBus.send(new EventNSClientNewLog("DATA", "svg " + sgvs.getJSONObject(index).toString()); .setInputData(dataWorker.storeInputData(sgvs, null))
NSSgv sgv = new NSSgv(jsonSgv); .build());
// Handle new sgv here
// remove from upload queue if Ack is failing List<JSONArray> splitted = splitArray(sgvs);
uploadQueue.removeID(jsonSgv); if (sp.getBoolean(R.string.key_nsclient_localbroadcasts, false)) {
//Find latest date in sgv for (JSONArray part : splitted) {
if (sgv.getMills() != null && sgv.getMills() < System.currentTimeMillis()) Bundle bundle = new Bundle();
if (sgv.getMills() > latestDateInReceivedData) bundle.putString("sgvs", part.toString());
latestDateInReceivedData = sgv.getMills(); bundle.putBoolean("delta", isDelta);
Intent intent = new Intent(Intents.ACTION_NEW_SGV);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
sendBroadcast(intent);
}
} }
// Was that sgv more less 5 mins ago ?
if ((System.currentTimeMillis() - latestDateInReceivedData) / (60 * 1000L) < 5L) {
rxBus.send(new EventDismissNotification(Notification.NS_ALARM));
rxBus.send(new EventDismissNotification(Notification.NS_URGENT_ALARM));
}
handleNewSgv(sgvs, isDelta);
} }
rxBus.send(new EventNSClientNewLog("LAST", dateUtil.dateAndTimeString(latestDateInReceivedData))); rxBus.send(new EventNSClientNewLog("LAST", dateUtil.dateAndTimeString(latestDateInReceivedData)));
} catch (JSONException e) { } catch (JSONException e) {
@ -849,16 +866,6 @@ public class NSClientService extends DaggerService {
} }
} }
public void handleFood(JSONArray foods, boolean isDelta) {
Bundle bundle = new Bundle();
bundle.putString("foods", foods.toString());
bundle.putBoolean("delta", isDelta);
Intent intent = new Intent(Intents.ACTION_FOOD);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
public void handleNewCal(JSONArray cals, boolean isDelta) { public void handleNewCal(JSONArray cals, boolean isDelta) {
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
bundle.putString("cals", cals.toString()); bundle.putString("cals", cals.toString());
@ -879,51 +886,6 @@ public class NSClientService extends DaggerService {
LocalBroadcastManager.getInstance(this).sendBroadcast(intent); LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
} }
public void handleNewProfile(ProfileStore profile, boolean isDelta) {
Bundle bundle = new Bundle();
bundle.putString("profile", profile.getData().toString());
bundle.putBoolean("delta", isDelta);
Intent intent = new Intent(Intents.ACTION_NEW_PROFILE);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
if (sp.getBoolean(R.string.key_nsclient_localbroadcasts, false)) {
bundle = new Bundle();
bundle.putString("profile", profile.getData().toString());
bundle.putBoolean("delta", isDelta);
intent = new Intent(Intents.ACTION_NEW_PROFILE);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
this.sendBroadcast(intent);
}
}
public void handleNewSgv(JSONArray sgvs, boolean isDelta) {
List<JSONArray> splitted = splitArray(sgvs);
for (JSONArray part : splitted) {
Bundle bundle = new Bundle();
bundle.putString("sgvs", part.toString());
bundle.putBoolean("delta", isDelta);
Intent intent = new Intent(Intents.ACTION_NEW_SGV);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
if (sp.getBoolean(R.string.key_nsclient_localbroadcasts, false)) {
for (JSONArray part : splitted) {
Bundle bundle = new Bundle();
bundle.putString("sgvs", part.toString());
bundle.putBoolean("delta", isDelta);
Intent intent = new Intent(Intents.ACTION_NEW_SGV);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
this.sendBroadcast(intent);
}
}
}
public void handleNewTreatment(JSONArray treatments, boolean isDelta) { public void handleNewTreatment(JSONArray treatments, boolean isDelta) {
List<JSONArray> splitted = splitArray(treatments); List<JSONArray> splitted = splitArray(treatments);
for (JSONArray part : splitted) { for (JSONArray part : splitted) {

View file

@ -839,7 +839,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
val toTime: Long val toTime: Long
val fromTime: Long val fromTime: Long
val endTime: Long val endTime: Long
val apsResult = if (config.APS) lastRun?.constraintsProcessed else NSDeviceStatus.getAPSResult(injector) val apsResult = if (config.APS) lastRun?.constraintsProcessed else nsDeviceStatus.getAPSResult(injector)
if (predictionsAvailable && apsResult != null && menuChartSettings[0][OverviewMenus.CharType.PRE.ordinal]) { if (predictionsAvailable && apsResult != null && menuChartSettings[0][OverviewMenus.CharType.PRE.ordinal]) {
var predictionHours = (ceil(apsResult.latestPredictionsTime - System.currentTimeMillis().toDouble()) / (60 * 60 * 1000)).toInt() var predictionHours = (ceil(apsResult.latestPredictionsTime - System.currentTimeMillis().toDouble()) / (60 * 60 * 1000)).toInt()
predictionHours = min(2, predictionHours) predictionHours = min(2, predictionHours)

View file

@ -36,11 +36,10 @@ import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotifi
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification import info.nightscout.androidaps.plugins.general.overview.notifications.Notification
import info.nightscout.androidaps.plugins.general.smsCommunicator.events.EventSmsCommunicatorUpdateGui import info.nightscout.androidaps.plugins.general.smsCommunicator.events.EventSmsCommunicatorUpdateGui
import info.nightscout.androidaps.plugins.general.smsCommunicator.otp.OneTimePassword import info.nightscout.androidaps.plugins.general.smsCommunicator.otp.OneTimePassword
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatusProvider import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatusProvider
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
import info.nightscout.androidaps.queue.Callback import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.receivers.BundleStore import info.nightscout.androidaps.receivers.DataWorker
import info.nightscout.androidaps.receivers.DataReceiver import info.nightscout.androidaps.receivers.DataReceiver
import info.nightscout.androidaps.utils.* import info.nightscout.androidaps.utils.*
import info.nightscout.androidaps.utils.extensions.valueToUnitsString import info.nightscout.androidaps.utils.extensions.valueToUnitsString
@ -176,7 +175,7 @@ class SmsCommunicatorPlugin @Inject constructor(
) : Worker(context, params) { ) : Worker(context, params) {
@Inject lateinit var smsCommunicatorPlugin: SmsCommunicatorPlugin @Inject lateinit var smsCommunicatorPlugin: SmsCommunicatorPlugin
@Inject lateinit var bundleStore: BundleStore @Inject lateinit var dataWorker: DataWorker
init { init {
(context.applicationContext as HasAndroidInjector).androidInjector().inject(this) (context.applicationContext as HasAndroidInjector).androidInjector().inject(this)
@ -184,7 +183,7 @@ class SmsCommunicatorPlugin @Inject constructor(
@Suppress("SpellCheckingInspection") @Suppress("SpellCheckingInspection")
override fun doWork(): Result { override fun doWork(): Result {
val bundle = bundleStore.pickup(inputData.getLong(DataReceiver.STORE_KEY, -1)) val bundle = dataWorker.pickupBundle(inputData.getLong(DataWorker.STORE_KEY, -1))
?: return Result.failure() ?: return Result.failure()
val format = bundle.getString("format") ?: return Result.failure() val format = bundle.getString("format") ?: return Result.failure()
val pdus = bundle["pdus"] as Array<*> val pdus = bundle["pdus"] as Array<*>
@ -731,7 +730,7 @@ class SmsCommunicatorPlugin @Inject constructor(
var replyText = resourceHelper.gs(R.string.smscommunicator_extendedcancelfailed) var replyText = resourceHelper.gs(R.string.smscommunicator_extendedcancelfailed)
replyText += "\n" + activePlugin.activePump.shortStatus(true) replyText += "\n" + activePlugin.activePump.shortStatus(true)
sendSMS(Sms(receivedSms.phoneNumber, replyText)) sendSMS(Sms(receivedSms.phoneNumber, replyText))
uel.log(Action.SMS_EXTENDED_BOLUS, activePlugin.activePump.shortStatus(true),ValueWithUnit(R.string.smscommunicator_extendedcanceled, Units.R_String)) uel.log(Action.SMS_EXTENDED_BOLUS, activePlugin.activePump.shortStatus(true), ValueWithUnit(R.string.smscommunicator_extendedcanceled, Units.R_String))
} }
} }
}) })
@ -758,14 +757,16 @@ class SmsCommunicatorPlugin @Inject constructor(
replyText += "\n" + activePlugin.activePump.shortStatus(true) replyText += "\n" + activePlugin.activePump.shortStatus(true)
sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText)) sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText))
if (config.APS) if (config.APS)
uel.log(Action.SMS_EXTENDED_BOLUS, activePlugin.activePump.shortStatus(true), ValueWithUnit(R.string.smscommunicator_extendedset, 2), ValueWithUnit(aDouble ?:0.0, Units.U), ValueWithUnit(duration, Units.M), ValueWithUnit(R.string.loopsuspended, Units.R_String)) uel.log(Action.SMS_EXTENDED_BOLUS, activePlugin.activePump.shortStatus(true), ValueWithUnit(R.string.smscommunicator_extendedset, 2), ValueWithUnit(aDouble
else ?: 0.0, Units.U), ValueWithUnit(duration, Units.M), ValueWithUnit(R.string.loopsuspended, Units.R_String))
uel.log(Action.SMS_EXTENDED_BOLUS, activePlugin.activePump.shortStatus(true), ValueWithUnit(R.string.smscommunicator_extendedset, 2), ValueWithUnit(aDouble ?:0.0, Units.U), ValueWithUnit(duration, Units.M)) else
uel.log(Action.SMS_EXTENDED_BOLUS, activePlugin.activePump.shortStatus(true), ValueWithUnit(R.string.smscommunicator_extendedset, 2), ValueWithUnit(aDouble
?: 0.0, Units.U), ValueWithUnit(duration, Units.M))
} else { } else {
var replyText = resourceHelper.gs(R.string.smscommunicator_extendedfailed) var replyText = resourceHelper.gs(R.string.smscommunicator_extendedfailed)
replyText += "\n" + activePlugin.activePump.shortStatus(true) replyText += "\n" + activePlugin.activePump.shortStatus(true)
sendSMS(Sms(receivedSms.phoneNumber, replyText)) sendSMS(Sms(receivedSms.phoneNumber, replyText))
uel.log(Action.SMS_EXTENDED_BOLUS, activePlugin.activePump.shortStatus(true),ValueWithUnit(R.string.smscommunicator_extendedfailed, Units.R_String)) uel.log(Action.SMS_EXTENDED_BOLUS, activePlugin.activePump.shortStatus(true), ValueWithUnit(R.string.smscommunicator_extendedfailed, Units.R_String))
} }
} }
}) })
@ -883,12 +884,14 @@ class SmsCommunicatorPlugin @Inject constructor(
var replyText = String.format(resourceHelper.gs(R.string.smscommunicator_carbsset), anInteger) var replyText = String.format(resourceHelper.gs(R.string.smscommunicator_carbsset), anInteger)
replyText += "\n" + activePlugin.activePump.shortStatus(true) replyText += "\n" + activePlugin.activePump.shortStatus(true)
sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText)) sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText))
uel.log(Action.SMS_CARBS, activePlugin.activePump.shortStatus(true), ValueWithUnit(R.string.smscommunicator_carbsset, 1), ValueWithUnit(anInteger ?:0,Units.G)) uel.log(Action.SMS_CARBS, activePlugin.activePump.shortStatus(true), ValueWithUnit(R.string.smscommunicator_carbsset, 1), ValueWithUnit(anInteger
?: 0, Units.G))
} else { } else {
var replyText = resourceHelper.gs(R.string.smscommunicator_carbsfailed, anInteger) var replyText = resourceHelper.gs(R.string.smscommunicator_carbsfailed, anInteger)
replyText += "\n" + activePlugin.activePump.shortStatus(true) replyText += "\n" + activePlugin.activePump.shortStatus(true)
sendSMS(Sms(receivedSms.phoneNumber, replyText)) sendSMS(Sms(receivedSms.phoneNumber, replyText))
uel.log(Action.SMS_CARBS, activePlugin.activePump.shortStatus(true), ValueWithUnit(R.string.smscommunicator_carbsfailed, 1), ValueWithUnit(anInteger ?:0,Units.G)) uel.log(Action.SMS_CARBS, activePlugin.activePump.shortStatus(true), ValueWithUnit(R.string.smscommunicator_carbsfailed, 1), ValueWithUnit(anInteger
?: 0, Units.G))
} }
} }
}) })
@ -897,7 +900,8 @@ class SmsCommunicatorPlugin @Inject constructor(
var replyText = String.format(resourceHelper.gs(R.string.smscommunicator_carbsset), anInteger) var replyText = String.format(resourceHelper.gs(R.string.smscommunicator_carbsset), anInteger)
replyText += "\n" + activePlugin.activePump.shortStatus(true) replyText += "\n" + activePlugin.activePump.shortStatus(true)
sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText)) sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText))
uel.log(Action.SMS_CARBS, activePlugin.activePump.shortStatus(true), ValueWithUnit(R.string.smscommunicator_carbsset, 1), ValueWithUnit(anInteger ?:0,Units.G)) uel.log(Action.SMS_CARBS, activePlugin.activePump.shortStatus(true), ValueWithUnit(R.string.smscommunicator_carbsset, 1), ValueWithUnit(anInteger
?: 0, Units.G))
} }
} }
}) })

View file

@ -715,7 +715,7 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
openApsStatus = loopPlugin.getLastRun() != null && loopPlugin.getLastRun().getLastTBREnact() != 0 ? loopPlugin.getLastRun().getLastTBREnact() : -1; openApsStatus = loopPlugin.getLastRun() != null && loopPlugin.getLastRun().getLastTBREnact() != 0 ? loopPlugin.getLastRun().getLastTBREnact() : -1;
} else { } else {
//NSClient or remote //NSClient or remote
openApsStatus = NSDeviceStatus.getOpenApsTimestamp(); openApsStatus = nsDeviceStatus.getOpenApsTimestamp();
} }
PutDataMapRequest dataMapRequest = PutDataMapRequest.create(NEW_STATUS_PATH); PutDataMapRequest dataMapRequest = PutDataMapRequest.create(NEW_STATUS_PATH);

View file

@ -17,8 +17,7 @@ import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart
import info.nightscout.androidaps.plugins.profile.ns.events.EventNSProfileUpdateGUI import info.nightscout.androidaps.plugins.profile.ns.events.EventNSProfileUpdateGUI
import info.nightscout.androidaps.receivers.BundleStore import info.nightscout.androidaps.receivers.DataWorker
import info.nightscout.androidaps.receivers.DataReceiver
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.sharedPreferences.SP
import org.json.JSONObject import org.json.JSONObject
@ -89,26 +88,23 @@ class NSProfilePlugin @Inject constructor(
@Inject lateinit var nsProfilePlugin: NSProfilePlugin @Inject lateinit var nsProfilePlugin: NSProfilePlugin
@Inject lateinit var aapsLogger: AAPSLogger @Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var rxBus: RxBusWrapper @Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var bundleStore: BundleStore @Inject lateinit var dataWorker: DataWorker
init { init {
(context.applicationContext as HasAndroidInjector).androidInjector().inject(this) (context.applicationContext as HasAndroidInjector).androidInjector().inject(this)
} }
override fun doWork(): Result { override fun doWork(): Result {
val bundle = bundleStore.pickup(inputData.getLong(DataReceiver.STORE_KEY, -1)) val profileString = dataWorker.pickupJSONObject(inputData.getLong(DataWorker.STORE_KEY, -1))
?: return Result.failure() ?: return Result.failure()
bundle.getString("profile")?.let { profileString -> nsProfilePlugin.profile = ProfileStore(injector, profileString)
nsProfilePlugin.profile = ProfileStore(injector, JSONObject(profileString)) nsProfilePlugin.storeNSProfile()
nsProfilePlugin.storeNSProfile() if (nsProfilePlugin.isEnabled()) {
if (nsProfilePlugin.isEnabled()) { rxBus.send(EventProfileStoreChanged())
rxBus.send(EventProfileStoreChanged()) rxBus.send(EventNSProfileUpdateGUI())
rxBus.send(EventNSProfileUpdateGUI())
}
aapsLogger.debug(LTag.PROFILE, "Received profileStore: ${nsProfilePlugin.profile}")
return Result.success()
} }
return Result.failure() aapsLogger.debug(LTag.PROFILE, "Received profileStore: ${nsProfilePlugin.profile}")
return Result.success()
} }
} }
} }

View file

@ -21,8 +21,7 @@ import info.nightscout.androidaps.interfaces.PluginType
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.receivers.BundleStore import info.nightscout.androidaps.receivers.DataWorker
import info.nightscout.androidaps.receivers.DataReceiver
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.XDripBroadcast import info.nightscout.androidaps.utils.XDripBroadcast
@ -84,7 +83,7 @@ class DexcomPlugin @Inject constructor(
@Inject lateinit var dexcomPlugin: DexcomPlugin @Inject lateinit var dexcomPlugin: DexcomPlugin
@Inject lateinit var nsUpload: NSUpload @Inject lateinit var nsUpload: NSUpload
@Inject lateinit var sp: SP @Inject lateinit var sp: SP
@Inject lateinit var bundleStore: BundleStore @Inject lateinit var dataWorker: DataWorker
@Inject lateinit var broadcastToXDrip: XDripBroadcast @Inject lateinit var broadcastToXDrip: XDripBroadcast
@Inject lateinit var repository: AppRepository @Inject lateinit var repository: AppRepository
@ -96,7 +95,7 @@ class DexcomPlugin @Inject constructor(
var ret = Result.success() var ret = Result.success()
if (!dexcomPlugin.isEnabled(PluginType.BGSOURCE)) return Result.failure() if (!dexcomPlugin.isEnabled(PluginType.BGSOURCE)) return Result.failure()
val bundle = bundleStore.pickup(inputData.getLong(DataReceiver.STORE_KEY, -1)) val bundle = dataWorker.pickupBundle(inputData.getLong(DataWorker.STORE_KEY, -1))
?: return Result.failure() ?: return Result.failure()
try { try {
val sourceSensor = when (bundle.getString("sensorType") ?: "") { val sourceSensor = when (bundle.getString("sensorType") ?: "") {

View file

@ -17,8 +17,7 @@ import info.nightscout.androidaps.interfaces.PluginType
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.receivers.BundleStore import info.nightscout.androidaps.receivers.DataWorker
import info.nightscout.androidaps.receivers.DataReceiver
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.XDripBroadcast import info.nightscout.androidaps.utils.XDripBroadcast
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
@ -57,7 +56,7 @@ class EversensePlugin @Inject constructor(
@Inject lateinit var sp: SP @Inject lateinit var sp: SP
@Inject lateinit var nsUpload: NSUpload @Inject lateinit var nsUpload: NSUpload
@Inject lateinit var dateUtil: DateUtil @Inject lateinit var dateUtil: DateUtil
@Inject lateinit var bundleStore: BundleStore @Inject lateinit var dataWorker: DataWorker
@Inject lateinit var repository: AppRepository @Inject lateinit var repository: AppRepository
@Inject lateinit var broadcastToXDrip: XDripBroadcast @Inject lateinit var broadcastToXDrip: XDripBroadcast
@ -69,7 +68,7 @@ class EversensePlugin @Inject constructor(
var ret = Result.success() var ret = Result.success()
if (!eversensePlugin.isEnabled(PluginType.BGSOURCE)) return Result.failure() if (!eversensePlugin.isEnabled(PluginType.BGSOURCE)) return Result.failure()
val bundle = bundleStore.pickup(inputData.getLong(DataReceiver.STORE_KEY, -1)) val bundle = dataWorker.pickupBundle(inputData.getLong(DataWorker.STORE_KEY, -1))
?: return Result.failure() ?: return Result.failure()
if (bundle.containsKey("currentCalibrationPhase")) aapsLogger.debug(LTag.BGSOURCE, "currentCalibrationPhase: " + bundle.getString("currentCalibrationPhase")) if (bundle.containsKey("currentCalibrationPhase")) aapsLogger.debug(LTag.BGSOURCE, "currentCalibrationPhase: " + bundle.getString("currentCalibrationPhase"))
if (bundle.containsKey("placementModeInProgress")) aapsLogger.debug(LTag.BGSOURCE, "placementModeInProgress: " + bundle.getBoolean("placementModeInProgress")) if (bundle.containsKey("placementModeInProgress")) aapsLogger.debug(LTag.BGSOURCE, "placementModeInProgress: " + bundle.getBoolean("placementModeInProgress"))

View file

@ -15,7 +15,7 @@ import info.nightscout.androidaps.interfaces.PluginType
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.receivers.BundleStore import info.nightscout.androidaps.receivers.DataWorker
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.XDripBroadcast import info.nightscout.androidaps.utils.XDripBroadcast
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
@ -51,7 +51,7 @@ class MM640gPlugin @Inject constructor(
@Inject lateinit var sp: SP @Inject lateinit var sp: SP
@Inject lateinit var nsUpload: NSUpload @Inject lateinit var nsUpload: NSUpload
@Inject lateinit var dateUtil: DateUtil @Inject lateinit var dateUtil: DateUtil
@Inject lateinit var bundleStore: BundleStore @Inject lateinit var dataWorker: DataWorker
@Inject lateinit var repository: AppRepository @Inject lateinit var repository: AppRepository
@Inject lateinit var broadcastToXDrip: XDripBroadcast @Inject lateinit var broadcastToXDrip: XDripBroadcast

View file

@ -15,10 +15,14 @@ import info.nightscout.androidaps.interfaces.PluginDescription
import info.nightscout.androidaps.interfaces.PluginType import info.nightscout.androidaps.interfaces.PluginType
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.plugins.general.nsclient.data.NSSgv import info.nightscout.androidaps.plugins.general.nsclient.data.NSSgv
import info.nightscout.androidaps.receivers.BundleStore import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification
import info.nightscout.androidaps.receivers.DataWorker
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.XDripBroadcast import info.nightscout.androidaps.utils.XDripBroadcast
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.sharedPreferences.SP
@ -80,9 +84,10 @@ class NSClientSourcePlugin @Inject constructor(
@Inject lateinit var injector: HasAndroidInjector @Inject lateinit var injector: HasAndroidInjector
@Inject lateinit var aapsLogger: AAPSLogger @Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var sp: SP @Inject lateinit var sp: SP
@Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var nsUpload: NSUpload @Inject lateinit var nsUpload: NSUpload
@Inject lateinit var dateUtil: DateUtil @Inject lateinit var dateUtil: DateUtil
@Inject lateinit var bundleStore: BundleStore @Inject lateinit var dataWorker: DataWorker
@Inject lateinit var repository: AppRepository @Inject lateinit var repository: AppRepository
@Inject lateinit var broadcastToXDrip: XDripBroadcast @Inject lateinit var broadcastToXDrip: XDripBroadcast
@Inject lateinit var dexcomPlugin: DexcomPlugin @Inject lateinit var dexcomPlugin: DexcomPlugin
@ -109,18 +114,27 @@ class NSClientSourcePlugin @Inject constructor(
var ret = Result.success() var ret = Result.success()
if (!nsClientSourcePlugin.isEnabled() && !sp.getBoolean(R.string.key_ns_autobackfill, true) && !dexcomPlugin.isEnabled()) return Result.failure() if (!nsClientSourcePlugin.isEnabled() && !sp.getBoolean(R.string.key_ns_autobackfill, true) && !dexcomPlugin.isEnabled()) return Result.failure()
val sgvs = dataWorker.pickupJSONArray(inputData.getLong(DataWorker.STORE_KEY, -1))
?: return Result.failure()
try { try {
var latestDateInReceivedData: Long = 0
aapsLogger.debug(LTag.BGSOURCE, "Received NS Data: $sgvs")
val glucoseValues = mutableListOf<CgmSourceTransaction.TransactionGlucoseValue>() val glucoseValues = mutableListOf<CgmSourceTransaction.TransactionGlucoseValue>()
inputData.getString("sgv")?.let { sgvString -> for (i in 0 until sgvs.length()) {
aapsLogger.debug(LTag.BGSOURCE, "Received NS Data: $sgvString") val sgv = toGv(sgvs.getJSONObject(i))
glucoseValues += toGv(JSONObject(sgvString)) if (sgv.timestamp < dateUtil._now() && sgv.timestamp > latestDateInReceivedData) latestDateInReceivedData = sgv.timestamp
glucoseValues += sgv
} }
inputData.getString("sgvs")?.let { sgvString -> // Was that sgv more less 5 mins ago ?
aapsLogger.debug(LTag.BGSOURCE, "Received NS Data: $sgvString") if (T.msecs(dateUtil._now() - latestDateInReceivedData).mins() < 5L) {
val jsonArray = JSONArray(sgvString) rxBus.send(EventDismissNotification(Notification.NS_ALARM))
for (i in 0 until jsonArray.length()) rxBus.send(EventDismissNotification(Notification.NS_URGENT_ALARM))
glucoseValues += toGv(jsonArray.getJSONObject(i))
} }
repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null, !nsClientSourcePlugin.isEnabled())) repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null, !nsClientSourcePlugin.isEnabled()))
.doOnError { .doOnError {
aapsLogger.error("Error while saving values from NSClient App", it) aapsLogger.error("Error while saving values from NSClient App", it)

View file

@ -14,8 +14,7 @@ import info.nightscout.androidaps.interfaces.PluginDescription
import info.nightscout.androidaps.interfaces.PluginType import info.nightscout.androidaps.interfaces.PluginType
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.receivers.BundleStore import info.nightscout.androidaps.receivers.DataWorker
import info.nightscout.androidaps.receivers.DataReceiver
import info.nightscout.androidaps.services.Intents import info.nightscout.androidaps.services.Intents
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import javax.inject.Inject import javax.inject.Inject
@ -62,7 +61,7 @@ class XdripPlugin @Inject constructor(
@Inject lateinit var aapsLogger: AAPSLogger @Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var xdripPlugin: XdripPlugin @Inject lateinit var xdripPlugin: XdripPlugin
@Inject lateinit var repository: AppRepository @Inject lateinit var repository: AppRepository
@Inject lateinit var bundleStore: BundleStore @Inject lateinit var dataWorker: DataWorker
init { init {
(context.applicationContext as HasAndroidInjector).androidInjector().inject(this) (context.applicationContext as HasAndroidInjector).androidInjector().inject(this)
@ -72,7 +71,7 @@ class XdripPlugin @Inject constructor(
var ret = Result.success() var ret = Result.success()
if (!xdripPlugin.isEnabled(PluginType.BGSOURCE)) return Result.failure() if (!xdripPlugin.isEnabled(PluginType.BGSOURCE)) return Result.failure()
val bundle = bundleStore.pickup(inputData.getLong(DataReceiver.STORE_KEY, -1)) val bundle = dataWorker.pickupBundle(inputData.getLong(DataWorker.STORE_KEY, -1))
?: return Result.failure() ?: return Result.failure()
aapsLogger.debug(LTag.BGSOURCE, "Received xDrip data: $bundle") aapsLogger.debug(LTag.BGSOURCE, "Received xDrip data: $bundle")

View file

@ -1,24 +0,0 @@
package info.nightscout.androidaps.receivers
import android.os.Bundle
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class BundleStore @Inject constructor() {
private val store = HashMap<Long, Bundle>()
private var counter = 0L
@Synchronized
fun store(bundle: Bundle) : Long {
store.put(counter, bundle)
return counter++
}
@Synchronized
fun pickup(key: Long) : Bundle? {
val bundle = store[key]
store.remove(key)
return bundle
}
}

View file

@ -2,20 +2,15 @@ package info.nightscout.androidaps.receivers
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.os.Bundle
import android.provider.Telephony import android.provider.Telephony
import androidx.work.Data import androidx.work.Data
import androidx.work.ExistingWorkPolicy
import androidx.work.OneTimeWorkRequest import androidx.work.OneTimeWorkRequest
import androidx.work.WorkManager
import dagger.android.DaggerBroadcastReceiver import dagger.android.DaggerBroadcastReceiver
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.BundleLogger import info.nightscout.androidaps.logging.BundleLogger
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.general.food.FoodPlugin
import info.nightscout.androidaps.plugins.general.nsclient.NSClientWorker import info.nightscout.androidaps.plugins.general.nsclient.NSClientWorker
import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin
import info.nightscout.androidaps.plugins.profile.ns.NSProfilePlugin
import info.nightscout.androidaps.plugins.source.* import info.nightscout.androidaps.plugins.source.*
import info.nightscout.androidaps.services.Intents import info.nightscout.androidaps.services.Intents
import info.nightscout.androidaps.utils.extensions.copyDouble import info.nightscout.androidaps.utils.extensions.copyDouble
@ -27,9 +22,7 @@ import javax.inject.Inject
open class DataReceiver : DaggerBroadcastReceiver() { open class DataReceiver : DaggerBroadcastReceiver() {
@Inject lateinit var aapsLogger: AAPSLogger @Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var bundleStore: BundleStore @Inject lateinit var dataWorker: DataWorker
private val jobGroupName = "data"
override fun onReceive(context: Context, intent: Intent) { override fun onReceive(context: Context, intent: Intent) {
super.onReceive(context, intent) super.onReceive(context, intent)
@ -40,7 +33,7 @@ open class DataReceiver : DaggerBroadcastReceiver() {
when (intent.action) { when (intent.action) {
Intents.ACTION_NEW_BG_ESTIMATE -> Intents.ACTION_NEW_BG_ESTIMATE ->
OneTimeWorkRequest.Builder(XdripPlugin.XdripWorker::class.java) OneTimeWorkRequest.Builder(XdripPlugin.XdripWorker::class.java)
.setInputData(bundleInputData(bundle, intent)).build() .setInputData(dataWorker.storeInputData(bundle, intent)).build()
Intents.POCTECH_BG -> Intents.POCTECH_BG ->
OneTimeWorkRequest.Builder(PoctechPlugin.PoctechWorker::class.java) OneTimeWorkRequest.Builder(PoctechPlugin.PoctechWorker::class.java)
.setInputData(Data.Builder().also { .setInputData(Data.Builder().also {
@ -54,20 +47,12 @@ open class DataReceiver : DaggerBroadcastReceiver() {
it.copyLong("myTimestamp", bundle) it.copyLong("myTimestamp", bundle)
}.build()).build() }.build()).build()
Intents.TOMATO_BG -> Intents.TOMATO_BG ->
@Suppress("SpellCheckingInspection")
OneTimeWorkRequest.Builder(TomatoPlugin.TomatoWorker::class.java) OneTimeWorkRequest.Builder(TomatoPlugin.TomatoWorker::class.java)
.setInputData(Data.Builder().also { .setInputData(Data.Builder().also {
it.copyDouble("com.fanqies.tomatofn.Extras.BgEstimate", bundle) it.copyDouble("com.fanqies.tomatofn.Extras.BgEstimate", bundle)
it.copyLong("com.fanqies.tomatofn.Extras.Time", bundle) it.copyLong("com.fanqies.tomatofn.Extras.Time", bundle)
}.build()).build() }.build()).build()
Intents.ACTION_NEW_PROFILE ->
OneTimeWorkRequest.Builder(NSProfilePlugin.NSProfileWorker::class.java)
.setInputData(bundleInputData(bundle, intent)).build()
Intents.ACTION_NEW_SGV ->
OneTimeWorkRequest.Builder(NSClientSourcePlugin.NSClientSourceWorker::class.java)
.setInputData(Data.Builder().also {
it.copyString("sgv", bundle, null)
it.copyString("sgvs", bundle, null)
}.build()).build()
Intents.NS_EMULATOR -> Intents.NS_EMULATOR ->
OneTimeWorkRequest.Builder(MM640gPlugin.MM640gWorker::class.java) OneTimeWorkRequest.Builder(MM640gPlugin.MM640gWorker::class.java)
.setInputData(Data.Builder().also { .setInputData(Data.Builder().also {
@ -80,36 +65,22 @@ open class DataReceiver : DaggerBroadcastReceiver() {
}.build()).build() }.build()).build()
Telephony.Sms.Intents.SMS_RECEIVED_ACTION -> Telephony.Sms.Intents.SMS_RECEIVED_ACTION ->
OneTimeWorkRequest.Builder(SmsCommunicatorPlugin.SmsCommunicatorWorker::class.java) OneTimeWorkRequest.Builder(SmsCommunicatorPlugin.SmsCommunicatorWorker::class.java)
.setInputData(bundleInputData(bundle, intent)).build() .setInputData(dataWorker.storeInputData(bundle, intent)).build()
Intents.EVERSENSE_BG -> Intents.EVERSENSE_BG ->
OneTimeWorkRequest.Builder(EversensePlugin.EversenseWorker::class.java) OneTimeWorkRequest.Builder(EversensePlugin.EversenseWorker::class.java)
.setInputData(bundleInputData(bundle, intent)).build() .setInputData(dataWorker.storeInputData(bundle, intent)).build()
Intents.DEXCOM_BG -> Intents.DEXCOM_BG ->
OneTimeWorkRequest.Builder(DexcomPlugin.DexcomWorker::class.java) OneTimeWorkRequest.Builder(DexcomPlugin.DexcomWorker::class.java)
.setInputData(bundleInputData(bundle, intent)).build() .setInputData(dataWorker.storeInputData(bundle, intent)).build()
Intents.ACTION_FOOD ->
OneTimeWorkRequest.Builder(FoodPlugin.FoodWorker::class.java)
.setInputData(bundleInputData(bundle, intent)).build()
Intents.ACTION_NEW_TREATMENT, Intents.ACTION_NEW_TREATMENT,
Intents.ACTION_CHANGED_TREATMENT, Intents.ACTION_CHANGED_TREATMENT,
Intents.ACTION_REMOVED_TREATMENT, Intents.ACTION_REMOVED_TREATMENT,
Intents.ACTION_NEW_CAL, Intents.ACTION_NEW_CAL,
Intents.ACTION_NEW_MBG -> Intents.ACTION_NEW_MBG ->
OneTimeWorkRequest.Builder(NSClientWorker::class.java) OneTimeWorkRequest.Builder(NSClientWorker::class.java)
.setInputData(bundleInputData(bundle, intent)).build() .setInputData(dataWorker.storeInputData(bundle, intent)).build()
else -> null else -> null
}?.let { request -> }?.let { request -> dataWorker.enqueue(request) }
WorkManager.getInstance(context)
.enqueueUniqueWork(jobGroupName, ExistingWorkPolicy.APPEND_OR_REPLACE, request)
}
} }
private fun bundleInputData(bundle: Bundle, intent: Intent) =
Data.Builder().putLong(STORE_KEY, bundleStore.store(bundle)).putString(ACTION_KEY, intent.action).build()
companion object {
const val STORE_KEY = "storeKey"
const val ACTION_KEY = "action"
}
} }

View file

@ -0,0 +1,70 @@
package info.nightscout.androidaps.receivers
import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.work.Data
import androidx.work.ExistingWorkPolicy
import androidx.work.OneTimeWorkRequest
import androidx.work.WorkManager
import org.json.JSONArray
import org.json.JSONObject
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class DataWorker @Inject constructor(
private val context: Context
) {
private val store = HashMap<Long, Any>()
private var counter = 0L
private val jobGroupName = "data"
@Synchronized private fun store(value: Any): Long {
store[counter] = value
return counter++
}
@Synchronized fun pickupBundle(key: Long): Bundle? {
val value = store[key]
store.remove(key)
return value as Bundle?
}
@Synchronized fun pickupString(key: Long): String? {
val value = store[key]
store.remove(key)
return value as String?
}
@Synchronized fun pickupJSONArray(key: Long): JSONArray? {
val value = store[key]
store.remove(key)
return value as JSONArray?
}
@Synchronized fun pickupJSONObject(key: Long): JSONObject? {
val value = store[key]
store.remove(key)
return value as JSONObject?
}
fun storeInputData(value: Any, intent: Intent? = null) =
Data.Builder()
.putLong(STORE_KEY, store(value))
.putString(ACTION_KEY, intent?.action).build()
fun enqueue(request: OneTimeWorkRequest) {
WorkManager.getInstance(context)
.enqueueUniqueWork(jobGroupName, ExistingWorkPolicy.APPEND_OR_REPLACE, request)
}
companion object {
const val STORE_KEY = "storeKey"
const val ACTION_KEY = "action"
}
}

View file

@ -5,7 +5,7 @@ interface Intents {
companion object { companion object {
// NSClient -> App // AAPS -> Xdrip
const val ACTION_NEW_TREATMENT = "info.nightscout.client.NEW_TREATMENT" const val ACTION_NEW_TREATMENT = "info.nightscout.client.NEW_TREATMENT"
const val ACTION_CHANGED_TREATMENT = "info.nightscout.client.CHANGED_TREATMENT" const val ACTION_CHANGED_TREATMENT = "info.nightscout.client.CHANGED_TREATMENT"
const val ACTION_REMOVED_TREATMENT = "info.nightscout.client.REMOVED_TREATMENT" const val ACTION_REMOVED_TREATMENT = "info.nightscout.client.REMOVED_TREATMENT"
@ -13,9 +13,8 @@ interface Intents {
const val ACTION_NEW_SGV = "info.nightscout.client.NEW_SGV" const val ACTION_NEW_SGV = "info.nightscout.client.NEW_SGV"
const val ACTION_NEW_MBG = "info.nightscout.client.NEW_MBG" const val ACTION_NEW_MBG = "info.nightscout.client.NEW_MBG"
const val ACTION_NEW_CAL = "info.nightscout.client.NEW_CAL" const val ACTION_NEW_CAL = "info.nightscout.client.NEW_CAL"
const val ACTION_FOOD = "info.nightscout.client.FOOD"
// xDrip -> App // xDrip -> AAPS
const val ACTION_NEW_BG_ESTIMATE = "com.eveningoutpost.dexdrip.BgEstimate" const val ACTION_NEW_BG_ESTIMATE = "com.eveningoutpost.dexdrip.BgEstimate"
const val EXTRA_BG_ESTIMATE = "com.eveningoutpost.dexdrip.Extras.BgEstimate" const val EXTRA_BG_ESTIMATE = "com.eveningoutpost.dexdrip.Extras.BgEstimate"
const val EXTRA_BG_SLOPE = "com.eveningoutpost.dexdrip.Extras.BgSlope" const val EXTRA_BG_SLOPE = "com.eveningoutpost.dexdrip.Extras.BgSlope"

View file

@ -13,7 +13,7 @@ enum class LTag(val tag: String, val defaultValue : Boolean = true, val requires
DATASERVICE("DATASERVICE"), DATASERVICE("DATASERVICE"),
DATATREATMENTS("DATATREATMENTS"), DATATREATMENTS("DATATREATMENTS"),
EVENTS("EVENTS", defaultValue = false, requiresRestart = true), EVENTS("EVENTS", defaultValue = false, requiresRestart = true),
GLUCOSE("GLUCOSE"), GLUCOSE("GLUCOSE", defaultValue = false),
LOCATION("LOCATION"), LOCATION("LOCATION"),
NOTIFICATION("NOTIFICATION"), NOTIFICATION("NOTIFICATION"),
NSCLIENT("NSCLIENT"), NSCLIENT("NSCLIENT"),