Merge pull request #10 from jotomo/combo-scripter-v2

dev
This commit is contained in:
Simon Pauwels 2017-12-19 22:16:56 +01:00 committed by GitHub
commit f4b36ae095
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 86 additions and 32 deletions

View file

@ -9,10 +9,10 @@ Hardware requirements:
- A Roche Accu-Chek Combo (any firmware, they all work) - A Roche Accu-Chek Combo (any firmware, they all work)
- A Smartpix or Realtyme device together with the 360 Configuration - A Smartpix or Realtyme device together with the 360 Configuration
Software to configure the pump. Software to configure the pump.
Roche sends these out Smartpix devices and the configuration software Roche sends out Smartpix devices and the configuration software
free of charge to their customers upon request. free of charge to their customers upon request.
- A compatible phone: An Android phone with a phone running LineageOS 14.1 (formerly CyanogenMod) - A compatible phone: An Android phone with a phone running LineageOS 14.1 (formerly CyanogenMod)
- To build AndroidAPS with Combo support you need the lastet Android Studio 3 version - To build AndroidAPS with Combo support you need the latest Android Studio 3 version
Limitations: Limitations:
- Extended bolus and multiwave bolus are not supported. - Extended bolus and multiwave bolus are not supported.
@ -24,10 +24,11 @@ Limitations:
changes have to be performed manually. changes have to be performed manually.
- There's a bug in the pump's firmware that's triggered when "too much" communication happens - There's a bug in the pump's firmware that's triggered when "too much" communication happens
with the pump. Specifically, this issue occurs when going from just issuing commands to the pump with the pump. Specifically, this issue occurs when going from just issuing commands to the pump
to reading the pumps data and history. For that reason, a minimal amount of data is read from to reading the pump's data and history. For that reason, a minimal amount of data is read from
the pump. the pump.
The bug might still rarely occur and causes the pump to not accept any connection The bug might still rarely occur and causes the pump to not accept any connection
unless a button is physically pressed on the pump. unless a button is physically pressed on the pump (make sure the 'pump unreachable' alert is enabled
so you'll get an alarm if the bug occurs.
Therefore, the pump's reservoir level is not read and the pump status information uploaded to Nightscout Therefore, the pump's reservoir level is not read and the pump status information uploaded to Nightscout
shows fake numbers of 150 (above low threshold - which can be configured via the configuration shows fake numbers of 150 (above low threshold - which can be configured via the configuration
tool), 8 (below low threshold, triggers NS alarm since < 10) and 0 if the reservoir is empty. tool), 8 (below low threshold, triggers NS alarm since < 10) and 0 if the reservoir is empty.
@ -48,20 +49,20 @@ Setup:
- Set maximum TBR to 500% - Set maximum TBR to 500%
- Disable end of TBR alert - Disable end of TBR alert
- Set TBR duration step-size to 15 min - Set TBR duration step-size to 15 min
- Set low cartridge alarm to your licking - Set low cartridge alarm to your liking
- Enable keylock (can also be set on the pump directly, see usage section on reasoning) - Enable keylock (can also be set on the pump directly, see usage section on reasoning)
- Get Android Studio 3 - Get Android Studio 3 https://developer.android.com/studio/index.html
- Get ruffy from https://github.com/jotomo/ruffy (branch `combo-scripter-v2`) - Clone ruffy from https://github.com/jotomo/ruffy (branch `combo-scripter-v2`)
- Pair the pump, if it doesn't work, switch to the `pairing` branch, pair, - Pair the pump, if it doesn't work after multiple attempts, switch to the `pairing` branch, pair,
then switch back the original branch. If the pump is already paired and then switch back the original branch. If the pump is already paired and
can be controlled via ruffy, installing the above version is sufficient. can be controlled via ruffy, installing the above version is sufficient.
If AAPS is already installed, switch to the MDI plugin to avoid the Combo If AAPS is already installed, switch to the MDI plugin to avoid the Combo
plugin from interfering with ruffy during the pairing process. plugin from interfering with ruffy during the pairing process.
Note that the pairing processing is somewhat fragile and may need a few attempts; Note that the pairing processing is somewhat fragile and may need a few attempts;
quickly acknowledge prompts and when starting over, remove the pump device quickly acknowledge prompts and when starting over, remove the pump device
from the bluetooth settings beforehand from the bluetooth settings beforehand.
- Get AndroidAPS from https://github.com/jotomo/AndroidAPS (Branch `combo-scripter-v2`) - Clone AndroidAPS from https://github.com/jotomo/AndroidAPS (Branch `combo-scripter-v2`)
- Before enabling the Combo plugin in AAPS make sure you're profile is set up - Before enabling the Combo plugin in AAPS make sure your profile is set up
correctly and your basal profile is up to date as AAPS will sync the basal profile correctly and your basal profile is up to date as AAPS will sync the basal profile
to the pump. to the pump.

View file

@ -228,6 +228,9 @@ public class DataService extends IntentService {
if (isNew && SP.getBoolean(R.string.key_dexcomg5_nsupload, false)) { if (isNew && SP.getBoolean(R.string.key_dexcomg5_nsupload, false)) {
NSUpload.uploadBg(bgReading); NSUpload.uploadBg(bgReading);
} }
if (isNew && SP.getBoolean(R.string.key_dexcomg5_xdripupload, false)) {
NSUpload.sendToXdrip(bgReading);
}
} }
} catch (JSONException e) { } catch (JSONException e) {

View file

@ -159,12 +159,16 @@ public class Profile {
LongSparseArray<Double> sparse = new LongSparseArray<>(); LongSparseArray<Double> sparse = new LongSparseArray<>();
for (Integer index = 0; index < array.length(); index++) { for (Integer index = 0; index < array.length(); index++) {
try { try {
JSONObject o = array.getJSONObject(index); final JSONObject o = array.getJSONObject(index);
long tas = getShitfTimeSecs((int) o.getLong("timeAsSeconds")); long tas = getShitfTimeSecs((int) o.getLong("timeAsSeconds"));
Double value = o.getDouble("value") * multiplier; Double value = o.getDouble("value") * multiplier;
sparse.put(tas, value); sparse.put(tas, value);
} catch (JSONException e) { } catch (JSONException e) {
log.error("Unhandled exception", e); log.error("Unhandled exception", e);
try {
log.error(array.getJSONObject(index).toString());
} catch (JSONException e1) {
}
} }
} }

View file

@ -69,11 +69,6 @@ public class NotificationStore {
} }
} }
WearPlugin wearPlugin = MainApp.getSpecificPlugin(WearPlugin.class);
if (wearPlugin != null && wearPlugin.isEnabled()) {
wearPlugin.overviewNotification(n.id, "OverviewNotification:\n" + n.text);
}
Collections.sort(store, new NotificationComparator()); Collections.sort(store, new NotificationComparator());
} }

View file

@ -80,7 +80,7 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
pumpDescription.tempMaxDuration = 24 * 60; pumpDescription.tempMaxDuration = 24 * 60;
pumpDescription.isSetBasalProfileCapable = false; pumpDescription.isSetBasalProfileCapable = true;
pumpDescription.basalStep = 0.01d; pumpDescription.basalStep = 0.01d;
pumpDescription.basalMinimumRate = 0.0d; pumpDescription.basalMinimumRate = 0.0d;

View file

@ -185,7 +185,7 @@ public class DanaRSService extends Service {
while (!msg.done && bleComm.isConnected()) { while (!msg.done && bleComm.isConnected()) {
SystemClock.sleep(100); SystemClock.sleep(100);
} }
lastHistoryFetched = DanaRS_Packet_APS_History_Events.lastEventTimeLoaded; lastHistoryFetched = DanaRS_Packet_APS_History_Events.lastEventTimeLoaded - 45 * 60 * 1000L; // always load last 45 min
log.debug("Events loaded"); log.debug("Events loaded");
return new PumpEnactResult().success(true); return new PumpEnactResult().success(true);
} }

View file

@ -527,7 +527,7 @@ public class DanaRv2ExecutionService extends Service {
waitMsec(100); waitMsec(100);
} }
waitMsec(200); waitMsec(200);
lastHistoryFetched = MsgHistoryEvents_v2.lastEventTimeLoaded; lastHistoryFetched = MsgHistoryEvents_v2.lastEventTimeLoaded - 45 * 60 * 1000L; //always load last 45 min;
return new PumpEnactResult().success(true); return new PumpEnactResult().success(true);
} }

View file

@ -153,6 +153,10 @@ public class CommandQueue {
// remove all unfinished boluses // remove all unfinished boluses
removeAll(Command.CommandType.BOLUS); removeAll(Command.CommandType.BOLUS);
// apply constraints
detailedBolusInfo.insulin = MainApp.getConfigBuilder().applyBolusConstraints(detailedBolusInfo.insulin);
detailedBolusInfo.carbs = MainApp.getConfigBuilder().applyCarbsConstraints((int) detailedBolusInfo.carbs);
// add new command to queue // add new command to queue
add(new CommandBolus(detailedBolusInfo, callback)); add(new CommandBolus(detailedBolusInfo, callback));
@ -161,14 +165,9 @@ public class CommandQueue {
// Notify Wear about upcoming bolus // Notify Wear about upcoming bolus
MainApp.bus().post(new EventBolusRequested(detailedBolusInfo.insulin)); MainApp.bus().post(new EventBolusRequested(detailedBolusInfo.insulin));
// Apply constraints
detailedBolusInfo.insulin = MainApp.getConfigBuilder().applyBolusConstraints(detailedBolusInfo.insulin);
detailedBolusInfo.carbs = MainApp.getConfigBuilder().applyCarbsConstraints((int) detailedBolusInfo.carbs);
// Bring up bolus progress dialog // Bring up bolus progress dialog
BolusProgressDialog bolusProgressDialog = null;
if (detailedBolusInfo.context != null) { if (detailedBolusInfo.context != null) {
bolusProgressDialog = new BolusProgressDialog(); BolusProgressDialog bolusProgressDialog = new BolusProgressDialog();
bolusProgressDialog.setInsulin(detailedBolusInfo.insulin); bolusProgressDialog.setInsulin(detailedBolusInfo.insulin);
bolusProgressDialog.show(((AppCompatActivity) detailedBolusInfo.context).getSupportFragmentManager(), "BolusProgress"); bolusProgressDialog.show(((AppCompatActivity) detailedBolusInfo.context).getSupportFragmentManager(), "BolusProgress");
} else { } else {

View file

@ -3,33 +3,37 @@ package info.nightscout.utils;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.pm.ResolveInfo;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
import java.util.List;
import java.util.Locale;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.Services.Intents; import info.nightscout.androidaps.Services.Intents;
import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.db.CareportalEvent; import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.db.ExtendedBolus; import info.nightscout.androidaps.db.ExtendedBolus;
import info.nightscout.androidaps.db.ProfileSwitch; import info.nightscout.androidaps.db.ProfileSwitch;
import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Loop.APSResult; import info.nightscout.androidaps.plugins.Loop.APSResult;
import info.nightscout.androidaps.plugins.Loop.DeviceStatus; import info.nightscout.androidaps.plugins.Loop.DeviceStatus;
import info.nightscout.androidaps.plugins.Loop.LoopPlugin; import info.nightscout.androidaps.plugins.Loop.LoopPlugin;
import info.nightscout.androidaps.plugins.NSClientInternal.data.DbLogger; import info.nightscout.androidaps.plugins.NSClientInternal.data.DbLogger;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.plugins.OpenAPSAMA.DetermineBasalResultAMA; import info.nightscout.androidaps.plugins.OpenAPSAMA.DetermineBasalResultAMA;
import info.nightscout.androidaps.plugins.OpenAPSMA.DetermineBasalResultMA; import info.nightscout.androidaps.plugins.OpenAPSMA.DetermineBasalResultMA;
@ -449,4 +453,44 @@ public class NSUpload {
} }
public static void sendToXdrip(BgReading bgReading) {
final String XDRIP_PLUS_NS_EMULATOR = "com.eveningoutpost.dexdrip.NS_EMULATOR";
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.US);
try {
final JSONArray entriesBody = new JSONArray();
JSONObject json = new JSONObject();
json.put("sgv", bgReading.value);
if (bgReading.direction == null) {
json.put("direction", "NONE");
} else {
json.put("direction", bgReading.direction);
}
json.put("device", "G5");
json.put("type", "sgv");
json.put("date", bgReading.date);
json.put("dateString", format.format(bgReading.date));
entriesBody.put(json);
final Bundle bundle = new Bundle();
bundle.putString("action", "add");
bundle.putString("collection", "entries");
bundle.putString("data", entriesBody.toString());
final Intent intent = new Intent(XDRIP_PLUS_NS_EMULATOR);
intent.putExtras(bundle).addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
MainApp.instance().sendBroadcast(intent);
List<ResolveInfo> receivers = MainApp.instance().getPackageManager().queryBroadcastReceivers(intent, 0);
if (receivers.size() < 1) {
log.debug("No xDrip receivers found. ");
} else {
log.debug(receivers.size() + " xDrip receivers");
}
} catch (JSONException e) {
e.printStackTrace();
}
}
} }

View file

@ -787,6 +787,9 @@
<string name="wear_detailed_delta_title">Show detailed delta</string> <string name="wear_detailed_delta_title">Show detailed delta</string>
<string name="wear_detailed_delta_summary">Show delta with one more decimal place</string> <string name="wear_detailed_delta_summary">Show delta with one more decimal place</string>
<string name="unsupportedfirmware">Unsupported pump firmware</string> <string name="unsupportedfirmware">Unsupported pump firmware</string>
<string name="dexcomg5_xdripupload_title">Send BG data to xDrip+</string>
<string name="key_dexcomg5_xdripupload" translatable="false">dexcomg5_xdripupload</string>
<string name="dexcomg5_xdripupload_summary">In xDrip+ select 640g/Eversense data source</string>
<string name="bolusstopping">Stopping bolus delivery</string> <string name="bolusstopping">Stopping bolus delivery</string>
<string name="bolusstopped">Bolus delivery stopped</string> <string name="bolusstopped">Bolus delivery stopped</string>
<string name="combo_programming_bolus">Programming pump for bolusing</string> <string name="combo_programming_bolus">Programming pump for bolusing</string>

View file

@ -9,6 +9,12 @@
android:key="@string/key_dexcomg5_nsupload" android:key="@string/key_dexcomg5_nsupload"
android:title="@string/dexcomg5_nsupload_title" /> android:title="@string/dexcomg5_nsupload_title" />
<SwitchPreference
android:defaultValue="false"
android:key="@string/key_dexcomg5_xdripupload"
android:summary="@string/dexcomg5_xdripupload_summary"
android:title="@string/dexcomg5_xdripupload_title" />
</PreferenceCategory> </PreferenceCategory>
</PreferenceScreen> </PreferenceScreen>

View file

@ -124,9 +124,8 @@ public class SetTbrCommand extends BaseCommand {
scripter.waitForScreenUpdate(); scripter.waitForScreenUpdate();
state = scripter.readPumpStateInternal(); state = scripter.readPumpStateInternal();
} }
// if we waited above and a cancellation (fake or hard) was requested, // if we waited above and a cancellation was requested, we already completed the request
// we already completed the request if (!state.tbrActive && percentage == 100) {
if (!state.tbrActive && percentage >= 90 && percentage <= 110) {
result.success = true; result.success = true;
return true; return true;
} }