commit
0092a1fa95
73 changed files with 948 additions and 1014 deletions
171
README-Combo.md
171
README-Combo.md
|
@ -2,10 +2,12 @@
|
|||
requires YOU to read, learn and understand the system and how to use it.
|
||||
It is not something that does all your diabetes management for you, but
|
||||
allows you to improve your diabetes and quality of life significantly
|
||||
if you're willing to put in the time required.
|
||||
You alone are responsible for what you do with it.**
|
||||
if you're willing to put in the time required. Don't rush into it,
|
||||
but allow yourself time to learn. You alone are responsible for what
|
||||
you do with it.**
|
||||
|
||||
Hardware requirements:
|
||||
Hardware requirements
|
||||
---------------------
|
||||
- A Roche Accu-Chek Combo (any firmware, they all work)
|
||||
- A Smartpix or Realtyme device together with the 360 Configuration
|
||||
Software to configure the pump.
|
||||
|
@ -18,58 +20,58 @@ Hardware requirements:
|
|||
has not been widely tested: https://github.com/gregorybel/combo-pairing/blob/master/README.md
|
||||
- To build AndroidAPS with Combo support you need the latest Android Studio 3 version
|
||||
|
||||
Limitations:
|
||||
Limitations
|
||||
-----------
|
||||
- Extended bolus and multiwave bolus are not supported.
|
||||
- Only one basal profile is supported.
|
||||
- Setting a basal profile other than 1 on the pump, or delivering extended boluses or multiwave
|
||||
boluses from the pump interferes with TBRs and forces the loop into low-suspend only mode for 6 hours
|
||||
as the the loop can't run safely under those conditions.
|
||||
- It's currently not possible to set the time and date on the pump, so daylight saving times
|
||||
changes have to be performed manually.
|
||||
- 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
|
||||
to reading the pump's data and history. For that reason, a minimal amount of data is read from
|
||||
the pump.
|
||||
The bug might still rarely occur and causes the pump to not accept any connection
|
||||
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
|
||||
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.
|
||||
Furthermore, no history (from the My Data menu) is read unless absolutely required.
|
||||
Reading all pump data can be forced through the Combo tab, to import
|
||||
events that happened solely on the pump, but that code has been tested less, might cause duplicates and may
|
||||
trigger the bug, so it's strongly recommended to stick to the usage scenario of controlling the
|
||||
pump solely through AAPS.
|
||||
Checking history, reservoir level etc on the pump causes no issues but should be avoided
|
||||
when the Bluetooth icon is displayed on the display, indicating that AAPS is communicating with the pump.
|
||||
changes have to be performed manually (disable automatic phone clock update in the evening and
|
||||
update change back in the morning while also updating the pump's clock to avoid an alarm during the night).
|
||||
- Currently only basal rates in the range of 0.05 to 10 U/h are supported (this also applies when modifying
|
||||
a profile, e.g. when increasing to 200%, the highest basal rate must not exceed 5 U/h since it will be
|
||||
doubled. Similarly, when reducing to 50%, the lowest basal rate must be at least 0.10 U/h).
|
||||
- If the loop requests a running TBR to be cancelled the Combo will set a TBR of 90% or 110%
|
||||
for 15 minutes instead. This is because cancelling a TBR causes an alert on the pump which
|
||||
causes a lot of vibrations.
|
||||
- Occasionally (every couple of days or so) AAPS might fail to automatically cancel
|
||||
a TBR CANCELLED alert the user then needs to deal with (press the refresh button in AAPS
|
||||
to transfer the warning to AAPS or confirm the alert on the pump).
|
||||
|
||||
Setup:
|
||||
Setup
|
||||
-----
|
||||
- Configure pump using 360 config software.
|
||||
- Set/leave the menu configuration as "Standard", this will show only the supported
|
||||
menus/actions on the pump and hide those which are unsupported (extended/multiwave bolus,
|
||||
multiple basal rates), which cause the loop functionality to be restricted when used because
|
||||
it's not possible to run the loop in a safe manner when used.
|
||||
- Verify the _Quick Info Text_ is set to "QUICK INFO" (without the quotes, found under _Insulin Pump Options_).
|
||||
- Set maximum TBR to 500%
|
||||
- Disable end of TBR alert
|
||||
- Set TBR duration step-size to 15 min
|
||||
- Set low cartridge alarm to your liking
|
||||
- Configure a max bolus suited for your therapy to protect against bugs in the software
|
||||
- Similarly, configure maximum TBR duration as a safeguard. Allow at least 3 hours, since
|
||||
the option to disconnect the pump for 3 hours sets a 0% for 3 hours.
|
||||
- Enable keylock (can also be set on the pump directly, see usage section on reasoning)
|
||||
- Get Android Studio 3 https://developer.android.com/studio/index.html
|
||||
- Follow the link http://ruffy.AndroidAPS.org and clone via git (branch `combo-scripter-v2`)
|
||||
- Required:
|
||||
- Set/leave the menu configuration as "Standard", this will show only the supported
|
||||
menus/actions on the pump and hide those which are unsupported (extended/multiwave bolus,
|
||||
multiple basal rates), which cause the loop functionality to be restricted when used because
|
||||
it's not possible to run the loop in a safe manner when used.
|
||||
- Verify the _Quick Info Text_ is set to "QUICK INFO" (without the quotes, found under _Insulin Pump Options_).
|
||||
- Set maximum TBR to 500%
|
||||
- Disable end of TBR alert
|
||||
- Set TBR duration step-size to 15 min
|
||||
- Recommended:
|
||||
- Set low cartridge alarm to your liking
|
||||
- Configure a max bolus suited for your therapy to protect against bugs in the software
|
||||
- Similarly, configure maximum TBR duration as a safeguard. Allow at least 3 hours, since
|
||||
the option to disconnect the pump for 3 hours sets a 0% for 3 hours.
|
||||
- Enable key lock on the pump to prevent bolusing from the pump, esp. when the
|
||||
pump was used before and quick bolusing was a habit.
|
||||
- Set display timeout and menu timeout to the mininum of 5.5 and 5 respectively. This allows the AAPS to
|
||||
recover more quickly from error situations and reduces the amount of vibrations that can occur during
|
||||
such errors
|
||||
- Install AndroidAPS as described in the wiki http://wiki.AndroidAPS.org
|
||||
- Make sure to read the wiki to understand how to setup AndroidAPS.
|
||||
- Select the MDI plugin in AndroidAPS, not the Combo plugin at this point to avoid the Combo
|
||||
plugin from interfering with ruffy during the pairing process.
|
||||
- Follow the link http://ruffy.AndroidAPS.org and clone ruffy via git. Use the same branch as you use for
|
||||
AndroidAPS, which is usally `master`.
|
||||
if you you want to help test the in-development version.
|
||||
- Pair the pump using ruffy. If it doesn't work after multiple attempts, switch to the `pairing` branch,
|
||||
pair the pump and then switch back the original branch.
|
||||
If the pump is already paired and can be controlled via ruffy, installing the
|
||||
`combo-scripter-v2` branch is sufficient.
|
||||
If AAPS is already installed, switch to the MDI plugin to avoid the Combo
|
||||
plugin from interfering with ruffy during the pairing process.
|
||||
If the pump is already paired and can be controlled via ruffy, installing the `master` branch is sufficient.
|
||||
Note that the pairing processing is somewhat fragile (but only has to be done once)
|
||||
and may need a few attempts; quickly acknowledge prompts and when starting over, remove the pump device
|
||||
from the bluetooth settings beforehand. Another option to try is to go to the bluetooth menu after
|
||||
|
@ -77,35 +79,40 @@ Setup:
|
|||
and switch back to ruffy after confirming the pairing on the pump, when the pump displays the authorization code.
|
||||
When AAPS is using ruffy, the ruffy app can't be used. The easiest way is to just
|
||||
reboot the phone after the pairing process and let AAPS start ruffy in the background.
|
||||
- Clone AndroidAPS from https://github.com/jotomo/AndroidAPS (branch `combo-scripter-v2`)
|
||||
and build AAPS using the instructions in the wiki http://wiki.AndroidAPS.org
|
||||
- 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
|
||||
to the pump.
|
||||
to the pump. Then activate the Combo plugin.
|
||||
|
||||
Usage:
|
||||
Usage
|
||||
-----
|
||||
- Keep in mind that this is not a product, esp. in the beginning the user needs to monitor and understand the system,
|
||||
its limitations and how it can fail. It is strongly advised NOT to use this system when the person
|
||||
using is not able to fully understand the system.
|
||||
using it is not able to fully understand the system.
|
||||
- Read the OpenAPS documentation https://openaps.org to understand the loop algorithm AndroidAPS
|
||||
is based upon.
|
||||
- Read in the wiki to learn about and understand AndroidAPS http://wiki.AndroidAPS.org
|
||||
- This integration uses the same functionality which the meter provides that comes with the Combo.
|
||||
The meter allows to mirror the pump screen and forwards button presses to the pump. The connection
|
||||
to the pump and this forwarding is what the ruffy app does. A `scripter` components reads the screen
|
||||
and automates inputing boluses, TBRs etc and making sure inputs are processed correctly (that's what
|
||||
the scripter-part in the branch name stands for).
|
||||
and automates inputing boluses, TBRs etc and making sure inputs are processed correctly.
|
||||
AAPS then interacts with the scripter to apply loop commands and to administer boluses.
|
||||
This mode has some restrictions: it's comparatively slow (but well fast enough for what it is used for),
|
||||
doesn't support reading history continuously and setting a TBR or giving a bolus causes the pump to
|
||||
vibrate.
|
||||
and setting a TBR or giving a bolus causes the pump to vibrate.
|
||||
- The integration of the Combo with AndroidAPS is designed with the assumption that all inputs are
|
||||
made via AndroidAPS. Boluses entered on the pump will NOT be detected by AAPS and may therefore
|
||||
result in too much insulin being delivered.
|
||||
- The pump's first basal rate profile is read on app start and is updated by AAPS. Manually changing
|
||||
the pump's basal rate profile will lead to wrong basals being delivered and is NOT supported.
|
||||
made via AndroidAPS. Boluses entered on the pump directly will be detected by AAPS, but it can take
|
||||
up to 25 min before AndroidAPS becomes aware of such a bolus. Reading boluses delivered directly on
|
||||
the pump is a safety feature and not meant to be regularly used (the loop requires knowledge of carbs
|
||||
consumed, which can't be entered on the pump, which is another reason why all inputs should be done
|
||||
in AndroidAPS).
|
||||
- The pump's first basal rate profile is read on application start and is updated by AAPS.
|
||||
The basal rate should not be manually changed on the pump, but will be detected and corrected as a safety
|
||||
measure (don't rely on safety measures by default, this is meant to detect an unintended change on the pump).
|
||||
- It's recommended to enable key lock on the pump to prevent bolusing from the pump, esp. when the
|
||||
pump was used before and quick bolusing was a habit.
|
||||
Also, with keylock enabled, accidentally pressing a key will NOT interrupt a running command
|
||||
Also, with keylock enabled, accidentally pressing a key will NOT interrupt active communication
|
||||
between AAPS and pmup.
|
||||
- When a BOLUS/TBR CANCELLED alert starts on the pump during bolusing or setting a TBR, this is
|
||||
caused by a disconnect between pump and phone. The app will try to reconnect and confirm the alert
|
||||
caused by a disconnect between pump and phone. AAPS will try to reconnect and confirm the alert
|
||||
and then retry the last action (boluses are NOT retried for safety reasons). Therefore,
|
||||
such an alarm shall be ignored (cancelling it is not a big issue, but will lead to the currently
|
||||
active action to have to wait till the pump's display turns off before it can reconnect to the
|
||||
|
@ -113,7 +120,7 @@ Usage:
|
|||
needs to confirm the alarm.
|
||||
- When a low cartridge or low battery alarm is raised during a bolus, they are confirmed and shown
|
||||
as a notification in AAPS. If they occur while no connection is open to the pump, going to the
|
||||
combo tab and hitting the Refresh button will take over those alerts by confirming them and
|
||||
Combo tab and hitting the Refresh button will take over those alerts by confirming them and
|
||||
showing a notification in AAPS.
|
||||
- When AAPS fails to confirm a TBR CANCELLED alert, or one is raised for a different reason,
|
||||
hitting Refresh in the Combo tab establishes a connection, confirms the alert and shows
|
||||
|
@ -121,52 +128,26 @@ Usage:
|
|||
appropriate TBR will be set again during the next loop iteration.
|
||||
- For all other alerts raised by the pump: connecting to the pump will show the alert message in
|
||||
the Combo tab, e.g. "State: E4: Occlusion" as well as showing a notification on the main screen.
|
||||
An error will raise an urgent notification.
|
||||
An error will raise an urgent notification. AAPS never confirms serious errors on the pump,
|
||||
but let's the pump vibrate and ring to make sure the user is informed of a critical situation
|
||||
that needs action.
|
||||
- After pairing, ruffy should not be used directly (AAPS will start in the background as needed),
|
||||
since using ruffy at AAPS at the same time is not supported.
|
||||
- If AAPS crashes (or is stopped from the debugger) while AAPS and the pump were comunicating (using
|
||||
- If AAPS crashes (or is stopped from the debugger) while AAPS and the pump were communicating (using
|
||||
ruffy), it might be necessary to force close ruffy. Restarting AAPS will start ruffy again.
|
||||
- Read the documentation on the wiki as well as the docs at https://openaps.org
|
||||
Restarting the phone is also an easy way to resolve this or you don't know how to force kill
|
||||
an app.
|
||||
- Don't press any buttons on the pump while AAPS communicates with the pump (Bluetooth logo is
|
||||
shown on the pump).
|
||||
- If the loop requests a running TBR to be cancelled the Combo will set a TBR of 90% or 110%
|
||||
for 15 minutes instead. This is because cancelling a TBR causes an alert on the pump which
|
||||
causes a lot of vibrations.
|
||||
- Due to the bug (which causes the pump to become unreachable when reading history regularly),
|
||||
a delivered bolus will NOT be added to treatments when the connection was lost during bolusing
|
||||
or when a pump error occurs (e.g. occlusion). This will raise a message (and play an annoying
|
||||
sound) and the user will have a create a bolus record via Careportal/NS manually. Currently
|
||||
this requires an available NS installation and being online (for a short time). Hopefully
|
||||
both of these issues can be resolved in future versions.
|
||||
|
||||
Known issues:
|
||||
- Occasionally (every couple of days or so) AAPS might fail to automatically cancel
|
||||
a TBR CANCELLED alert the user then needs to deal with (press the refresh button in AAPS
|
||||
to transfer the warning to AAPS or confirm the alert on the pump).
|
||||
- Similarly, the 'pump unreachable' bug may occur from time to time, which requires confirming
|
||||
the alert on the pump to get the pump to accept connections again.
|
||||
- Overall the integration seems rather robust, but there are limits to the way the
|
||||
pump is controlled and how stable BT is, so there will be minor issues like the above
|
||||
from time to time, though they're small compared to what works well.
|
||||
- AAPS might be unresponsive for 10-30s or so when starting and calculating sensitivity.
|
||||
AAPS might also be unresponsive when doing background work, e.g. after receiving a new
|
||||
glucose reading.
|
||||
- Since the pump's date & time can't be updated automatically at this time, daylight saving changes
|
||||
will cause an alert asking to update the pump clock. A usable workaround should be to disable
|
||||
the automatic update of the phone's clock for the night and then enabling it again in the morning
|
||||
when also updating the pump.
|
||||
|
||||
Reporting bugs:
|
||||
Reporting bugs
|
||||
--------------
|
||||
- See https://github.com/MilosKozak/AndroidAPS/blob/master/ISSUE_TEMPLATE.md
|
||||
- Note the precise time the problem occurred and describe the circumstances and steps that caused
|
||||
the problem
|
||||
- Note the Build version (found in the About dialog in the app, when pressing the three dots in the
|
||||
upper-right corner).
|
||||
- Attach the app's log files, which can be found on the phone in
|
||||
- Obtain the app's log files, which can be found on the phone in
|
||||
_/storage/emulated/0/Android/data/info.nightscout.androidaps/_
|
||||
- Open an issue at https://github.com/MilosKozak/AndroidAPS/issues/new
|
||||
|
||||
Components/Layers (developers):
|
||||
- AndroidAPS
|
||||
- ComboPlugin
|
||||
- ruffy-spi (RuffyCommands interface to plug in lower layer)
|
||||
- Scripting layer (ruffyscripter) / Command layer
|
||||
- Driver layer (ruffy)
|
||||
|
|
|
@ -57,7 +57,7 @@ android {
|
|||
targetSdkVersion 23
|
||||
multiDexEnabled true
|
||||
versionCode 1500
|
||||
version "1.57-combo-csv2-test"
|
||||
version "1.57-combo-csv2-beta"
|
||||
buildConfigField "String", "VERSION", '"' + version + '"'
|
||||
buildConfigField "String", "BUILDVERSION", generateGitBuild()
|
||||
|
||||
|
@ -175,7 +175,6 @@ allprojects {
|
|||
|
||||
dependencies {
|
||||
wearApp project(':wear')
|
||||
compile project(path: ':ruffyscripter')
|
||||
|
||||
compile fileTree(include: ['*.jar'], dir: 'libs')
|
||||
compile("com.crashlytics.sdk.android:crashlytics:2.6.7@aar") {
|
||||
|
|
|
@ -6,16 +6,14 @@ import org.json.JSONObject;
|
|||
|
||||
import java.util.Date;
|
||||
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.db.CareportalEvent;
|
||||
import info.nightscout.androidaps.db.Source;
|
||||
import info.nightscout.androidaps.interfaces.InsulinInterface;
|
||||
|
||||
/**
|
||||
* Created by mike on 29.05.2017.
|
||||
*/
|
||||
|
||||
public class DetailedBolusInfo {
|
||||
public class DetailedBolusInfo implements Cloneable {
|
||||
public long date = System.currentTimeMillis();
|
||||
public String eventType = CareportalEvent.MEALBOLUS;
|
||||
public double insulin = 0;
|
||||
|
@ -30,6 +28,24 @@ public class DetailedBolusInfo {
|
|||
public long pumpId = 0; // id of record if comming from pump history (not a newly created treatment)
|
||||
public boolean isSMB = false; // is a Super-MicroBolus
|
||||
|
||||
public DetailedBolusInfo copy() {
|
||||
DetailedBolusInfo copy = new DetailedBolusInfo();
|
||||
copy.date = this.date;
|
||||
copy.eventType = this.eventType;
|
||||
copy.insulin = this.insulin;
|
||||
copy.carbs = this.carbs;
|
||||
copy.source = this.source;
|
||||
copy.isValid = this.isValid;
|
||||
copy.glucose = this.glucose;
|
||||
copy.glucoseType = this.glucoseType;
|
||||
copy.carbTime = this.carbTime;
|
||||
copy.boluscalc = this.boluscalc;
|
||||
copy.context = this.context;
|
||||
copy.pumpId = this.pumpId;
|
||||
copy.isSMB = this.isSMB;
|
||||
return copy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new Date(date).toLocaleString() +
|
||||
|
|
|
@ -713,24 +713,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Treatment getTreatmentByDate(long mills) {
|
||||
try {
|
||||
Dao<Treatment, Long> daoTreatments = getDaoTreatments();
|
||||
List<Treatment> treatments;
|
||||
QueryBuilder<Treatment, Long> queryBuilder = daoTreatments.queryBuilder();
|
||||
Where where = queryBuilder.where();
|
||||
where.eq("date", mills);
|
||||
PreparedQuery<Treatment> preparedQuery = queryBuilder.prepare();
|
||||
treatments = daoTreatments.query(preparedQuery);
|
||||
// date is unique
|
||||
return treatments.isEmpty() ? null : treatments.get(0);
|
||||
} catch (SQLException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public List<Treatment> getTreatmentDataFromTime(long mills, boolean ascending) {
|
||||
try {
|
||||
Dao<Treatment, Long> daoTreatments = getDaoTreatments();
|
||||
|
@ -1086,23 +1068,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
scheduleTemporaryBasalChange();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public TemporaryBasal getTemporaryBasalsDataByDate(long startTime) {
|
||||
try {
|
||||
List<TemporaryBasal> tempbasals;
|
||||
QueryBuilder<TemporaryBasal, Long> queryBuilder = getDaoTemporaryBasal().queryBuilder();
|
||||
Where where = queryBuilder.where();
|
||||
where.eq("date", startTime);
|
||||
PreparedQuery<TemporaryBasal> preparedQuery = queryBuilder.prepare();
|
||||
tempbasals = getDaoTemporaryBasal().query(preparedQuery);
|
||||
// date is unique
|
||||
return tempbasals.isEmpty() ? null : tempbasals.get(0);
|
||||
} catch (SQLException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<TemporaryBasal> getTemporaryBasalsDataFromTime(long mills, boolean ascending) {
|
||||
try {
|
||||
List<TemporaryBasal> tempbasals;
|
||||
|
|
|
@ -10,7 +10,7 @@ import android.widget.TextView;
|
|||
import java.text.DateFormat;
|
||||
import java.util.List;
|
||||
|
||||
import de.jotomo.ruffy.spi.history.PumpAlert;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.history.PumpAlert;
|
||||
import info.nightscout.androidaps.R;
|
||||
|
||||
public class ComboAlertHistoryDialog extends DialogFragment {
|
||||
|
|
|
@ -14,12 +14,16 @@ import android.widget.TextView;
|
|||
|
||||
import com.squareup.otto.Subscribe;
|
||||
|
||||
import de.jotomo.ruffy.spi.PumpState;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.PumpState;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.history.Bolus;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.plugins.Common.SubscriberFragment;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.events.EventComboPumpUpdateGUI;
|
||||
import info.nightscout.androidaps.queue.Callback;
|
||||
import info.nightscout.androidaps.queue.events.EventQueueChanged;
|
||||
import info.nightscout.utils.DateUtil;
|
||||
|
||||
|
@ -29,6 +33,7 @@ public class ComboFragment extends SubscriberFragment implements View.OnClickLis
|
|||
private TextView batteryView;
|
||||
private TextView reservoirView;
|
||||
private TextView lastConnectionView;
|
||||
private TextView lastBolusView;
|
||||
private TextView baseBasalRate;
|
||||
private TextView tempBasalText;
|
||||
private Button refreshButton;
|
||||
|
@ -45,6 +50,7 @@ public class ComboFragment extends SubscriberFragment implements View.OnClickLis
|
|||
activityView = (TextView) view.findViewById(R.id.combo_activity);
|
||||
batteryView = (TextView) view.findViewById(R.id.combo_pumpstate_battery);
|
||||
reservoirView = (TextView) view.findViewById(R.id.combo_insulinstate);
|
||||
lastBolusView = (TextView) view.findViewById(R.id.combo_last_bolus);
|
||||
lastConnectionView = (TextView) view.findViewById(R.id.combo_lastconnection);
|
||||
baseBasalRate = (TextView) view.findViewById(R.id.combo_base_basal_rate);
|
||||
tempBasalText = (TextView) view.findViewById(R.id.combo_temp_basal);
|
||||
|
@ -68,11 +74,24 @@ public class ComboFragment extends SubscriberFragment implements View.OnClickLis
|
|||
return view;
|
||||
}
|
||||
|
||||
private void runOnUiThread(Runnable action) {
|
||||
Activity activity = getActivity();
|
||||
if (activity != null) {
|
||||
activity.runOnUiThread(action);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
switch (view.getId()) {
|
||||
case R.id.combo_refresh_button:
|
||||
ConfigBuilderPlugin.getCommandQueue().readStatus("User request", null);
|
||||
refreshButton.setEnabled(false);
|
||||
ConfigBuilderPlugin.getCommandQueue().readStatus("User request", new Callback() {
|
||||
@Override
|
||||
public void run() {
|
||||
runOnUiThread(() -> refreshButton.setEnabled(true));
|
||||
}
|
||||
});
|
||||
break;
|
||||
case R.id.combo_alerts_button:
|
||||
ComboAlertHistoryDialog ehd = new ComboAlertHistoryDialog();
|
||||
|
@ -84,30 +103,60 @@ public class ComboFragment extends SubscriberFragment implements View.OnClickLis
|
|||
break;
|
||||
case R.id.combo_full_history_button:
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
|
||||
builder.setTitle(R.string.combo_warning);
|
||||
builder.setMessage(R.string.combo_read_full_history_warning);
|
||||
builder.setMessage(R.string.combo_read_full_history_info);
|
||||
builder.show();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO clean up when when queuing
|
||||
@Override
|
||||
public boolean onLongClick(View view) {
|
||||
switch (view.getId()) {
|
||||
case R.id.combo_alerts_button:
|
||||
new Thread(() -> ComboPlugin.getPlugin().readAlertData()).start();
|
||||
alertsButton.setEnabled(false);
|
||||
tddsButton.setEnabled(false);
|
||||
fullHistoryButton.setEnabled(false);
|
||||
new Thread(() -> ComboPlugin.getPlugin().readAlertData(new Callback() {
|
||||
@Override
|
||||
public void run() {
|
||||
runOnUiThread(() -> {
|
||||
alertsButton.setEnabled(true);
|
||||
tddsButton.setEnabled(true);
|
||||
fullHistoryButton.setEnabled(true);
|
||||
});
|
||||
}
|
||||
})).start();
|
||||
return true;
|
||||
case R.id.combo_tdds_button:
|
||||
new Thread(() -> ComboPlugin.getPlugin().readTddData()).start();
|
||||
alertsButton.setEnabled(false);
|
||||
tddsButton.setEnabled(false);
|
||||
fullHistoryButton.setEnabled(false);
|
||||
new Thread(() -> ComboPlugin.getPlugin().readTddData(new Callback() {
|
||||
@Override
|
||||
public void run() {
|
||||
runOnUiThread(() -> {
|
||||
alertsButton.setEnabled(true);
|
||||
tddsButton.setEnabled(true);
|
||||
fullHistoryButton.setEnabled(true);
|
||||
});
|
||||
}
|
||||
})).start();
|
||||
return true;
|
||||
case R.id.combo_full_history_button:
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
|
||||
builder.setTitle(R.string.combo_warning);
|
||||
builder.setMessage(R.string.combo_read_full_history_confirmation);
|
||||
builder.setPositiveButton(R.string.ok, (dialog, which) ->
|
||||
new Thread(() -> ComboPlugin.getPlugin().readAllPumpData()).start());
|
||||
builder.setNegativeButton(MainApp.gs(R.string.cancel), null);
|
||||
builder.show();
|
||||
alertsButton.setEnabled(false);
|
||||
tddsButton.setEnabled(false);
|
||||
fullHistoryButton.setEnabled(false);
|
||||
new Thread(() -> ComboPlugin.getPlugin().readAllPumpData(new Callback() {
|
||||
@Override
|
||||
public void run() {
|
||||
runOnUiThread(() -> {
|
||||
alertsButton.setEnabled(true);
|
||||
tddsButton.setEnabled(true);
|
||||
fullHistoryButton.setEnabled(true);
|
||||
});
|
||||
}
|
||||
})).start();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -125,93 +174,127 @@ public class ComboFragment extends SubscriberFragment implements View.OnClickLis
|
|||
|
||||
|
||||
public void updateGUI() {
|
||||
Activity fragmentActivity = getActivity();
|
||||
if (fragmentActivity != null)
|
||||
fragmentActivity.runOnUiThread(() -> {
|
||||
ComboPlugin plugin = ComboPlugin.getPlugin();
|
||||
runOnUiThread(() -> {
|
||||
ComboPlugin plugin = ComboPlugin.getPlugin();
|
||||
|
||||
// state
|
||||
stateView.setText(plugin.getStateSummary());
|
||||
PumpState ps = plugin.getPump().state;
|
||||
if (ps.insulinState == PumpState.EMPTY || ps.batteryState == PumpState.EMPTY
|
||||
|| ps.activeAlert != null && ps.activeAlert.errorCode != null) {
|
||||
stateView.setTextColor(Color.RED);
|
||||
stateView.setTypeface(null, Typeface.BOLD);
|
||||
} else if (plugin.getPump().state.suspended
|
||||
|| ps.activeAlert != null && ps.activeAlert.warningCode != null) {
|
||||
stateView.setTextColor(Color.YELLOW);
|
||||
stateView.setTypeface(null, Typeface.BOLD);
|
||||
// state
|
||||
stateView.setText(plugin.getStateSummary());
|
||||
PumpState ps = plugin.getPump().state;
|
||||
if (ps.insulinState == PumpState.EMPTY || ps.batteryState == PumpState.EMPTY
|
||||
|| ps.activeAlert != null && ps.activeAlert.errorCode != null) {
|
||||
stateView.setTextColor(Color.RED);
|
||||
stateView.setTypeface(null, Typeface.BOLD);
|
||||
} else if (plugin.getPump().state.suspended
|
||||
|| ps.activeAlert != null && ps.activeAlert.warningCode != null) {
|
||||
stateView.setTextColor(Color.YELLOW);
|
||||
stateView.setTypeface(null, Typeface.BOLD);
|
||||
} else {
|
||||
stateView.setTextColor(Color.WHITE);
|
||||
stateView.setTypeface(null, Typeface.NORMAL);
|
||||
}
|
||||
|
||||
// activity
|
||||
String activity = plugin.getPump().activity;
|
||||
if (StringUtils.isNotEmpty(activity)) {
|
||||
activityView.setTextSize(14);
|
||||
activityView.setText(activity);
|
||||
} else {
|
||||
activityView.setTextSize(18);
|
||||
activityView.setText("{fa-bed}");
|
||||
}
|
||||
|
||||
if (plugin.isInitialized()) {
|
||||
refreshButton.setVisibility(View.VISIBLE);
|
||||
alertsButton.setVisibility(View.VISIBLE);
|
||||
tddsButton.setVisibility(View.VISIBLE);
|
||||
fullHistoryButton.setVisibility(View.VISIBLE);
|
||||
|
||||
// battery
|
||||
batteryView.setTextSize(20);
|
||||
if (ps.batteryState == PumpState.EMPTY) {
|
||||
batteryView.setText("{fa-battery-empty}");
|
||||
batteryView.setTextColor(Color.RED);
|
||||
} else if (ps.batteryState == PumpState.LOW) {
|
||||
batteryView.setText("{fa-battery-quarter}");
|
||||
batteryView.setTextColor(Color.YELLOW);
|
||||
} else {
|
||||
stateView.setTextColor(Color.WHITE);
|
||||
stateView.setTypeface(null, Typeface.NORMAL);
|
||||
batteryView.setText("{fa-battery-full}");
|
||||
batteryView.setTextColor(Color.WHITE);
|
||||
}
|
||||
|
||||
// activity
|
||||
String activity = plugin.getPump().activity;
|
||||
activityView.setText(activity != null ? activity : "");
|
||||
|
||||
if (plugin.isInitialized()) {
|
||||
refreshButton.setVisibility(View.VISIBLE);
|
||||
alertsButton.setVisibility(View.VISIBLE);
|
||||
tddsButton.setVisibility(View.VISIBLE);
|
||||
fullHistoryButton.setVisibility(View.VISIBLE);
|
||||
|
||||
// battery
|
||||
batteryView.setTextSize(20);
|
||||
if (ps.batteryState == PumpState.EMPTY) {
|
||||
batteryView.setText("{fa-battery-empty}");
|
||||
batteryView.setTextColor(Color.RED);
|
||||
} else if (ps.batteryState == PumpState.LOW) {
|
||||
batteryView.setText("{fa-battery-quarter}");
|
||||
batteryView.setTextColor(Color.YELLOW);
|
||||
} else {
|
||||
batteryView.setText("{fa-battery-full}");
|
||||
batteryView.setTextColor(Color.WHITE);
|
||||
}
|
||||
|
||||
// reservoir
|
||||
if (ps.insulinState == PumpState.LOW) {
|
||||
reservoirView.setTextColor(Color.YELLOW);
|
||||
reservoirView.setText(R.string.combo_reservoir_low);
|
||||
reservoirView.setTypeface(null, Typeface.BOLD);
|
||||
} else if (ps.insulinState == PumpState.EMPTY) {
|
||||
reservoirView.setTextColor(Color.RED);
|
||||
reservoirView.setText(R.string.combo_reservoir_empty);
|
||||
reservoirView.setTypeface(null, Typeface.BOLD);
|
||||
} else {
|
||||
reservoirView.setTextColor(Color.WHITE);
|
||||
reservoirView.setText(R.string.combo_reservoir_normal);
|
||||
reservoirView.setTypeface(null, Typeface.NORMAL);
|
||||
}
|
||||
|
||||
// last connection
|
||||
String minAgo = DateUtil.minAgo(plugin.getPump().lastSuccessfulCmdTime);
|
||||
long min = (System.currentTimeMillis() - plugin.getPump().lastSuccessfulCmdTime) / 1000 / 60;
|
||||
if (plugin.getPump().lastSuccessfulCmdTime + 60 * 1000 > System.currentTimeMillis()) {
|
||||
lastConnectionView.setText(R.string.combo_pump_connected_now);
|
||||
lastConnectionView.setTextColor(Color.WHITE);
|
||||
} else if (plugin.getPump().lastSuccessfulCmdTime + 30 * 60 * 1000 < System.currentTimeMillis()) {
|
||||
lastConnectionView.setText(MainApp.gs(R.string.combo_no_pump_connection, min));
|
||||
lastConnectionView.setTextColor(Color.RED);
|
||||
} else {
|
||||
lastConnectionView.setText(minAgo);
|
||||
lastConnectionView.setTextColor(Color.WHITE);
|
||||
}
|
||||
|
||||
// base basal rate
|
||||
baseBasalRate.setText(MainApp.gs(R.string.pump_basebasalrate, plugin.getBaseBasalRate()));
|
||||
|
||||
// TBR
|
||||
String tbrStr = "";
|
||||
if (ps.tbrPercent != -1 && ps.tbrPercent != 100) {
|
||||
long minSinceRead = (System.currentTimeMillis() - plugin.getPump().state.timestamp) / 1000 / 60;
|
||||
long remaining = ps.tbrRemainingDuration - minSinceRead;
|
||||
if (remaining >= 0) {
|
||||
tbrStr = MainApp.gs(R.string.combo_tbr_remaining, ps.tbrPercent, remaining);
|
||||
}
|
||||
}
|
||||
tempBasalText.setText(tbrStr);
|
||||
// reservoir
|
||||
int reservoirLevel = plugin.getPump().reservoirLevel;
|
||||
if (reservoirLevel != -1) {
|
||||
reservoirView.setText(reservoirLevel + " " + MainApp.sResources.getString(R.string.treatments_wizard_unit_label));
|
||||
} else if (ps.insulinState == PumpState.LOW) {
|
||||
reservoirView.setText(MainApp.gs(R.string.combo_reservoir_low));
|
||||
} else if (ps.insulinState == PumpState.EMPTY) {
|
||||
reservoirView.setText(MainApp.gs(R.string.combo_reservoir_empty));
|
||||
} else {
|
||||
reservoirView.setText(MainApp.gs(R.string.combo_reservoir_normal));
|
||||
}
|
||||
});
|
||||
|
||||
if (ps.insulinState == PumpState.UNKNOWN) {
|
||||
reservoirView.setTextColor(Color.WHITE);
|
||||
reservoirView.setTypeface(null, Typeface.NORMAL);
|
||||
} else if (ps.insulinState == PumpState.LOW) {
|
||||
reservoirView.setTextColor(Color.YELLOW);
|
||||
reservoirView.setTypeface(null, Typeface.BOLD);
|
||||
} else if (ps.insulinState == PumpState.EMPTY) {
|
||||
reservoirView.setTextColor(Color.RED);
|
||||
reservoirView.setTypeface(null, Typeface.BOLD);
|
||||
} else {
|
||||
reservoirView.setTextColor(Color.WHITE);
|
||||
reservoirView.setTypeface(null, Typeface.NORMAL);
|
||||
}
|
||||
|
||||
// last connection
|
||||
String minAgo = DateUtil.minAgo(plugin.getPump().lastSuccessfulCmdTime);
|
||||
long min = (System.currentTimeMillis() - plugin.getPump().lastSuccessfulCmdTime) / 1000 / 60;
|
||||
if (plugin.getPump().lastSuccessfulCmdTime + 60 * 1000 > System.currentTimeMillis()) {
|
||||
lastConnectionView.setText(R.string.combo_pump_connected_now);
|
||||
lastConnectionView.setTextColor(Color.WHITE);
|
||||
} else if (plugin.getPump().lastSuccessfulCmdTime + 30 * 60 * 1000 < System.currentTimeMillis()) {
|
||||
lastConnectionView.setText(MainApp.gs(R.string.combo_no_pump_connection, min));
|
||||
lastConnectionView.setTextColor(Color.RED);
|
||||
} else {
|
||||
lastConnectionView.setText(minAgo);
|
||||
lastConnectionView.setTextColor(Color.WHITE);
|
||||
}
|
||||
|
||||
// last bolus
|
||||
Bolus bolus = plugin.getPump().lastBolus;
|
||||
if (bolus != null && bolus.timestamp + 6 * 60 * 60 * 1000 >= System.currentTimeMillis()) {
|
||||
long agoMsc = System.currentTimeMillis() - bolus.timestamp;
|
||||
double bolusMinAgo = agoMsc / 60d / 1000d;
|
||||
String unit = MainApp.gs(R.string.treatments_wizard_unit_label);
|
||||
String ago;
|
||||
if ((agoMsc < 60 * 1000)) {
|
||||
ago = MainApp.gs(R.string.combo_pump_connected_now);
|
||||
} else if (bolusMinAgo < 60) {
|
||||
ago = DateUtil.minAgo(bolus.timestamp);
|
||||
} else {
|
||||
ago = DateUtil.hourAgo(bolus.timestamp);
|
||||
}
|
||||
lastBolusView.setText(MainApp.gs(R.string.combo_last_bolus, bolus.amount, unit, ago));
|
||||
} else {
|
||||
lastBolusView.setText("");
|
||||
}
|
||||
|
||||
// base basal rate
|
||||
baseBasalRate.setText(MainApp.gs(R.string.pump_basebasalrate, plugin.getBaseBasalRate()));
|
||||
|
||||
// TBR
|
||||
String tbrStr = "";
|
||||
if (ps.tbrPercent != -1 && ps.tbrPercent != 100) {
|
||||
long minSinceRead = (System.currentTimeMillis() - plugin.getPump().state.timestamp) / 1000 / 60;
|
||||
long remaining = ps.tbrRemainingDuration - minSinceRead;
|
||||
if (remaining >= 0) {
|
||||
tbrStr = MainApp.gs(R.string.combo_tbr_remaining, ps.tbrPercent, remaining);
|
||||
}
|
||||
}
|
||||
tempBasalText.setText(tbrStr);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,9 +2,7 @@ package info.nightscout.androidaps.plugins.PumpCombo;
|
|||
|
||||
import android.os.SystemClock;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import com.crashlytics.android.answers.Answers;
|
||||
import com.crashlytics.android.answers.CustomEvent;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import org.json.JSONObject;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -12,21 +10,7 @@ import org.slf4j.LoggerFactory;
|
|||
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import de.jotomo.ruffy.spi.BasalProfile;
|
||||
import de.jotomo.ruffy.spi.BolusProgressReporter;
|
||||
import de.jotomo.ruffy.spi.CommandResult;
|
||||
import de.jotomo.ruffy.spi.PumpState;
|
||||
import de.jotomo.ruffy.spi.PumpWarningCodes;
|
||||
import de.jotomo.ruffy.spi.RuffyCommands;
|
||||
import de.jotomo.ruffy.spi.WarningOrErrorCode;
|
||||
import de.jotomo.ruffy.spi.history.Bolus;
|
||||
import de.jotomo.ruffy.spi.history.PumpHistory;
|
||||
import de.jotomo.ruffy.spi.history.PumpHistoryRequest;
|
||||
import de.jotomo.ruffy.spi.history.Tbr;
|
||||
import de.jotomo.ruffyscripter.RuffyCommandsV1Impl;
|
||||
import info.nightscout.androidaps.BuildConfig;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
|
@ -34,10 +18,8 @@ import info.nightscout.androidaps.data.DetailedBolusInfo;
|
|||
import info.nightscout.androidaps.data.Profile;
|
||||
import info.nightscout.androidaps.data.PumpEnactResult;
|
||||
import info.nightscout.androidaps.db.CareportalEvent;
|
||||
import info.nightscout.androidaps.db.DatabaseHelper;
|
||||
import info.nightscout.androidaps.db.Source;
|
||||
import info.nightscout.androidaps.db.TemporaryBasal;
|
||||
import info.nightscout.androidaps.db.Treatment;
|
||||
import info.nightscout.androidaps.events.EventInitializationChanged;
|
||||
import info.nightscout.androidaps.events.EventRefreshOverview;
|
||||
import info.nightscout.androidaps.interfaces.ConstraintsInterface;
|
||||
|
@ -50,6 +32,18 @@ import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
|
|||
import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress;
|
||||
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.events.EventComboPumpUpdateGUI;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.BasalProfile;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.BolusProgressReporter;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.CommandResult;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.PumpState;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.PumpWarningCodes;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.RuffyCommands;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.RuffyScripter;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.WarningOrErrorCode;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.history.Bolus;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.history.PumpHistory;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.history.PumpHistoryRequest;
|
||||
import info.nightscout.androidaps.queue.Callback;
|
||||
import info.nightscout.utils.DateUtil;
|
||||
|
||||
/**
|
||||
|
@ -101,8 +95,18 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
|
|||
|
||||
private volatile boolean bolusInProgress;
|
||||
private volatile boolean cancelBolus;
|
||||
|
||||
private Bolus lastRequestedBolus;
|
||||
private long pumpHistoryLastChecked;
|
||||
|
||||
/**
|
||||
* This is set whenever a connection to the pump is made and indicates if new history
|
||||
* records on the pump have been found. This effectively blocks high temps and boluses
|
||||
* till the queue is empty and the connection is shut down. The next reconnect will
|
||||
* then reset this flag. This might cause some grief when attempting to bolus again within
|
||||
* the 5s of idling it takes before the connecting is shut down.
|
||||
*/
|
||||
private volatile boolean pumpHistoryChanged = false;
|
||||
private volatile long timestampOfLastKnownPumpBolusRecord;
|
||||
|
||||
public static ComboPlugin getPlugin() {
|
||||
if (plugin == null)
|
||||
|
@ -114,7 +118,7 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
|
|||
.success(false).enacted(false).comment(MainApp.sResources.getString(R.string.combo_pump_unsupported_operation));
|
||||
|
||||
private ComboPlugin() {
|
||||
ruffyScripter = RuffyCommandsV1Impl.getInstance(MainApp.instance());
|
||||
ruffyScripter = new RuffyScripter(MainApp.instance().getApplicationContext());
|
||||
}
|
||||
|
||||
public ComboPump getPump() {
|
||||
|
@ -144,15 +148,15 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
|
|||
|
||||
String getStateSummary() {
|
||||
PumpState ps = pump.state;
|
||||
if (!validBasalRateProfileSelectedOnPump) {
|
||||
if (!pump.initialized) {
|
||||
return MainApp.gs(R.string.combo_pump_state_initializing);
|
||||
} else if (!validBasalRateProfileSelectedOnPump) {
|
||||
return MainApp.gs(R.string.loopdisabled);
|
||||
} else if (ps.activeAlert != null) {
|
||||
return ps.activeAlert.errorCode != null
|
||||
? "E" + ps.activeAlert.errorCode + ": " + ps.activeAlert.message
|
||||
: "W" + ps.activeAlert.warningCode + ": " + ps.activeAlert.message;
|
||||
} else if (ps.menu == null)
|
||||
return MainApp.gs(R.string.combo_pump_state_disconnected);
|
||||
else if (ps.suspended && (ps.batteryState == PumpState.EMPTY || ps.insulinState == PumpState.EMPTY))
|
||||
} else if (ps.suspended && (ps.batteryState == PumpState.EMPTY || ps.insulinState == PumpState.EMPTY))
|
||||
return MainApp.gs(R.string.combo_pump_state_suspended_due_to_error);
|
||||
else if (ps.suspended)
|
||||
return MainApp.gs(R.string.combo_pump_state_suspended_by_user);
|
||||
|
@ -346,13 +350,12 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
|
|||
if (!pump.initialized) {
|
||||
initializePump();
|
||||
} else {
|
||||
runCommand(MainApp.gs(R.string.combo_pump_action_refreshing), 1, ruffyScripter::readPumpState);
|
||||
// trigger a connect, which will update state and check history
|
||||
runCommand(null, 3, ruffyScripter::readPumpState);
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void initializePump() {
|
||||
Answers.getInstance().logCustom(new CustomEvent("ComboInit")
|
||||
.putCustomAttribute("buildversion", BuildConfig.BUILDVERSION));
|
||||
long maxWait = System.currentTimeMillis() + 15 * 1000;
|
||||
while (!ruffyScripter.isPumpAvailable()) {
|
||||
log.debug("Waiting for ruffy service to come up ...");
|
||||
|
@ -363,11 +366,19 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
|
|||
}
|
||||
}
|
||||
|
||||
CommandResult stateResult = runCommand(MainApp.gs(R.string.combo_pump_action_initializing),1, ruffyScripter::readPumpState);
|
||||
// trigger a connect, which will update state and check history
|
||||
CommandResult stateResult = runCommand(null,1, ruffyScripter::readPumpState);
|
||||
if (!stateResult.success) {
|
||||
return;
|
||||
}
|
||||
|
||||
// note that since the history is checked upon every connect, the above already updated
|
||||
// the DB with any changed history records
|
||||
if (pumpHistoryChanged) {
|
||||
log.debug("Pump history has changed and was imported");
|
||||
pumpHistoryChanged = false;
|
||||
}
|
||||
|
||||
if (stateResult.state.unsafeUsageDetected == PumpState.UNSUPPORTED_BASAL_RATE_PROFILE) {
|
||||
Notification n = new Notification(Notification.COMBO_PUMP_ALARM,
|
||||
MainApp.gs(R.string.combo_force_disabled_notification),
|
||||
|
@ -384,14 +395,23 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
|
|||
}
|
||||
pump.basalProfile = readBasalResult.basalProfile;
|
||||
validBasalRateProfileSelectedOnPump = true;
|
||||
|
||||
pump.initialized = true;
|
||||
MainApp.bus().post(new EventInitializationChanged());
|
||||
|
||||
// ComboFragment updates state fully only after the pump has initialized, so read full state here
|
||||
updateLocalData(readBasalResult);
|
||||
// ComboFragment updates state fully only after the pump has initialized,
|
||||
// so force an update after initialization completed
|
||||
updateLocalData(runCommand(null, 1, ruffyScripter::readQuickInfo));
|
||||
}
|
||||
|
||||
/** Updates local cache with state (reservoir level, last bolus ...) returned from the pump */
|
||||
private void updateLocalData(CommandResult result) {
|
||||
if (result.reservoirLevel != PumpState.UNKNOWN) {
|
||||
pump.reservoirLevel = result.reservoirLevel;
|
||||
}
|
||||
if (result.history != null && !result.history.bolusHistory.isEmpty()) {
|
||||
pump.lastBolus = result.history.bolusHistory.get(0);
|
||||
}
|
||||
if (result.state.menu != null) {
|
||||
pump.state = result.state;
|
||||
}
|
||||
|
@ -466,22 +486,37 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
|
|||
|
||||
@NonNull
|
||||
private PumpEnactResult deliverBolus(final DetailedBolusInfo detailedBolusInfo) {
|
||||
// guard against boluses issued multiple times within a minute
|
||||
// Guard against boluses issued multiple times within two minutes.
|
||||
// Two minutes, so that the resulting timestamp and bolus are different with the Combo
|
||||
// history records which only store with minute-precision
|
||||
if (lastRequestedBolus != null
|
||||
&& Math.abs(lastRequestedBolus.amount - detailedBolusInfo.insulin) < 0.01
|
||||
&& lastRequestedBolus.timestamp + 60 * 1000 > System.currentTimeMillis()) {
|
||||
log.error("Bolus delivery failure at stage 0", new Exception());
|
||||
&& lastRequestedBolus.timestamp + 120 * 1000 > System.currentTimeMillis()) {
|
||||
log.error("Bolus request rejected, same bolus requested recently: " + lastRequestedBolus);
|
||||
return new PumpEnactResult().success(false).enacted(false)
|
||||
.comment(MainApp.gs(R.string.bolus_frequency_exceeded));
|
||||
}
|
||||
lastRequestedBolus = new Bolus(System.currentTimeMillis(), detailedBolusInfo.insulin, true);
|
||||
|
||||
CommandResult stateResult = runCommand(null, 1, ruffyScripter::readPumpState);
|
||||
long pumpTimeWhenBolusWasRequested = stateResult .state.pumpTime;
|
||||
if (!stateResult.success || pumpTimeWhenBolusWasRequested == 0) {
|
||||
// check pump is ready and all pump bolus records are known
|
||||
CommandResult stateResult = runCommand(null, 2, ruffyScripter::readQuickInfo);
|
||||
if (!stateResult.success) {
|
||||
return new PumpEnactResult().success(false).enacted(false)
|
||||
.comment(MainApp.gs(R.string.combo_error_no_bolus_delivered));
|
||||
.comment(MainApp.gs(R.string.combo_error_no_connection_no_bolus_delivered));
|
||||
}
|
||||
if (stateResult.reservoirLevel != -1 && stateResult.reservoirLevel - 0.5 < detailedBolusInfo.insulin) {
|
||||
return new PumpEnactResult().success(false).enacted(false)
|
||||
.comment(MainApp.gs(R.string.combo_reservoir_level_insufficient_for_bolus));
|
||||
}
|
||||
// the commands above ensured a connection was made, which updated this field
|
||||
if (pumpHistoryChanged) {
|
||||
return new PumpEnactResult().success(false).enacted(false)
|
||||
.comment(MainApp.gs(R.string.combo_bolus_rejected_due_to_pump_history_change));
|
||||
}
|
||||
|
||||
Bolus previousBolus = stateResult.history != null && !stateResult.history.bolusHistory.isEmpty()
|
||||
? stateResult.history.bolusHistory.get(0)
|
||||
: new Bolus(0, 0, false);
|
||||
|
||||
try {
|
||||
pump.activity = MainApp.gs(R.string.combo_pump_action_bolusing, detailedBolusInfo.insulin);
|
||||
|
@ -495,90 +530,95 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
|
|||
|
||||
// start bolus delivery
|
||||
bolusInProgress = true;
|
||||
CommandResult bolusCmdResult = runCommand(null, 0,
|
||||
runCommand(null, 0,
|
||||
() -> ruffyScripter.deliverBolus(detailedBolusInfo.insulin, progressReporter));
|
||||
bolusInProgress = false;
|
||||
|
||||
if (bolusCmdResult.success) {
|
||||
if (bolusCmdResult.delivered > 0) {
|
||||
detailedBolusInfo.insulin = bolusCmdResult.delivered;
|
||||
detailedBolusInfo.source = Source.USER;
|
||||
MainApp.getConfigBuilder().addToHistoryTreatment(detailedBolusInfo);
|
||||
}
|
||||
return new PumpEnactResult()
|
||||
.success(true)
|
||||
.enacted(bolusCmdResult.delivered > 0)
|
||||
.bolusDelivered(bolusCmdResult.delivered)
|
||||
.carbsDelivered(detailedBolusInfo.carbs);
|
||||
} else {
|
||||
progressReporter.report(BolusProgressReporter.State.RECOVERING, 0, 0);
|
||||
return recoverFromErrorDuringBolusDelivery(detailedBolusInfo, pumpTimeWhenBolusWasRequested);
|
||||
// Note that the result of the issued bolus command is not checked. If there was
|
||||
// a connection problem, ruffyscripter tried to recover and we can just check the
|
||||
// history below to see what was actually delivered
|
||||
|
||||
// get last bolus from pump history for verification
|
||||
CommandResult postBolusStateResult = runCommand(null, 3, ruffyScripter::readQuickInfo);
|
||||
if (!postBolusStateResult.success) {
|
||||
return new PumpEnactResult().success(false).enacted(false)
|
||||
.comment(MainApp.gs(R.string.combo_error_bolus_verification_failed));
|
||||
}
|
||||
Bolus lastPumpBolus = postBolusStateResult.history != null && !postBolusStateResult.history.bolusHistory.isEmpty()
|
||||
? postBolusStateResult.history.bolusHistory.get(0)
|
||||
: null;
|
||||
|
||||
// no bolus delivered?
|
||||
if (lastPumpBolus == null || lastPumpBolus.equals(previousBolus) ) {
|
||||
if (cancelBolus) {
|
||||
return new PumpEnactResult().success(true).enacted(false);
|
||||
} else {
|
||||
return new PumpEnactResult()
|
||||
.success(false)
|
||||
.enacted(false)
|
||||
.comment(MainApp.gs(R.string.combo_error_no_bolus_delivered));
|
||||
}
|
||||
}
|
||||
|
||||
// at least some insulin delivered, so add it to treatments
|
||||
if (!addBolusToTreatments(detailedBolusInfo, lastPumpBolus))
|
||||
return new PumpEnactResult().success(false).enacted(true)
|
||||
.comment(MainApp.gs(R.string.combo_error_updating_treatment_record));
|
||||
|
||||
// partial bolus was delivered
|
||||
if (Math.abs(lastPumpBolus.amount - detailedBolusInfo.insulin) > 0.01) {
|
||||
if (cancelBolus) {
|
||||
return new PumpEnactResult().success(true).enacted(true);
|
||||
}
|
||||
return new PumpEnactResult().success(false).enacted(true)
|
||||
.comment(MainApp.gs(R.string.combo_error_partial_bolus_delivered,
|
||||
lastPumpBolus.amount, detailedBolusInfo.insulin));
|
||||
}
|
||||
|
||||
// full bolus was delivered successfully
|
||||
return new PumpEnactResult()
|
||||
.success(true)
|
||||
.enacted(lastPumpBolus.amount > 0)
|
||||
.bolusDelivered(lastPumpBolus.amount)
|
||||
.carbsDelivered(detailedBolusInfo.carbs);
|
||||
} finally {
|
||||
pump.activity = null;
|
||||
MainApp.bus().post(new EventComboPumpUpdateGUI());
|
||||
MainApp.bus().post(new EventRefreshOverview("Combo Bolus"));
|
||||
MainApp.bus().post(new EventRefreshOverview("Bolus"));
|
||||
cancelBolus = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* If there was an error during BolusCommand the scripter reconnects and cleans up. The pump
|
||||
* refuses connections while a bolus delivery is still in progress (once bolus delivery started
|
||||
* it continues regardless of a connection loss).
|
||||
* Then verify the bolus record we read has a date which is >= the time the bolus was requested
|
||||
* (using the pump's time!). If there is such a bolus with <= the requested amount, then it's
|
||||
* from this command and shall be added to treatments. If the bolus wasn't delivered in full,
|
||||
* add it to treatments but raise a warning. Raise a warning as well if no bolus was delivered
|
||||
* at all.
|
||||
* This all still might fail for very large boluses and earthquakes in which case an error
|
||||
* is raised asking to user to deal with it.
|
||||
* Updates a DetailedBolusInfo from a pump bolus and adds it as a Treatment to the DB.
|
||||
* Handles edge cases when dates aren't unique which are extremely unlikely to occur,
|
||||
* but if they do, the user should be warned since a bolus will be missing from calculations.
|
||||
*/
|
||||
private PumpEnactResult recoverFromErrorDuringBolusDelivery(DetailedBolusInfo detailedBolusInfo, long pumpTimeWhenBolusWasRequested) {
|
||||
log.debug("Trying to determine from pump history what was actually delivered");
|
||||
CommandResult readLastBolusResult = runCommand(null , 2,
|
||||
() -> ruffyScripter.readHistory(new PumpHistoryRequest().bolusHistory(PumpHistoryRequest.LAST)));
|
||||
if (!readLastBolusResult.success || readLastBolusResult.history == null) {
|
||||
// this happens when the cartridge runs empty during delivery, the pump will be in an error
|
||||
// state with multiple alarms ringing and no chance of reading history
|
||||
return new PumpEnactResult().success(false).enacted(false)
|
||||
.comment(MainApp.gs(R.string.combo_error_bolus_verification_failed));
|
||||
}
|
||||
|
||||
List<Bolus> bolusHistory = readLastBolusResult.history.bolusHistory;
|
||||
Bolus lastBolus = !bolusHistory.isEmpty() ? bolusHistory.get(0) : null;
|
||||
log.debug("Last bolus read from history: " + lastBolus + ", request time: " +
|
||||
pumpTimeWhenBolusWasRequested + " (" + new Date(pumpTimeWhenBolusWasRequested) + ")");
|
||||
|
||||
if (lastBolus == null // no bolus ever given
|
||||
|| lastBolus.timestamp < pumpTimeWhenBolusWasRequested // this is not the bolus you're looking for
|
||||
|| lastBolus.amount - detailedBolusInfo.insulin > 0.01 // this one neither, big than requested bolus
|
||||
|| !lastBolus.isValid) { // ext/multiwave bolus
|
||||
log.debug("No bolus was delivered");
|
||||
return new PumpEnactResult().success(false).enacted(false)
|
||||
.comment(MainApp.gs(R.string.combo_error_no_bolus_delivered));
|
||||
} else if (Math.abs(lastBolus.amount - detailedBolusInfo.insulin) > 0.01) { // bolus only partially delivered
|
||||
double requestedBolus = detailedBolusInfo.insulin;
|
||||
|
||||
detailedBolusInfo.insulin = lastBolus.amount;
|
||||
detailedBolusInfo.source = Source.USER;
|
||||
MainApp.getConfigBuilder().addToHistoryTreatment(detailedBolusInfo);
|
||||
log.debug(String.format(Locale.getDefault(), "Added partial bolus of %.2f to treatments (requested: %.2f)", lastBolus.amount, requestedBolus));
|
||||
|
||||
return new PumpEnactResult().success(false).enacted(true)
|
||||
.comment(MainApp.gs(R.string.combo_error_partial_bolus_delivered,
|
||||
lastBolus.amount, requestedBolus));
|
||||
} else {
|
||||
// bolus was correctly and fully delivered
|
||||
detailedBolusInfo.insulin = lastBolus.amount;
|
||||
detailedBolusInfo.source = Source.USER;
|
||||
MainApp.getConfigBuilder().addToHistoryTreatment(detailedBolusInfo);
|
||||
log.debug("Added correctly delivered bolus to treatments");
|
||||
return new PumpEnactResult().success(true).enacted(true)
|
||||
.bolusDelivered(lastBolus.amount)
|
||||
.carbsDelivered(detailedBolusInfo.carbs);
|
||||
private boolean addBolusToTreatments(DetailedBolusInfo detailedBolusInfo, Bolus lastPumpBolus) {
|
||||
DetailedBolusInfo dbi = detailedBolusInfo.copy();
|
||||
dbi.date = calculateFakeBolusDate(lastPumpBolus);
|
||||
dbi.pumpId = calculateFakeBolusDate(lastPumpBolus);
|
||||
dbi.source = Source.PUMP;
|
||||
dbi.insulin = lastPumpBolus.amount;
|
||||
try {
|
||||
boolean treatmentCreated = MainApp.getConfigBuilder().addToHistoryTreatment(dbi);
|
||||
if (!treatmentCreated) {
|
||||
log.error("Adding treatment record overrode an existing record: " + dbi);
|
||||
if (dbi.isSMB) {
|
||||
Notification notification = new Notification(Notification.COMBO_PUMP_ALARM, MainApp.sResources.getString(R.string.combo_error_updating_treatment_record), Notification.URGENT);
|
||||
MainApp.bus().post(new EventNewNotification(notification));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("Adding treatment record failed", e);
|
||||
if (dbi.isSMB) {
|
||||
Notification notification = new Notification(Notification.COMBO_PUMP_ALARM, MainApp.sResources.getString(R.string.combo_error_updating_treatment_record), Notification.URGENT);
|
||||
MainApp.bus().post(new EventNewNotification(notification));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -589,13 +629,16 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
|
|||
cancelBolus = true;
|
||||
}
|
||||
|
||||
// Note: AAPS calls this solely to enact OpenAPS suggestions
|
||||
/** Note: AAPS calls this solely to enact OpenAPS suggestions
|
||||
*
|
||||
* @param force the force parameter isn't used currently since we always set the tbr -
|
||||
* there might be room for optimization to first test the currently running tbr
|
||||
* and only change it if it differs (as the DanaR plugin does). This approach
|
||||
* might have other issues though (what happens if the tbr which wasn't re-set to
|
||||
* the new value (and thus still has the old duration of e.g. 1 min) expires?)
|
||||
*/
|
||||
@Override
|
||||
public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean force) {
|
||||
// the force parameter isn't used currently since we always set the tbr - there might be room for optimization to
|
||||
// first test the currently running tbr and only change it if it differs (as the DanaR plugin does).
|
||||
// This approach might have other issues though (what happens if the tbr which wasn't re-set to the new value
|
||||
// (and thus still has the old duration of e.g. 1 min) expires?)
|
||||
log.debug("setTempBasalAbsolute called with a rate of " + absoluteRate + " for " + durationInMinutes + " min.");
|
||||
int unroundedPercentage = Double.valueOf(absoluteRate / getBaseBasalRate() * 100).intValue();
|
||||
int roundedPercentage = (int) (Math.round(absoluteRate / getBaseBasalRate() * 10) * 10);
|
||||
|
@ -620,6 +663,11 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
|
|||
private PumpEnactResult setTempBasalPercent(Integer percent, final Integer durationInMinutes) {
|
||||
log.debug("setTempBasalPercent called with " + percent + "% for " + durationInMinutes + "min");
|
||||
|
||||
if (pumpHistoryChanged && percent > 110) {
|
||||
return new PumpEnactResult().success(false).enacted(false)
|
||||
.comment(MainApp.gs(R.string.combo_high_temp_rejected_due_to_pump_history_changes));
|
||||
}
|
||||
|
||||
int adjustedPercent = percent;
|
||||
|
||||
if (adjustedPercent > pumpDescription.maxTempPercent) {
|
||||
|
@ -712,17 +760,15 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
|
|||
/**
|
||||
* Runs a command, sets an activity if provided, retries if requested and updates fields
|
||||
* concerned with last connection.
|
||||
* NO history, reservoir level fields are updated, this make be done separately if desired.
|
||||
* Local cache (history, reservoir level, pump state) are updated via #updateLocalData()
|
||||
* if returned by a command.
|
||||
*/
|
||||
private synchronized CommandResult runCommand(String activity, int retries, CommandExecution commandExecution) {
|
||||
CommandResult commandResult;
|
||||
try {
|
||||
if (activity != null) {
|
||||
pump.activity = activity;
|
||||
MainApp.bus().post(new EventComboPumpUpdateGUI());
|
||||
}
|
||||
|
||||
if (!ruffyScripter.isConnected()) {
|
||||
pump.activity = MainApp.gs(R.string.combo_activity_checking_pump_state);
|
||||
MainApp.bus().post(new EventComboPumpUpdateGUI());
|
||||
CommandResult preCheckError = runOnConnectChecks();
|
||||
if (preCheckError != null) {
|
||||
updateLocalData(preCheckError);
|
||||
|
@ -730,6 +776,11 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
|
|||
}
|
||||
}
|
||||
|
||||
if (activity != null) {
|
||||
pump.activity = activity;
|
||||
MainApp.bus().post(new EventComboPumpUpdateGUI());
|
||||
}
|
||||
|
||||
commandResult = commandExecution.execute();
|
||||
|
||||
if (!commandResult.success && retries > 0) {
|
||||
|
@ -763,8 +814,6 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
|
|||
}
|
||||
}
|
||||
|
||||
checkForUnsafeUsage(commandResult);
|
||||
|
||||
return commandResult;
|
||||
}
|
||||
|
||||
|
@ -801,12 +850,57 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
|
|||
}
|
||||
}
|
||||
|
||||
checkForUnsafeUsage(preCheckResult);
|
||||
checkAndResolveTbrMismatch(preCheckResult.state);
|
||||
checkPumpTime(preCheckResult.state);
|
||||
checkBasalRate(preCheckResult.state);
|
||||
CommandResult historyCheckError = checkHistory();
|
||||
if (historyCheckError != null) {
|
||||
return historyCheckError;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private void checkBasalRate(PumpState state) {
|
||||
if (!pump.initialized) {
|
||||
// no cached profile to compare against
|
||||
return;
|
||||
}
|
||||
if (state.unsafeUsageDetected != PumpState.SAFE_USAGE) {
|
||||
// with an extended or multiwavo bolus running it's not (easily) possible
|
||||
// to infer base basal rate and not supported either. Also don't compare
|
||||
// if set basal rate profile is != -1.
|
||||
return;
|
||||
}
|
||||
if (state.tbrActive && state.tbrPercent == 0) {
|
||||
// can't infer base basal rate if TBR is 0
|
||||
return;
|
||||
}
|
||||
double pumpBasalRate = state.tbrActive
|
||||
? Math.round(state.basalRate * 100 / state.tbrPercent * 100) / 100d
|
||||
: state.basalRate;
|
||||
int pumpHour = new Date(state.pumpTime).getHours();
|
||||
int phoneHour = new Date().getHours();
|
||||
if (pumpHour != phoneHour) {
|
||||
// only check if clocks are close
|
||||
return;
|
||||
}
|
||||
|
||||
if (Math.abs(pumpBasalRate - getBaseBasalRate()) > 0.001) {
|
||||
CommandResult readBasalResult = runCommand(MainApp.gs(R.string.combo_actvity_reading_basal_profile), 2, ruffyScripter::readBasalProfile);
|
||||
if (readBasalResult.success) {
|
||||
pump.basalProfile = readBasalResult.basalProfile;
|
||||
Notification notification = new Notification(Notification.COMBO_PUMP_ALARM, MainApp.gs(R.string.combo_warning_pump_basal_rate_changed), Notification.NORMAL);
|
||||
MainApp.bus().post(new EventNewNotification(notification));
|
||||
} else {
|
||||
Notification notification = new Notification(Notification.COMBO_PUMP_ALARM, MainApp.gs(R.string.combo_error_failure_reading_changed_basal_rate), Notification.URGENT);
|
||||
MainApp.bus().post(new EventNewNotification(notification));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Check pump time (on the main menu) and raise notification if time is off.
|
||||
* (setting clock is not supported by ruffy) */
|
||||
private void checkPumpTime(PumpState state) {
|
||||
|
@ -850,8 +944,6 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
|
|||
long lastViolation = 0;
|
||||
if (commandResult.state.unsafeUsageDetected == PumpState.UNSUPPORTED_BOLUS_TYPE) {
|
||||
lastViolation = System.currentTimeMillis();
|
||||
} else if (commandResult.lastBolus != null && !commandResult.lastBolus.isValid) {
|
||||
lastViolation = commandResult.lastBolus.timestamp;
|
||||
} else if (commandResult.history != null) {
|
||||
for (Bolus bolus : commandResult.history.bolusHistory) {
|
||||
if (!bolus.isValid && bolus.timestamp > lastViolation) {
|
||||
|
@ -922,7 +1014,7 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
|
|||
* Only ever called by #readAllPumpData which is triggered by the user via the combo fragment
|
||||
* which warns the user against doing this.
|
||||
*/
|
||||
private boolean readHistory(final PumpHistoryRequest request) {
|
||||
private boolean readHistory(@Nullable PumpHistoryRequest request) {
|
||||
CommandResult historyResult = runCommand(MainApp.gs(R.string.combo_activity_reading_pump_history), 3, () -> ruffyScripter.readHistory(request));
|
||||
if (!historyResult.success) {
|
||||
return false;
|
||||
|
@ -942,85 +1034,107 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
|
|||
return historyResult.success;
|
||||
}
|
||||
|
||||
private synchronized void updateDbFromPumpHistory(@NonNull PumpHistory history) {
|
||||
DatabaseHelper dbHelper = MainApp.getDbHelper();
|
||||
// boluses
|
||||
private boolean updateDbFromPumpHistory(@NonNull PumpHistory history) {
|
||||
boolean updated = false;
|
||||
for (Bolus pumpBolus : history.bolusHistory) {
|
||||
Treatment aapsBolus = dbHelper.getTreatmentByDate(pumpBolus.timestamp);
|
||||
if (aapsBolus == null) {
|
||||
log.debug("Creating bolus record from pump bolus: " + pumpBolus);
|
||||
DetailedBolusInfo dbi = new DetailedBolusInfo();
|
||||
dbi.date = pumpBolus.timestamp;
|
||||
dbi.pumpId = pumpBolus.timestamp;
|
||||
dbi.source = Source.PUMP;
|
||||
dbi.insulin = pumpBolus.amount;
|
||||
dbi.eventType = CareportalEvent.CORRECTIONBOLUS;
|
||||
MainApp.getConfigBuilder().addToHistoryTreatment(dbi);
|
||||
}
|
||||
}
|
||||
|
||||
// TBRs
|
||||
for (Tbr pumpTbr : history.tbrHistory) {
|
||||
TemporaryBasal aapsTbr = dbHelper.getTemporaryBasalsDataByDate(pumpTbr.timestamp);
|
||||
if (aapsTbr == null) {
|
||||
log.debug("Creating TBR from pump TBR: " + pumpTbr);
|
||||
TemporaryBasal temporaryBasal = new TemporaryBasal();
|
||||
temporaryBasal.date = pumpTbr.timestamp;
|
||||
temporaryBasal.pumpId = pumpTbr.timestamp;
|
||||
temporaryBasal.source = Source.PUMP;
|
||||
temporaryBasal.percentRate = pumpTbr.percent;
|
||||
temporaryBasal.durationInMinutes = pumpTbr.duration;
|
||||
temporaryBasal.isAbsolute = false;
|
||||
MainApp.getConfigBuilder().addToHistoryTempBasal(temporaryBasal);
|
||||
DetailedBolusInfo dbi = new DetailedBolusInfo();
|
||||
dbi.date = calculateFakeBolusDate(pumpBolus);
|
||||
dbi.pumpId = calculateFakeBolusDate(pumpBolus);
|
||||
dbi.source = Source.PUMP;
|
||||
dbi.insulin = pumpBolus.amount;
|
||||
dbi.eventType = CareportalEvent.CORRECTIONBOLUS;
|
||||
if (MainApp.getConfigBuilder().addToHistoryTreatment(dbi)) {
|
||||
updated = true;
|
||||
}
|
||||
}
|
||||
return updated;
|
||||
}
|
||||
|
||||
// TODO queue
|
||||
void readTddData() {
|
||||
readHistory(new PumpHistoryRequest().tddHistory(PumpHistoryRequest.FULL));
|
||||
/** Adds the bolus to the timestamp to be able to differentiate multiple boluses in the same
|
||||
* minute. Best effort, since this covers only boluses up to 5.9 U and relies on other code
|
||||
* to prevent a boluses with the same amount to be delivered within the same minute.
|
||||
* Should be good enough, even with command mode, it's a challenge to create that situation
|
||||
* and most time clashes will be around SMBs which are covered.
|
||||
*/
|
||||
private long calculateFakeBolusDate(Bolus pumpBolus) {
|
||||
return pumpBolus.timestamp + (Math.min((int) (pumpBolus.amount - 0.1) * 10 * 1000, 59 * 1000));
|
||||
}
|
||||
|
||||
// TODO use queue once ready
|
||||
void readTddData(Callback post) {
|
||||
// ConfigBuilderPlugin.getCommandQueue().custom(new Callback() {
|
||||
// @Override
|
||||
// public void run() {
|
||||
readHistory(new PumpHistoryRequest().tddHistory(PumpHistoryRequest.FULL));
|
||||
// }
|
||||
// }, post);
|
||||
post.run();
|
||||
ruffyScripter.disconnect();
|
||||
}
|
||||
|
||||
// TODO queue
|
||||
void readAlertData() {
|
||||
readHistory(new PumpHistoryRequest().pumpErrorHistory(PumpHistoryRequest.FULL));
|
||||
// TODO use queue once ready
|
||||
void readAlertData(Callback post) {
|
||||
// ConfigBuilderPlugin.getCommandQueue().custom(new Callback() {
|
||||
// @Override
|
||||
// public void run() {
|
||||
readHistory(new PumpHistoryRequest().pumpErrorHistory(PumpHistoryRequest.FULL));
|
||||
// }
|
||||
// }, post);
|
||||
post.run();
|
||||
ruffyScripter.disconnect();
|
||||
}
|
||||
|
||||
// TODO queue
|
||||
void readAllPumpData() {
|
||||
long lastCheckInitiated = System.currentTimeMillis();
|
||||
|
||||
boolean readHistorySuccess = readHistory(new PumpHistoryRequest()
|
||||
.bolusHistory(pumpHistoryLastChecked)
|
||||
.tbrHistory(pumpHistoryLastChecked)
|
||||
.pumpErrorHistory(PumpHistoryRequest.FULL)
|
||||
.tddHistory(PumpHistoryRequest.FULL));
|
||||
if (!readHistorySuccess) {
|
||||
return;
|
||||
}
|
||||
|
||||
pumpHistoryLastChecked = lastCheckInitiated;
|
||||
|
||||
/* not displayed in the UI anymore due to pump bug
|
||||
CommandResult reservoirResult = runCommand("Checking reservoir level", 2,
|
||||
ruffyScripter::readReservoirLevelAndLastBolus);
|
||||
if (!reservoirResult.success) {
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
CommandResult basalResult = runCommand(MainApp.gs(R.string.combo_actvity_reading_basal_profile), 2, ruffyScripter::readBasalProfile);
|
||||
if (!basalResult.success) {
|
||||
return;
|
||||
}
|
||||
|
||||
pump.basalProfile = basalResult.basalProfile;
|
||||
|
||||
// TODO use queue once ready
|
||||
void readAllPumpData(Callback post) {
|
||||
// ConfigBuilderPlugin.getCommandQueue().custom(new Callback() {
|
||||
// @Override
|
||||
// public void run() {
|
||||
readHistory(new PumpHistoryRequest()
|
||||
.bolusHistory(PumpHistoryRequest.FULL)
|
||||
.pumpErrorHistory(PumpHistoryRequest.FULL)
|
||||
.tddHistory(PumpHistoryRequest.FULL));
|
||||
CommandResult readBasalResult = runCommand(MainApp.gs(R.string.combo_actvity_reading_basal_profile), 2, ruffyScripter::readBasalProfile);
|
||||
if (readBasalResult.success) {
|
||||
pump.basalProfile = readBasalResult.basalProfile;
|
||||
}
|
||||
// }
|
||||
// }, post);
|
||||
post.run();
|
||||
ruffyScripter.disconnect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads QuickInfo to update reservoir level and determine if new boluses exist on the pump
|
||||
* and if so, queries the history for all new records.
|
||||
*
|
||||
* @return null on success or the failed command result
|
||||
*/
|
||||
private CommandResult checkHistory() {
|
||||
CommandResult quickInfoResult = runCommand(MainApp.gs(R.string.combo_activity_checking_for_history_changes), 3, ruffyScripter::readQuickInfo);
|
||||
if (quickInfoResult.history != null && !quickInfoResult.history.bolusHistory.isEmpty()
|
||||
&& quickInfoResult.history.bolusHistory.get(0).timestamp == timestampOfLastKnownPumpBolusRecord) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// OPTIMIZE this reads the entire history on start, so this could be optimized by persisting
|
||||
// `timestampOfLastKnownPumpBolusRecord`, though this should be thought through, to make sure
|
||||
// all scenarios are covered
|
||||
CommandResult historyResult = runCommand(MainApp.gs(R.string.combo_activity_reading_pump_history), 3, () ->
|
||||
ruffyScripter.readHistory(new PumpHistoryRequest()
|
||||
.bolusHistory(timestampOfLastKnownPumpBolusRecord)));
|
||||
if (!historyResult.success) {
|
||||
return historyResult;
|
||||
}
|
||||
|
||||
pumpHistoryChanged = updateDbFromPumpHistory(historyResult.history);
|
||||
|
||||
if (!historyResult.history.bolusHistory.isEmpty()) {
|
||||
timestampOfLastKnownPumpBolusRecord = historyResult.history.bolusHistory.get(0).timestamp;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PumpEnactResult cancelExtendedBolus() {
|
||||
return OPERATION_NOT_SUPPORTED;
|
||||
|
@ -1036,9 +1150,11 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
|
|||
JSONObject pumpJson = new JSONObject();
|
||||
pumpJson.put("clock", DateUtil.toISOString(pump.lastSuccessfulCmdTime));
|
||||
|
||||
int level = 150;
|
||||
if (pump.state.insulinState == PumpState.LOW) level = 8;
|
||||
int level;
|
||||
if (pump.reservoirLevel != -1) level = pump.reservoirLevel;
|
||||
else if (pump.state.insulinState == PumpState.LOW) level = 8;
|
||||
else if (pump.state.insulinState == PumpState.EMPTY) level = 0;
|
||||
else level = 150;
|
||||
pumpJson.put("reservoir", level);
|
||||
|
||||
JSONObject statusJson = new JSONObject();
|
||||
|
@ -1051,7 +1167,7 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
|
|||
extendedJson.put("ActiveProfile", MainApp.getConfigBuilder().getProfileName());
|
||||
PumpState ps = pump.state;
|
||||
if (ps.tbrActive) {
|
||||
extendedJson.put("TempBasalAbsoluteRate", ps.tbrRate);
|
||||
extendedJson.put("TempBasalAbsoluteRate", ps.basalRate);
|
||||
extendedJson.put("TempBasalPercent", ps.tbrPercent);
|
||||
extendedJson.put("TempBasalRemaining", ps.tbrRemainingDuration);
|
||||
}
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
package info.nightscout.androidaps.plugins.PumpCombo;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import de.jotomo.ruffy.spi.BasalProfile;
|
||||
import de.jotomo.ruffy.spi.PumpState;
|
||||
import de.jotomo.ruffy.spi.history.PumpAlert;
|
||||
import de.jotomo.ruffy.spi.history.Tdd;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.BasalProfile;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.PumpState;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.history.Bolus;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.history.PumpAlert;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.history.Tdd;
|
||||
|
||||
class ComboPump {
|
||||
boolean initialized = false;
|
||||
|
@ -17,8 +19,11 @@ class ComboPump {
|
|||
public volatile String activity;
|
||||
@NonNull
|
||||
volatile PumpState state = new PumpState();
|
||||
volatile int reservoirLevel = -1;
|
||||
@NonNull
|
||||
volatile BasalProfile basalProfile = new BasalProfile();
|
||||
@Nullable
|
||||
volatile Bolus lastBolus;
|
||||
|
||||
// Alert and TDD histories are not stored in DB, but are read on demand and just cached here
|
||||
List<PumpAlert> errorHistory = new ArrayList<>(0);
|
||||
|
|
|
@ -11,7 +11,7 @@ import java.text.DateFormat;
|
|||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import de.jotomo.ruffy.spi.history.Tdd;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.history.Tdd;
|
||||
import info.nightscout.androidaps.R;
|
||||
|
||||
public class ComboTddHistoryDialog extends DialogFragment {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package de.jotomo.ruffy.spi;
|
||||
package info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package de.jotomo.ruffy.spi;
|
||||
package info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter;
|
||||
|
||||
public interface BolusProgressReporter {
|
||||
enum State {
|
|
@ -1,20 +1,18 @@
|
|||
package de.jotomo.ruffy.spi;
|
||||
package info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter;
|
||||
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import de.jotomo.ruffy.spi.history.Bolus;
|
||||
import de.jotomo.ruffy.spi.history.PumpHistory;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.history.Bolus;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.history.PumpHistory;
|
||||
|
||||
public class CommandResult {
|
||||
/** Whether the command was executed successfully. */
|
||||
public boolean success;
|
||||
/** State of the pump *after* command execution. */
|
||||
public PumpState state;
|
||||
/** Bolus actually delivered if request was a bolus command. */
|
||||
public double delivered;
|
||||
/** History if requested by the command. */
|
||||
@Nullable
|
||||
public PumpHistory history;
|
||||
|
@ -27,10 +25,6 @@ public class CommandResult {
|
|||
|
||||
public int reservoirLevel = -1;
|
||||
|
||||
/** Only set when by ReadReservoirLevelCommand. */
|
||||
@Nullable
|
||||
public Bolus lastBolus;
|
||||
|
||||
public CommandResult success(boolean success) {
|
||||
this.success = success;
|
||||
return this;
|
||||
|
@ -59,7 +53,6 @@ public class CommandResult {
|
|||
", history=" + history +
|
||||
", basalProfile=" + basalProfile +
|
||||
", forwardedWarnings='" + forwardedWarnings + '\'' +
|
||||
", lastBolus=" + lastBolus +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package de.jotomo.ruffy.spi;
|
||||
package info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter;
|
||||
|
||||
public class PumpErrorCodes {
|
||||
public static final int CARTRIDGE_EMPTY = 1;
|
|
@ -1,4 +1,4 @@
|
|||
package de.jotomo.ruffy.spi;
|
||||
package info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter;
|
||||
|
||||
/** State displayed on the main screen of the pump. */
|
||||
public class PumpState {
|
||||
|
@ -13,8 +13,8 @@ public class PumpState {
|
|||
public boolean tbrActive = false;
|
||||
/** TBR percentage. 100% means no TBR active, just the normal basal rate running. */
|
||||
public int tbrPercent = -1;
|
||||
/** The absolute rate the TBR is running, e.g. 0.80U/h. */
|
||||
public double tbrRate = -1;
|
||||
/** The absolute rate the pump is running (regular basal rate or TBR), e.g. 0.80U/h. */
|
||||
public double basalRate = -1;
|
||||
/** Remaining time of an active TBR. Note that 0:01 is te lowest displayed, the pump
|
||||
* jumps from that to TBR end, skipping 0:00(xx). */
|
||||
public int tbrRemainingDuration = -1;
|
||||
|
@ -52,8 +52,8 @@ public class PumpState {
|
|||
return this;
|
||||
}
|
||||
|
||||
public PumpState tbrRate(double tbrRate) {
|
||||
this.tbrRate = tbrRate;
|
||||
public PumpState basalRate(double basalRate) {
|
||||
this.basalRate = basalRate;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -91,7 +91,7 @@ public class PumpState {
|
|||
", suspended=" + suspended +
|
||||
", tbrActive=" + tbrActive +
|
||||
", tbrPercent=" + tbrPercent +
|
||||
", tbrRate=" + tbrRate +
|
||||
", basalRate=" + basalRate +
|
||||
", tbrRemainingDuration=" + tbrRemainingDuration +
|
||||
", activeAlert=" + activeAlert +
|
||||
", batteryState=" + batteryState +
|
|
@ -1,4 +1,4 @@
|
|||
package de.jotomo.ruffy.spi;
|
||||
package info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter;
|
||||
|
||||
public class PumpWarningCodes {
|
||||
public static final int CARTRIDGE_LOW = 1;
|
|
@ -1,6 +1,6 @@
|
|||
package de.jotomo.ruffy.spi;
|
||||
package info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter;
|
||||
|
||||
import de.jotomo.ruffy.spi.history.PumpHistoryRequest;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.history.PumpHistoryRequest;
|
||||
|
||||
public interface RuffyCommands {
|
||||
/** Issues a bolus issues updates on progress through via {@link BolusProgressReporter}. */
|
||||
|
@ -32,7 +32,7 @@ public interface RuffyCommands {
|
|||
CommandResult readPumpState();
|
||||
|
||||
/** Read reservoir level and last bolus via Quick Info */
|
||||
CommandResult readReservoirLevelAndLastBolus();
|
||||
CommandResult readQuickInfo();
|
||||
|
||||
/** Reads pump history via the My Data menu. The {@link PumpHistoryRequest} specifies
|
||||
* what types of data and how far back data is returned. */
|
||||
|
@ -45,13 +45,5 @@ public interface RuffyCommands {
|
|||
CommandResult getDateAndTime();
|
||||
|
||||
CommandResult setDateAndTime();
|
||||
|
||||
// TODO below methods are drafts
|
||||
void requestPairing();
|
||||
|
||||
/** Send the key displayed on the pump during pairing/bonding. */
|
||||
void sendAuthKey(String key);
|
||||
|
||||
void unpair();
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package de.jotomo.ruffyscripter;
|
||||
package info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
|
@ -10,6 +10,8 @@ import android.os.SystemClock;
|
|||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import com.crashlytics.android.answers.Answers;
|
||||
import com.crashlytics.android.answers.CustomEvent;
|
||||
import com.google.common.base.Joiner;
|
||||
|
||||
import org.monkey.d.ruffy.ruffy.driver.IRTHandler;
|
||||
|
@ -26,24 +28,19 @@ import java.util.Date;
|
|||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import de.jotomo.ruffy.spi.BasalProfile;
|
||||
import de.jotomo.ruffy.spi.BolusProgressReporter;
|
||||
import de.jotomo.ruffy.spi.CommandResult;
|
||||
import de.jotomo.ruffy.spi.PumpState;
|
||||
import de.jotomo.ruffy.spi.RuffyCommands;
|
||||
import de.jotomo.ruffy.spi.WarningOrErrorCode;
|
||||
import de.jotomo.ruffy.spi.history.PumpHistoryRequest;
|
||||
import de.jotomo.ruffyscripter.commands.BolusCommand;
|
||||
import de.jotomo.ruffyscripter.commands.CancelTbrCommand;
|
||||
import de.jotomo.ruffyscripter.commands.Command;
|
||||
import de.jotomo.ruffyscripter.commands.CommandException;
|
||||
import de.jotomo.ruffyscripter.commands.ConfirmAlertCommand;
|
||||
import de.jotomo.ruffyscripter.commands.ReadBasalProfileCommand;
|
||||
import de.jotomo.ruffyscripter.commands.ReadHistoryCommand;
|
||||
import de.jotomo.ruffyscripter.commands.ReadPumpStateCommand;
|
||||
import de.jotomo.ruffyscripter.commands.ReadReservoirLevelAndLastBolus;
|
||||
import de.jotomo.ruffyscripter.commands.SetBasalProfileCommand;
|
||||
import de.jotomo.ruffyscripter.commands.SetTbrCommand;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.commands.ReadQuickInfoCommand;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.history.PumpHistoryRequest;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.commands.BolusCommand;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.commands.CancelTbrCommand;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.commands.Command;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.commands.CommandException;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.commands.ConfirmAlertCommand;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.commands.ReadBasalProfileCommand;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.commands.ReadHistoryCommand;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.commands.ReadPumpStateCommand;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.commands.SetBasalProfileCommand;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.commands.SetTbrCommand;
|
||||
import info.nightscout.androidaps.BuildConfig;
|
||||
|
||||
/**
|
||||
* Provides scripting 'runtime' and operations. consider moving operations into a separate
|
||||
|
@ -51,6 +48,8 @@ import de.jotomo.ruffyscripter.commands.SetTbrCommand;
|
|||
* operations and are cleanly separated from the thread management, connection management etc
|
||||
*/
|
||||
public class RuffyScripter implements RuffyCommands {
|
||||
private final boolean readQuickInfo = true;
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(RuffyScripter.class);
|
||||
|
||||
private IRuffyService ruffyService;
|
||||
|
@ -59,6 +58,7 @@ public class RuffyScripter implements RuffyCommands {
|
|||
private volatile Menu currentMenu;
|
||||
private volatile long menuLastUpdated = 0;
|
||||
|
||||
private String previousCommand = "<none>";
|
||||
private volatile Command activeCmd = null;
|
||||
|
||||
private boolean started = false;
|
||||
|
@ -69,14 +69,21 @@ public class RuffyScripter implements RuffyCommands {
|
|||
@Override
|
||||
public void log(String message) throws RemoteException {
|
||||
if (log.isTraceEnabled()) {
|
||||
log.debug("Ruffy says: " + message);
|
||||
log.trace("Ruffy says: " + message);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fail(String message) throws RemoteException {
|
||||
// TODO 10-28 19:50:54.059 1426 1826 W RuffyScripter: [Thread-268] WARN [de.jotomo.ruffyscripter.RuffyScripter$1:78]: Ruffy warns: no connection possible
|
||||
log.warn("Ruffy warns: " + message);
|
||||
if (message.startsWith("no connection possible"))
|
||||
Answers.getInstance().logCustom(new CustomEvent("ComboRuffyWarning").putCustomAttribute("message", "no connection possible"));
|
||||
else if (message.startsWith("Error sending keep alive while rtModeRunning is still true"))
|
||||
Answers.getInstance().logCustom(new CustomEvent("ComboRuffyWarning").putCustomAttribute("message", "Error sending keep alive while rtModeRunning is still true"));
|
||||
else if (message.startsWith("Error sending keep alive. rtModeRunning is false, so this is most likely a race condition during disconnect"))
|
||||
Answers.getInstance().logCustom(new CustomEvent("ComboRuffyWarning").putCustomAttribute("message", "Error sending keep alive. rtModeRunning is false, so this is most likely a race condition during disconnect"));
|
||||
else
|
||||
Answers.getInstance().logCustom(new CustomEvent("ComboRuffyWarning").putCustomAttribute("message", message.substring(0, 98)));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -122,7 +129,7 @@ public class RuffyScripter implements RuffyCommands {
|
|||
}
|
||||
};
|
||||
|
||||
RuffyScripter(Context context) {
|
||||
public RuffyScripter(Context context) {
|
||||
boolean boundSucceeded = false;
|
||||
|
||||
try {
|
||||
|
@ -165,6 +172,10 @@ public class RuffyScripter implements RuffyCommands {
|
|||
|
||||
if (!boundSucceeded) {
|
||||
log.error("No connection to ruffy. Pump control unavailable.");
|
||||
} else {
|
||||
Answers.getInstance().logCustom(new CustomEvent("ComboScripterInit")
|
||||
.putCustomAttribute("buildversion", BuildConfig.BUILDVERSION)
|
||||
.putCustomAttribute("version", BuildConfig.VERSION));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -214,8 +225,17 @@ public class RuffyScripter implements RuffyCommands {
|
|||
}
|
||||
|
||||
@Override
|
||||
public CommandResult readReservoirLevelAndLastBolus() {
|
||||
return runCommand(new ReadReservoirLevelAndLastBolus());
|
||||
public CommandResult readQuickInfo() {
|
||||
if (readQuickInfo) {
|
||||
Answers.getInstance().logCustom(new CustomEvent("ComboReadQuickInfoCmd")
|
||||
.putCustomAttribute("buildversion", BuildConfig.BUILDVERSION)
|
||||
.putCustomAttribute("version", BuildConfig.VERSION));
|
||||
return runCommand(new ReadQuickInfoCommand());
|
||||
}
|
||||
Answers.getInstance().logCustom(new CustomEvent("ComboReadHistoryCmd")
|
||||
.putCustomAttribute("buildversion", BuildConfig.BUILDVERSION)
|
||||
.putCustomAttribute("version", BuildConfig.VERSION));
|
||||
return runCommand(new ReadHistoryCommand(new PumpHistoryRequest().bolusHistory(PumpHistoryRequest.LAST)));
|
||||
}
|
||||
|
||||
public void returnToRootMenu() {
|
||||
|
@ -344,6 +364,7 @@ public class RuffyScripter implements RuffyCommands {
|
|||
// ignore
|
||||
}
|
||||
}
|
||||
previousCommand = "" + activeCmd;
|
||||
activeCmd = null;
|
||||
}
|
||||
}
|
||||
|
@ -412,6 +433,11 @@ public class RuffyScripter implements RuffyCommands {
|
|||
}
|
||||
}
|
||||
log.debug("Recovery from connection loss " + (connected ? "succeeded" : "failed"));
|
||||
Answers.getInstance().logCustom(new CustomEvent("ComboRecoveryFromConnectionLoss")
|
||||
.putCustomAttribute("buildversion", BuildConfig.BUILDVERSION)
|
||||
.putCustomAttribute("version", BuildConfig.VERSION)
|
||||
.putCustomAttribute("activeCommand", "" + activeCmd)
|
||||
.putCustomAttribute("success", connected ? "true" : "else"));
|
||||
return connected;
|
||||
}
|
||||
|
||||
|
@ -422,6 +448,11 @@ public class RuffyScripter implements RuffyCommands {
|
|||
private PumpState recoverFromCommandFailure() {
|
||||
Menu menu = this.currentMenu;
|
||||
if (menu == null) {
|
||||
Answers.getInstance().logCustom(new CustomEvent("ComboRecoveryFromCommandFailure")
|
||||
.putCustomAttribute("buildversion", BuildConfig.BUILDVERSION)
|
||||
.putCustomAttribute("version", BuildConfig.VERSION)
|
||||
.putCustomAttribute("activeCommand", "" + activeCmd)
|
||||
.putCustomAttribute("success", "false"));
|
||||
return new PumpState();
|
||||
}
|
||||
MenuType type = menu.getType();
|
||||
|
@ -434,8 +465,19 @@ public class RuffyScripter implements RuffyCommands {
|
|||
}
|
||||
}
|
||||
try {
|
||||
return readPumpStateInternal();
|
||||
PumpState pumpState = readPumpStateInternal();
|
||||
Answers.getInstance().logCustom(new CustomEvent("ComboRecoveryFromCommandFailure")
|
||||
.putCustomAttribute("buildversion", BuildConfig.BUILDVERSION)
|
||||
.putCustomAttribute("version", BuildConfig.VERSION)
|
||||
.putCustomAttribute("activeCommand", "" + activeCmd)
|
||||
.putCustomAttribute("success", "true"));
|
||||
return pumpState;
|
||||
} catch (Exception e) {
|
||||
Answers.getInstance().logCustom(new CustomEvent("ComboRecoveryFromCommandFailure")
|
||||
.putCustomAttribute("buildversion", BuildConfig.BUILDVERSION)
|
||||
.putCustomAttribute("version", BuildConfig.VERSION)
|
||||
.putCustomAttribute("activeCommand", "" + activeCmd)
|
||||
.putCustomAttribute("success", "false"));
|
||||
log.debug("Reading pump state during recovery failed", e);
|
||||
return new PumpState();
|
||||
}
|
||||
|
@ -457,6 +499,11 @@ public class RuffyScripter implements RuffyCommands {
|
|||
long initialUpdateTime = menuLastUpdated;
|
||||
while (initialUpdateTime == menuLastUpdated) {
|
||||
if (System.currentTimeMillis() > timeoutExpired) {
|
||||
Answers.getInstance().logCustom(new CustomEvent("ComboConnectTimeout")
|
||||
.putCustomAttribute("buildversion", BuildConfig.BUILDVERSION)
|
||||
.putCustomAttribute("version", BuildConfig.VERSION)
|
||||
.putCustomAttribute("activeCommand", "" + activeCmd)
|
||||
.putCustomAttribute("previousCommand", previousCommand));
|
||||
throw new CommandException("Timeout connecting to pump");
|
||||
}
|
||||
SystemClock.sleep(50);
|
||||
|
@ -479,7 +526,7 @@ public class RuffyScripter implements RuffyCommands {
|
|||
}
|
||||
|
||||
/**
|
||||
* This reads the state of the, which is whatever is currently displayed on the display,
|
||||
* This reads the state of the pump, which is whatever is currently displayed on the display,
|
||||
* no actions are performed.
|
||||
*/
|
||||
public PumpState readPumpStateInternal() {
|
||||
|
@ -510,7 +557,9 @@ public class RuffyScripter implements RuffyCommands {
|
|||
state.tbrPercent = displayedTbr.intValue();
|
||||
MenuTime durationMenuTime = ((MenuTime) menu.getAttribute(MenuAttribute.RUNTIME));
|
||||
state.tbrRemainingDuration = durationMenuTime.getHour() * 60 + durationMenuTime.getMinute();
|
||||
state.tbrRate = ((double) menu.getAttribute(MenuAttribute.BASAL_RATE));
|
||||
}
|
||||
if (menu.attributes().contains(MenuAttribute.BASAL_RATE)) {
|
||||
state.basalRate = ((double) menu.getAttribute(MenuAttribute.BASAL_RATE));
|
||||
}
|
||||
if (menu.attributes().contains(MenuAttribute.BATTERY_STATE)) {
|
||||
state.batteryState = ((int) menu.getAttribute(MenuAttribute.BATTERY_STATE));
|
||||
|
@ -763,12 +812,18 @@ public class RuffyScripter implements RuffyCommands {
|
|||
|
||||
@Override
|
||||
public CommandResult deliverBolus(double amount, BolusProgressReporter bolusProgressReporter) {
|
||||
Answers.getInstance().logCustom(new CustomEvent("ComboBolusCmd")
|
||||
.putCustomAttribute("buildversion", BuildConfig.BUILDVERSION)
|
||||
.putCustomAttribute("version", BuildConfig.VERSION));
|
||||
return runCommand(new BolusCommand(amount, bolusProgressReporter));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelBolus() {
|
||||
if (activeCmd instanceof BolusCommand) {
|
||||
Answers.getInstance().logCustom(new CustomEvent("ComboBolusCmdCancel")
|
||||
.putCustomAttribute("buildversion", BuildConfig.BUILDVERSION)
|
||||
.putCustomAttribute("version", BuildConfig.VERSION));
|
||||
((BolusCommand) activeCmd).requestCancellation();
|
||||
} else {
|
||||
log.error("cancelBolus called, but active command is not a bolus:" + activeCmd);
|
||||
|
@ -777,31 +832,49 @@ public class RuffyScripter implements RuffyCommands {
|
|||
|
||||
@Override
|
||||
public CommandResult setTbr(int percent, int duration) {
|
||||
Answers.getInstance().logCustom(new CustomEvent("ComboSetTbrCmd")
|
||||
.putCustomAttribute("buildversion", BuildConfig.BUILDVERSION)
|
||||
.putCustomAttribute("version", BuildConfig.VERSION));
|
||||
return runCommand(new SetTbrCommand(percent, duration));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult cancelTbr() {
|
||||
Answers.getInstance().logCustom(new CustomEvent("ComboCancelTbrCmd")
|
||||
.putCustomAttribute("buildversion", BuildConfig.BUILDVERSION)
|
||||
.putCustomAttribute("version", BuildConfig.VERSION));
|
||||
return runCommand(new CancelTbrCommand());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult confirmAlert(int warningCode) {
|
||||
Answers.getInstance().logCustom(new CustomEvent("ComboConfirmAlertCmd")
|
||||
.putCustomAttribute("buildversion", BuildConfig.BUILDVERSION)
|
||||
.putCustomAttribute("version", BuildConfig.VERSION));
|
||||
return runCommand(new ConfirmAlertCommand(warningCode));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult readHistory(PumpHistoryRequest request) {
|
||||
Answers.getInstance().logCustom(new CustomEvent("ComboReadHistoryCmd")
|
||||
.putCustomAttribute("buildversion", BuildConfig.BUILDVERSION)
|
||||
.putCustomAttribute("version", BuildConfig.VERSION));
|
||||
return runCommand(new ReadHistoryCommand(request));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult readBasalProfile() {
|
||||
Answers.getInstance().logCustom(new CustomEvent("ComboReadBasalProfileCmd")
|
||||
.putCustomAttribute("buildversion", BuildConfig.BUILDVERSION)
|
||||
.putCustomAttribute("version", BuildConfig.VERSION));
|
||||
return runCommand(new ReadBasalProfileCommand());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult setBasalProfile(BasalProfile basalProfile) {
|
||||
Answers.getInstance().logCustom(new CustomEvent("ComboSetBasalProfileCmd")
|
||||
.putCustomAttribute("buildversion", BuildConfig.BUILDVERSION)
|
||||
.putCustomAttribute("version", BuildConfig.VERSION));
|
||||
return runCommand(new SetBasalProfileCommand(basalProfile));
|
||||
}
|
||||
|
||||
|
@ -815,21 +888,6 @@ public class RuffyScripter implements RuffyCommands {
|
|||
throw new RuntimeException("Not supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestPairing() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendAuthKey(String key) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unpair() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirms and dismisses the given alert if it's raised before the timeout
|
||||
*/
|
|
@ -1,4 +1,4 @@
|
|||
package de.jotomo.ruffy.spi;
|
||||
package info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter;
|
||||
|
||||
import android.support.annotation.Nullable;
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
package info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.commands;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.monkey.d.ruffy.ruffy.driver.display.MenuAttribute;
|
||||
import org.monkey.d.ruffy.ruffy.driver.display.MenuType;
|
||||
import org.monkey.d.ruffy.ruffy.driver.display.menu.BolusType;
|
||||
import org.monkey.d.ruffy.ruffy.driver.display.menu.MenuDate;
|
||||
import org.monkey.d.ruffy.ruffy.driver.display.menu.MenuTime;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.CommandResult;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.PumpWarningCodes;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.RuffyScripter;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.history.Bolus;
|
||||
|
||||
public abstract class BaseCommand implements Command {
|
||||
// RS will inject itself here
|
||||
protected RuffyScripter scripter;
|
||||
|
||||
protected CommandResult result;
|
||||
|
||||
public BaseCommand() {
|
||||
result = new CommandResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setScripter(RuffyScripter scripter) {
|
||||
this.scripter = scripter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean needsRunMode() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* A warning id (or null) caused by a disconnect we can safely confirm on reconnect,
|
||||
* knowing it's not severe as it was caused by this command.
|
||||
* @see PumpWarningCodes
|
||||
*/
|
||||
@Override
|
||||
public Integer getReconnectWarningId() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> validateArguments() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult getResult() {
|
||||
return result;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
protected Bolus readBolusRecord() {
|
||||
scripter.verifyMenuIsDisplayed(MenuType.BOLUS_DATA);
|
||||
BolusType bolusType = (BolusType) scripter.getCurrentMenu().getAttribute(MenuAttribute.BOLUS_TYPE);
|
||||
boolean isValid = bolusType == BolusType.NORMAL;
|
||||
Double bolus = (Double) scripter.getCurrentMenu().getAttribute(MenuAttribute.BOLUS);
|
||||
long recordDate = readRecordDate();
|
||||
return new Bolus(recordDate, bolus, isValid);
|
||||
}
|
||||
|
||||
protected long readRecordDate() {
|
||||
MenuDate date = (MenuDate) scripter.getCurrentMenu().getAttribute(MenuAttribute.DATE);
|
||||
MenuTime time = (MenuTime) scripter.getCurrentMenu().getAttribute(MenuAttribute.TIME);
|
||||
|
||||
int year = Calendar.getInstance().get(Calendar.YEAR);
|
||||
if (date.getMonth() > Calendar.getInstance().get(Calendar.MONTH) + 1) {
|
||||
year -= 1;
|
||||
}
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.set(year, date.getMonth() - 1, date.getDay(), time.getHour(), time.getMinute(), 0);
|
||||
|
||||
// round to second
|
||||
return calendar.getTimeInMillis() - calendar.getTimeInMillis() % 1000;
|
||||
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package de.jotomo.ruffyscripter.commands;
|
||||
package info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.commands;
|
||||
|
||||
import android.os.SystemClock;
|
||||
|
||||
|
@ -11,17 +11,18 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import de.jotomo.ruffy.spi.BolusProgressReporter;
|
||||
import de.jotomo.ruffy.spi.PumpWarningCodes;
|
||||
import de.jotomo.ruffy.spi.WarningOrErrorCode;
|
||||
import de.jotomo.ruffy.spi.history.Bolus;
|
||||
import de.jotomo.ruffyscripter.RuffyScripter;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.BolusProgressReporter;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.CommandResult;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.PumpWarningCodes;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.WarningOrErrorCode;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.history.Bolus;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.RuffyScripter;
|
||||
|
||||
import static de.jotomo.ruffy.spi.BolusProgressReporter.State.DELIVERED;
|
||||
import static de.jotomo.ruffy.spi.BolusProgressReporter.State.DELIVERING;
|
||||
import static de.jotomo.ruffy.spi.BolusProgressReporter.State.PROGRAMMING;
|
||||
import static de.jotomo.ruffy.spi.BolusProgressReporter.State.STOPPED;
|
||||
import static de.jotomo.ruffy.spi.BolusProgressReporter.State.STOPPING;
|
||||
import static info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.BolusProgressReporter.State.DELIVERED;
|
||||
import static info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.BolusProgressReporter.State.DELIVERING;
|
||||
import static info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.BolusProgressReporter.State.PROGRAMMING;
|
||||
import static info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.BolusProgressReporter.State.STOPPED;
|
||||
import static info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.BolusProgressReporter.State.STOPPING;
|
||||
|
||||
public class BolusCommand extends BaseCommand {
|
||||
private static final Logger log = LoggerFactory.getLogger(BolusCommand.class);
|
||||
|
@ -184,19 +185,9 @@ public class BolusCommand extends BaseCommand {
|
|||
}
|
||||
|
||||
if (cancelInProgress) {
|
||||
log.debug("Stage 4: reading last bolus from pump history since a cancellation was requested during bolus delivery");
|
||||
ReadReservoirLevelAndLastBolus readReservoirLevelAndLastBolus = new ReadReservoirLevelAndLastBolus();
|
||||
readReservoirLevelAndLastBolus.setScripter(scripter);
|
||||
readReservoirLevelAndLastBolus.execute();
|
||||
Bolus lastBolus = readReservoirLevelAndLastBolus.result.lastBolus;
|
||||
if (lastBolus == null || Math.abs(System.currentTimeMillis() - lastBolus.timestamp) >= 10 * 60 * 1000) {
|
||||
throw new CommandException("Unable to determine last bolus");
|
||||
}
|
||||
log.debug("Stage 4: " + lastBolus.amount + " U delivered before cancellation according to history");
|
||||
result.delivered = lastBolus.amount;
|
||||
log.debug("Stage 4: bolus was cancelled, with unknown amount delivered");
|
||||
} else {
|
||||
log.debug("Stage 4: full bolus of " + bolus + " U was successfully delivered");
|
||||
result.delivered = bolus;
|
||||
bolusProgressReporter.report(DELIVERED, 100, bolus);
|
||||
}
|
||||
result.success = true;
|
|
@ -1,11 +1,11 @@
|
|||
package de.jotomo.ruffyscripter.commands;
|
||||
package info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.commands;
|
||||
|
||||
import org.monkey.d.ruffy.ruffy.driver.display.MenuType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import de.jotomo.ruffy.spi.PumpState;
|
||||
import de.jotomo.ruffy.spi.PumpWarningCodes;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.PumpState;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.PumpWarningCodes;
|
||||
|
||||
public class CancelTbrCommand extends BaseCommand {
|
||||
private static final Logger log = LoggerFactory.getLogger(CancelTbrCommand.class);
|
|
@ -1,9 +1,9 @@
|
|||
package de.jotomo.ruffyscripter.commands;
|
||||
package info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.commands;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import de.jotomo.ruffyscripter.RuffyScripter;
|
||||
import de.jotomo.ruffy.spi.CommandResult;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.RuffyScripter;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.CommandResult;
|
||||
|
||||
/**
|
||||
* Interface for all commands to be executed by the pump.
|
|
@ -1,4 +1,4 @@
|
|||
package de.jotomo.ruffyscripter.commands;
|
||||
package info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.commands;
|
||||
|
||||
public class CommandException extends RuntimeException {
|
||||
public CommandException(String message) {
|
|
@ -1,4 +1,4 @@
|
|||
package de.jotomo.ruffyscripter.commands;
|
||||
package info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.commands;
|
||||
|
||||
public class ConfirmAlertCommand extends BaseCommand {
|
||||
private final int warningCode;
|
|
@ -1,4 +1,4 @@
|
|||
package de.jotomo.ruffyscripter.commands;
|
||||
package info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.commands;
|
||||
|
||||
import org.monkey.d.ruffy.ruffy.driver.display.Menu;
|
||||
import org.monkey.d.ruffy.ruffy.driver.display.MenuAttribute;
|
||||
|
@ -9,8 +9,8 @@ import org.slf4j.LoggerFactory;
|
|||
|
||||
import java.util.Arrays;
|
||||
|
||||
import de.jotomo.ruffy.spi.BasalProfile;
|
||||
import de.jotomo.ruffy.spi.PumpState;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.BasalProfile;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.PumpState;
|
||||
|
||||
public class ReadBasalProfileCommand extends BaseCommand {
|
||||
private static final Logger log = LoggerFactory.getLogger(ReadBasalProfileCommand.class);
|
|
@ -1,4 +1,4 @@
|
|||
package de.jotomo.ruffyscripter.commands;
|
||||
package info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.commands;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
|
@ -13,15 +13,13 @@ import org.slf4j.LoggerFactory;
|
|||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
|
||||
import de.jotomo.ruffy.spi.history.Bolus;
|
||||
import de.jotomo.ruffy.spi.history.PumpAlert;
|
||||
import de.jotomo.ruffy.spi.history.PumpHistory;
|
||||
import de.jotomo.ruffy.spi.history.PumpHistoryRequest;
|
||||
import de.jotomo.ruffy.spi.history.Tbr;
|
||||
import de.jotomo.ruffy.spi.history.Tdd;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.history.Bolus;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.history.PumpAlert;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.history.PumpHistory;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.history.PumpHistoryRequest;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.history.Tbr;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.history.Tdd;
|
||||
|
||||
// Note: TBRs are added to history only after they've completed running
|
||||
// TODO remove duplication
|
||||
public class ReadHistoryCommand extends BaseCommand {
|
||||
private static Logger log = LoggerFactory.getLogger(ReadHistoryCommand.class);
|
||||
|
||||
|
@ -60,47 +58,51 @@ public class ReadHistoryCommand extends BaseCommand {
|
|||
}
|
||||
}
|
||||
|
||||
// error history
|
||||
scripter.pressMenuKey();
|
||||
scripter.verifyMenuIsDisplayed(MenuType.ERROR_DATA);
|
||||
if (request.pumpErrorHistory != PumpHistoryRequest.SKIP) {
|
||||
int totalRecords = (int) scripter.getCurrentMenu().getAttribute(MenuAttribute.TOTAL_RECORD);
|
||||
if (totalRecords > 0) {
|
||||
if (request.pumpErrorHistory == PumpHistoryRequest.LAST) {
|
||||
PumpAlert error = readAlertRecord();
|
||||
history.pumpAlertHistory.add(error);
|
||||
} else {
|
||||
readAlertRecords(request.pumpErrorHistory);
|
||||
if (request.pumpErrorHistory != PumpHistoryRequest.SKIP
|
||||
|| request.tddHistory != PumpHistoryRequest.SKIP
|
||||
|| request.tbrHistory != PumpHistoryRequest.SKIP) {
|
||||
// error history
|
||||
scripter.pressMenuKey();
|
||||
scripter.verifyMenuIsDisplayed(MenuType.ERROR_DATA);
|
||||
if (request.pumpErrorHistory != PumpHistoryRequest.SKIP) {
|
||||
int totalRecords = (int) scripter.getCurrentMenu().getAttribute(MenuAttribute.TOTAL_RECORD);
|
||||
if (totalRecords > 0) {
|
||||
if (request.pumpErrorHistory == PumpHistoryRequest.LAST) {
|
||||
PumpAlert error = readAlertRecord();
|
||||
history.pumpAlertHistory.add(error);
|
||||
} else {
|
||||
readAlertRecords(request.pumpErrorHistory);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// tdd history
|
||||
scripter.pressMenuKey();
|
||||
scripter.verifyMenuIsDisplayed(MenuType.DAILY_DATA);
|
||||
if (request.tddHistory != PumpHistoryRequest.SKIP) {
|
||||
int totalRecords = (int) scripter.getCurrentMenu().getAttribute(MenuAttribute.TOTAL_RECORD);
|
||||
if (totalRecords > 0) {
|
||||
if (request.tddHistory == PumpHistoryRequest.LAST) {
|
||||
Tdd tdd = readTddRecord();
|
||||
history.tddHistory.add(tdd);
|
||||
} else {
|
||||
readTddRecords(request.tbrHistory);
|
||||
// tdd history (TBRs are added to history only after they've completed running)
|
||||
scripter.pressMenuKey();
|
||||
scripter.verifyMenuIsDisplayed(MenuType.DAILY_DATA);
|
||||
if (request.tddHistory != PumpHistoryRequest.SKIP) {
|
||||
int totalRecords = (int) scripter.getCurrentMenu().getAttribute(MenuAttribute.TOTAL_RECORD);
|
||||
if (totalRecords > 0) {
|
||||
if (request.tddHistory == PumpHistoryRequest.LAST) {
|
||||
Tdd tdd = readTddRecord();
|
||||
history.tddHistory.add(tdd);
|
||||
} else {
|
||||
readTddRecords(request.tbrHistory);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// tbr history
|
||||
scripter.pressMenuKey();
|
||||
scripter.verifyMenuIsDisplayed(MenuType.TBR_DATA);
|
||||
if (request.tbrHistory != PumpHistoryRequest.SKIP) {
|
||||
int totalRecords = (int) scripter.getCurrentMenu().getAttribute(MenuAttribute.TOTAL_RECORD);
|
||||
if (totalRecords > 0) {
|
||||
if (request.tbrHistory == PumpHistoryRequest.LAST) {
|
||||
Tbr tbr = readTbrRecord();
|
||||
history.tbrHistory.add(tbr);
|
||||
} else {
|
||||
readTbrRecords(request.tbrHistory);
|
||||
// tbr history
|
||||
scripter.pressMenuKey();
|
||||
scripter.verifyMenuIsDisplayed(MenuType.TBR_DATA);
|
||||
if (request.tbrHistory != PumpHistoryRequest.SKIP) {
|
||||
int totalRecords = (int) scripter.getCurrentMenu().getAttribute(MenuAttribute.TOTAL_RECORD);
|
||||
if (totalRecords > 0) {
|
||||
if (request.tbrHistory == PumpHistoryRequest.LAST) {
|
||||
Tbr tbr = readTbrRecord();
|
||||
history.tbrHistory.add(tbr);
|
||||
} else {
|
||||
readTbrRecords(request.tbrHistory);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -230,16 +232,6 @@ public class ReadHistoryCommand extends BaseCommand {
|
|||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private Bolus readBolusRecord() {
|
||||
scripter.verifyMenuIsDisplayed(MenuType.BOLUS_DATA);
|
||||
BolusType bolusType = (BolusType) scripter.getCurrentMenu().getAttribute(MenuAttribute.BOLUS_TYPE);
|
||||
boolean isValid = bolusType == BolusType.NORMAL;
|
||||
Double bolus = (Double) scripter.getCurrentMenu().getAttribute(MenuAttribute.BOLUS);
|
||||
long recordDate = readRecordDate();
|
||||
return new Bolus(recordDate, bolus, isValid);
|
||||
}
|
||||
|
||||
private void readAlertRecords(long requestedTime) {
|
||||
int record = (int) scripter.getCurrentMenu().getAttribute(MenuAttribute.CURRENT_RECORD);
|
||||
int totalRecords = (int) scripter.getCurrentMenu().getAttribute(MenuAttribute.TOTAL_RECORD);
|
||||
|
@ -273,22 +265,6 @@ public class ReadHistoryCommand extends BaseCommand {
|
|||
return new PumpAlert(recordDate, warningCode, errorCode, message);
|
||||
}
|
||||
|
||||
private long readRecordDate() {
|
||||
MenuDate date = (MenuDate) scripter.getCurrentMenu().getAttribute(MenuAttribute.DATE);
|
||||
MenuTime time = (MenuTime) scripter.getCurrentMenu().getAttribute(MenuAttribute.TIME);
|
||||
|
||||
int year = Calendar.getInstance().get(Calendar.YEAR);
|
||||
if (date.getMonth() > Calendar.getInstance().get(Calendar.MONTH) + 1) {
|
||||
year -= 1;
|
||||
}
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.set(year, date.getMonth() - 1, date.getDay(), time.getHour(), time.getMinute(), 0);
|
||||
|
||||
// round to second
|
||||
return calendar.getTimeInMillis() - calendar.getTimeInMillis() % 1000;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ReadHistoryCommand{" +
|
|
@ -1,4 +1,4 @@
|
|||
package de.jotomo.ruffyscripter.commands;
|
||||
package info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.commands;
|
||||
|
||||
public class ReadPumpStateCommand extends BaseCommand {
|
||||
@Override
|
|
@ -0,0 +1,38 @@
|
|||
package info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.commands;
|
||||
|
||||
import org.monkey.d.ruffy.ruffy.driver.display.MenuAttribute;
|
||||
import org.monkey.d.ruffy.ruffy.driver.display.MenuType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.history.Bolus;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.history.PumpHistory;
|
||||
|
||||
public class ReadQuickInfoCommand extends BaseCommand {
|
||||
@Override
|
||||
public void execute() {
|
||||
scripter.verifyRootMenuIsDisplayed();
|
||||
scripter.pressCheckKey();
|
||||
scripter.waitForMenuToBeLeft(MenuType.MAIN_MENU);
|
||||
scripter.waitForMenuToBeLeft(MenuType.STOP);
|
||||
scripter.verifyMenuIsDisplayed(MenuType.QUICK_INFO);
|
||||
result.reservoirLevel = ((Double) scripter.getCurrentMenu().getAttribute(MenuAttribute.REMAINING_INSULIN)).intValue();
|
||||
scripter.pressCheckKey();
|
||||
List<Bolus> bolusHistory = new ArrayList<>(1);
|
||||
bolusHistory.add(readBolusRecord());
|
||||
result.history = new PumpHistory().bolusHistory(bolusHistory);
|
||||
scripter.returnToRootMenu();
|
||||
result.success = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean needsRunMode() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ReadQuickInfoCommand{}";
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package de.jotomo.ruffyscripter.commands;
|
||||
package info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.commands;
|
||||
|
||||
import android.os.SystemClock;
|
||||
|
||||
|
@ -12,8 +12,8 @@ import org.slf4j.LoggerFactory;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import de.jotomo.ruffy.spi.BasalProfile;
|
||||
import de.jotomo.ruffy.spi.PumpState;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.BasalProfile;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.PumpState;
|
||||
|
||||
public class SetBasalProfileCommand extends BaseCommand {
|
||||
private static final Logger log = LoggerFactory.getLogger(SetBasalProfileCommand.class);
|
|
@ -1,4 +1,4 @@
|
|||
package de.jotomo.ruffyscripter.commands;
|
||||
package info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.commands;
|
||||
|
||||
import android.os.SystemClock;
|
||||
|
||||
|
@ -12,9 +12,9 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import de.jotomo.ruffy.spi.PumpState;
|
||||
import de.jotomo.ruffy.spi.PumpWarningCodes;
|
||||
import de.jotomo.ruffy.spi.WarningOrErrorCode;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.PumpState;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.PumpWarningCodes;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.WarningOrErrorCode;
|
||||
|
||||
public class SetTbrCommand extends BaseCommand {
|
||||
private static final Logger log = LoggerFactory.getLogger(SetTbrCommand.class);
|
|
@ -1,4 +1,4 @@
|
|||
package de.jotomo.ruffy.spi.history;
|
||||
package info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.history;
|
||||
|
||||
import java.util.Date;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package de.jotomo.ruffy.spi.history;
|
||||
package info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.history;
|
||||
|
||||
public abstract class HistoryRecord {
|
||||
public final long timestamp;
|
|
@ -1,4 +1,4 @@
|
|||
package de.jotomo.ruffy.spi.history;
|
||||
package info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.history;
|
||||
|
||||
import java.util.Date;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package de.jotomo.ruffy.spi.history;
|
||||
package info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.history;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package de.jotomo.ruffy.spi.history;
|
||||
package info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.history;
|
||||
|
||||
import java.util.Date;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package de.jotomo.ruffy.spi.history;
|
||||
package info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.history;
|
||||
|
||||
import java.util.Date;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package de.jotomo.ruffy.spi.history;
|
||||
package info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.history;
|
||||
|
||||
import java.util.Date;
|
||||
|
|
@ -127,6 +127,11 @@ public class DateUtil {
|
|||
return String.format(MainApp.sResources.getString(R.string.minago), mins);
|
||||
}
|
||||
|
||||
public static String hourAgo(long time) {
|
||||
double hours = (System.currentTimeMillis() - time) / 1000d / 60 / 60;
|
||||
return String.format(MainApp.sResources.getString(R.string.hoursago), hours);
|
||||
}
|
||||
|
||||
private static LongSparseArray<String> timeStrings = new LongSparseArray<>();
|
||||
|
||||
public static String timeStringFromSeconds(int seconds) {
|
||||
|
|
|
@ -87,7 +87,7 @@
|
|||
android:text=":"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<TextView
|
||||
<com.joanzapata.iconify.widget.IconTextView
|
||||
android:id="@+id/combo_activity"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
@ -236,7 +236,6 @@
|
|||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- reading last bolus from pump triggers pump bug
|
||||
<View
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="2dip"
|
||||
|
@ -281,7 +280,6 @@
|
|||
android:textSize="14sp" />
|
||||
|
||||
</LinearLayout>
|
||||
-->
|
||||
|
||||
<View
|
||||
android:layout_width="fill_parent"
|
||||
|
|
|
@ -224,7 +224,6 @@
|
|||
<string name="danar_iob_label">IOB на помпата</string>
|
||||
<string name="danar_dailyunits">Инсулин за деня</string>
|
||||
<string name="pump_lastbolus_label">Последен болус:</string>
|
||||
<string name="hoursago">ч по-рано</string>
|
||||
<string name="danar_invalidinput">Грешни входящи данни</string>
|
||||
<string name="danar_valuenotsetproperly">Неправилна стойност</string>
|
||||
<string name="reloadprofile">Презареди профил</string>
|
||||
|
|
|
@ -206,7 +206,6 @@
|
|||
<string name="enacted">Provedeno</string>
|
||||
<string name="end_user_license_agreement">Licenční ujednání</string>
|
||||
<string name="end_user_license_agreement_i_understand">ROZUMÍM A PORVZUJI</string>
|
||||
<string name="hoursago">h zpět</string>
|
||||
<string name="nobtadapter">Nenalezen bluetooth adaptér</string>
|
||||
<string name="percent">Procent</string>
|
||||
<string name="reloadprofile">Obnovit profil</string>
|
||||
|
|
|
@ -222,7 +222,6 @@
|
|||
<string name="end_user_license_agreement_i_understand">Ich verstehe und stimme zu</string>
|
||||
<string name="end_user_license_agreement_text">DAS PROGRAMM DARF NICHT FÜR MEDIZINISCHE ENTSCHEIDUNGEN BENUTZT WERDEN. ES GIBT IN DIESEM PROJEKT KEINE GEWÄHRLEISTUNG ODER GARANTIERTE UNTERSTÜTZUNG IN IRGENDEINER ART. WENN DU DICH ENTSCHEIDEST ES ZU NUTZEN, HÄNGT DIE QUALITÄT UND LEISTUNGSFÄHIGKEIT DIESES PROJEKTES VON DIR SELBST AB. ES WIRD \"WIE BESEHEN\" ZUR VERFÜGUNG GESTELLT. SOLLTE SICH DAS PROGRAMM ALS FEHLERHAFT ERWEISEN, ÜBERNEHMEN SIE DIE KOSTEN ALLER NOTWENDIGEN KRANKHEITSKOSTEN, SERVICELEISTUNGEN, REPARATUREN ODER KORREKTUREN.</string>
|
||||
<string name="failedupdatebasalprofile">Fehler beim Aktualisieren der Basalrate</string>
|
||||
<string name="hoursago">"h her "</string>
|
||||
<string name="smscommunicator">SMS-Kommunikator</string>
|
||||
<string name="smscommunicator_allowednumbers">Erlaubte Telefonnummern</string>
|
||||
<string name="waitingforpumpresult">Auf Pumpenergebnis warten</string>
|
||||
|
@ -726,7 +725,7 @@
|
|||
<string name="combo_pump_action_bolusing">Bolus (%.1f IE) wird abgegeben</string>
|
||||
<string name="alert_dialog_storage_permission_text">Bitte starte dein Telefon neu oder starte AndroidAPS in den System-Einstellungen neu. Andernfalls wird AndroidAPS nicht protokolliert (wichtig zum Nachverfolgen und Verifizieren, dass der Algorithmus korrekt funktioniert)</string>
|
||||
<string name="pump_tempbasal_label">TBR</string>
|
||||
<string name="combo_last_bolus">%.1f IE (%s, %s)</string>
|
||||
<string name="combo_last_bolus">%.1f %s (%s)</string>
|
||||
<string name="bolus_frequency_exceeded">Ein gleich großer Bolus wurde in der letzten Minute angefordert. Dies ist nicht zulässig, um ungewollte Doppelboli zu verhindern und vor eventuellen Bugs zu schützen.</string>
|
||||
<string name="combo_activity_reading_pump_history">Historie wird gelesen</string>
|
||||
<string name="combo_activity_setting_basal_profile">Basalratenprofil wird aktualisiert</string>
|
||||
|
@ -736,7 +735,7 @@
|
|||
<string name="combo_error_partial_bolus_delivered">Wegen eines Fehlers wurden nur %.2f IE von den angeforderten %.2f IE abgegeben. Bitte prüfe den abgegebenen Bolus auf der Pumpe.</string>
|
||||
<string name="combo_history">Historie</string>
|
||||
<string name="combo_pump_action_refreshing">Status wird aktualisiert</string>
|
||||
<string name="combo_pump_action_initializing">Die Pumpe wird initialisiert</string>
|
||||
<string name="combo_pump_state_initializing">Die Pumpe wird initialisiert</string>
|
||||
<string name="combo_pump_connected_now">Jetzt</string>
|
||||
<string name="combo_pump_never_connected">Nie</string>
|
||||
<string name="combo_pump_tbr_cancelled_warrning">Der Alarm \"TBR ABBRUCH\" wurde bestätigt</string>
|
||||
|
@ -778,6 +777,6 @@
|
|||
<string name="openapsama_bolussnooze_dia_divisor_summary">Standarwert: 2\nBolus snooze (\"Bolus-Schlummer\") bremst den Loop nach einem Mahleiten-Bolus, damit dieser nicht mit niedrigen TBR reagiert, wenn Du gerade gegessen hast. Beispiel: Der Standardwert 2 bewirkt, dass bei einem 3 Stunden DIA der Bolus snooze während 1.5 Stunden nach dem Bolus linear ausläuft (3 h Dia / 2 = 1.5 h Bolus snooze).</string>
|
||||
<string name="openapsama_min_5m_carbimpact_summary">Standardwert: 3.0\nDies ist eine Einstellung für die Standard-Kohlenhydrat-Absorptionswirkung pro 5 Minuten. Der Standardwert ist 3mg/dl/5min. Dies wirkt sich darauf aus, wie schnell der COB-Wert fällt und wieviel KH-Absorption bei der Berechnung des vorhergesagten BZ angenommen wird, wenn der BZ stärker als erwartet fällt oder nicht so stark wie erwartet steigt.</string>
|
||||
<string name="openapsama_link_to_preferncejson_doc_txt">Achtung! Normalerweise musst Du diese Werte nicht ändern. Bitte KLICKE HIER und LESE den Text. Verändere Werte erst, wenn Du den Inhalt des Textes verstanden hast.</string>
|
||||
<string name="pump_basebasalrate">%.2f IE/h</string>
|
||||
<string name="combo_actvity_reading_basal_profile">Basalratenprofil wird gelesen</string>
|
||||
<string name="pump_basebasalrate">%.2f IE/h</string>
|
||||
</resources>
|
||||
|
|
|
@ -220,7 +220,6 @@
|
|||
<string name="danar_iob_label">IOB αντλίας</string>
|
||||
<string name="danar_dailyunits">"Μονάδες ανά ημέρα "</string>
|
||||
<string name="pump_lastbolus_label">Τελευταίο Bolus:</string>
|
||||
<string name="hoursago">ώρες πριν</string>
|
||||
<string name="danar_invalidinput">Μη έγκυρα δεδομένα</string>
|
||||
<string name="danar_valuenotsetproperly">Η τιμή δεν μπήκε σωστά</string>
|
||||
<string name="reloadprofile">Ξαναφορτώστε το προφίλ</string>
|
||||
|
|
|
@ -214,7 +214,6 @@
|
|||
<string name="danar_iob_label">Bomba IOB</string>
|
||||
<string name="danar_dailyunits">Unidades diarias</string>
|
||||
<string name="pump_lastbolus_label">Último bolo:</string>
|
||||
<string name="hoursago">h antes</string>
|
||||
<string name="danar_invalidinput">Datos invalidos</string>
|
||||
<string name="danar_valuenotsetproperly">Valor no establecido correctamente</string>
|
||||
<string name="reloadprofile">Recargar Perfil</string>
|
||||
|
@ -229,7 +228,7 @@
|
|||
<string name="waitingforpumpresult">Esperando resultado</string>
|
||||
<string name="smscommunicator_allowednumbers">Números de teléfono permitidos</string>
|
||||
<string name="smscommunicator_allowednumbers_summary">XXXXXXXXXX +; + YYYYYYYYYY</string>
|
||||
<string formatted="false" name="smscommunicator_bolusreplywithcode">Para entregar bolo% .2fU responder con código% s</string>
|
||||
<string formatted="false" name="smscommunicator_bolusreplywithcode">Para entregar bolo %.2fU responder con código% s</string>
|
||||
<string name="smscommunicator_bolusfailed">Bolo falló</string>
|
||||
<string formatted="false" name="bolusdelivered">Bolo %.2fU entregado con éxito</string>
|
||||
<string formatted="false" name="bolusdelivering">Entregando %.2fU</string>
|
||||
|
|
|
@ -178,7 +178,6 @@
|
|||
<string name="gettingpumpstatus">Stato Micro</string>
|
||||
<string name="glucose">Glucosio</string>
|
||||
<string name="glucosetype_sensor">Sensore</string>
|
||||
<string name="hoursago">h fa</string>
|
||||
<string name="import_from">Importa impstazioni da</string>
|
||||
<string name="initializing">Inizzializzazione</string>
|
||||
<string name="insulin_shortname">INS</string>
|
||||
|
|
|
@ -225,7 +225,6 @@
|
|||
<string name="danar_iob_label">펌프 IOB</string>
|
||||
<string name="danar_dailyunits">일 인슐린 총량</string>
|
||||
<string name="pump_lastbolus_label">최근 식사주입:</string>
|
||||
<string name="hoursago">시간 전</string>
|
||||
<string name="danar_invalidinput">사용할수 없는 입력 데이터</string>
|
||||
<string name="danar_valuenotsetproperly">값이 제대로 설정되지 않았습니다</string>
|
||||
<string name="reloadprofile">Reload profile</string>
|
||||
|
|
|
@ -419,7 +419,6 @@
|
|||
<string name="overview_bolusprogress_stoppressed">STOP INGEDRUKT</string>
|
||||
<string name="overview_calibration">Kalibratie</string>
|
||||
<string name="danar_stats_olddata_Message">Oude gegevens druk \"VERNIEUW\" a.u.b.</string>
|
||||
<string name="hoursago">u geleden</string>
|
||||
<string name="minago">%d min geleden</string>
|
||||
<string name="reason">Berekening</string>
|
||||
<string name="rate">Dosis</string>
|
||||
|
@ -743,7 +742,7 @@
|
|||
<string name="combo_no_pump_connection">Geen verbinding gedurende %d minuten</string>
|
||||
<string name="combo_tbr_remaining">%d%% (%d min resterend)</string>
|
||||
<string name="combo_last_bolus">%.1f E (%s, %s)</string>
|
||||
<string name="combo_pump_action_initializing">Initialiseren</string>
|
||||
<string name="combo_pump_state_initializing">Initialiseren</string>
|
||||
<string name="combo_pump_state_disconnected">Verbinding verbroken</string>
|
||||
<string name="combo_error_bolus_recovery_progress">Herstel van verbroken verbindng</string>
|
||||
<string name="combo_warning">Waarschuwing</string>
|
||||
|
|
|
@ -221,7 +221,6 @@
|
|||
<string name="glucosetype_finger">палец</string>
|
||||
<string name="glucosetype_sensor">сенсор</string>
|
||||
<string name="high_mark">ВЕРХНЯЯ отметка</string>
|
||||
<string name="hoursago">час. назад</string>
|
||||
<string name="import_from">импортировать настройки из</string>
|
||||
<string name="initializing">инициализация...</string>
|
||||
<string name="insulin_shortname">ИНС</string>
|
||||
|
|
|
@ -206,9 +206,8 @@
|
|||
<string name="glucosetype_sensor">Sensor</string>
|
||||
<string name="high_mark">HÖG markering</string>
|
||||
<string name="hours">timmar</string>
|
||||
<string name="hoursago">h sedan</string>
|
||||
<string name="import_from">Importera inställningar från</string>
|
||||
<string name="initializing">Startar...</string>
|
||||
<string name="initializing">Startar…</string>
|
||||
<string name="invalidprofile">Ogiltig profil !!!</string>
|
||||
<string name="iob">IOB</string>
|
||||
<string name="it_lang">Italienska</string>
|
||||
|
|
|
@ -235,7 +235,7 @@
|
|||
<string name="danar_iob_label">Pump IOB</string>
|
||||
<string name="danar_dailyunits">Daily units</string>
|
||||
<string name="pump_lastbolus_label">Last bolus</string>
|
||||
<string name="hoursago">h ago</string>
|
||||
<string name="hoursago">%.1fh ago</string>
|
||||
<string name="danar_invalidinput">Invalid input data</string>
|
||||
<string name="danar_valuenotsetproperly">Value not set properly</string>
|
||||
<string name="reloadprofile">Reload profile</string>
|
||||
|
@ -820,8 +820,8 @@
|
|||
<string name="combo_pump_activity_label">Activity</string>
|
||||
<string name="combo_no_pump_connection">No connection for %d min</string>
|
||||
<string name="combo_tbr_remaining">%d%% (%d min remaining)</string>
|
||||
<string name="combo_last_bolus">%.1f U (%s, %s)</string>
|
||||
<string name="combo_pump_action_initializing">Initializing</string>
|
||||
<string name="combo_last_bolus">%.1f %s (%s)</string>
|
||||
<string name="combo_pump_state_initializing">Initializing</string>
|
||||
<string name="combo_pump_state_disconnected">Disconnected</string>
|
||||
<string name="combo_pump_state_suspended_due_to_error">Suspended due to error</string>
|
||||
<string name="combo_pump_state_suspended_by_user">Suspended by user</string>
|
||||
|
@ -834,7 +834,7 @@
|
|||
<string name="combo_pump_unsupported_operation">Requested operation not supported by pump</string>
|
||||
<string name="combo_low_suspend_forced_notification">Unsafe usage: extended or multiwave boluses are active. Loop mode has been set to low-suspend only 6 hours. Only normal boluses are supported in loop mode</string>
|
||||
<string name="combo_force_disabled_notification">Unsafe usage: the pump uses a different basal rate profile than the first. The loop has been disabled. Select the first profile on the pump and refresh.</string>
|
||||
<string name="bolus_frequency_exceeded">A bolus with the same amount was requested within the last minute. To prevent accidental double boluses and to guard against bugs this is disallowed.</string>
|
||||
<string name="bolus_frequency_exceeded">A bolus with the same amount was requested within the last two minutes. To prevent accidental double boluses and to guard against bugs this is disallowed.</string>
|
||||
<string name="combo_pump_connected_now">Now</string>
|
||||
<string name="combo_activity_reading_pump_history">Reading pump history</string>
|
||||
<string name="danar_history">pump history</string>
|
||||
|
@ -843,8 +843,8 @@
|
|||
<string name="combo_pump_cartridge_low_warrning">Pump cartridge level is low</string>
|
||||
<string name="combo_pump_battery_low_warrning">Pump battery is low</string>
|
||||
<string name="combo_is_in_error_state">The pump is showing the error E%d: %s</string>
|
||||
<string name="combo_no_alert_data_note">To read the pump\'s error history, long press the ALERTS button\n\nWARNING: this can trigger a bug which causes the pump to reject all connection attempts and requires pressing a button on the pump to recover and should therefore be avoided.</string>
|
||||
<string name="combo_no_tdd_data_note">To read the pump\'s TDD history, long press the TDDS button\n\nWARNING: this can trigger a bug which causes the pump to reject all connection attempts and requires pressing a button on the pump to recover and should therefore be avoided.</string>
|
||||
<string name="combo_no_alert_data_note">To read the pump\'s error history, long press this button</string>
|
||||
<string name="combo_no_tdd_data_note">To read the pump\'s TDD history, long press this button</string>
|
||||
<string name="combo_tdd_minimum">Minimum: %3.1f U</string>
|
||||
<string name="combo_tdd_average">Average: %3.1f U</string>
|
||||
<string name="combo_tdd_maximum">Maximum: %3.1f U</string>
|
||||
|
@ -854,9 +854,11 @@
|
|||
<string name="combo_notification_check_time_date">Pump clock update needed</string>
|
||||
<string name="combo_history">History</string>
|
||||
<string name="combo_warning">Warning</string>
|
||||
<string name="combo_read_full_history_info">Long press this button to force a full read of history and basal profile from the pump. This is generally not needed, since the pump\'s history is read continuously, but can be useful if the pump\'s date and time changed significantly or the pump was replaced.</string>
|
||||
<string name="combo_read_full_history_warning">This will read the full history and state of the pump. Everything in \"My Data\" and the basal rate. Boluses and TBRs will be added to Treatments if they don\'t already exist. This can cause entries to be duplicated because the pump\'s time is imprecise. Using this when normally looping with the pump is highly discouraged and reserved for special circumstances. If you still want to do this, long press this button again.\n\nWARNING: this can trigger a bug which causes the pump to reject all connection attempts and requires pressing a button on the pump to recover and should therefore be avoided.</string>
|
||||
<string name="combo_read_full_history_confirmation">Are you really sure you want to read all pump data and take the consequences of this action?</string>
|
||||
<string name="combo_pump_tbr_cancelled_warrning">TBR CANCELLED warning was confirmed</string>
|
||||
<string name="combo_error_no_connection_no_bolus_delivered">The pump could\'nt be reached. No bolus was given</string>
|
||||
<string name="combo_error_no_bolus_delivered">Bolus delivery failed. It appears no bolus was delivered. To be sure, please check the pump to avoid a double bolus and then bolus again. To guard against bugs, boluses are not automatically retried.</string>
|
||||
<string name="combo_error_partial_bolus_delivered">Only %.2f U of the requested bolus of %.2f U was delivered due to an error. Please check the pump to verify this and take appropriate actions.</string>
|
||||
<string name="combo_error_bolus_verification_failed">Delivering the bolus and verifying the pump\'s history failed, please check the pump and manually create a bolus record using the Careportal tab if a bolus was delivered.</string>
|
||||
|
@ -865,5 +867,12 @@
|
|||
<string name="extendedbolusdeliveryerror">Extended bolus delivery error</string>
|
||||
<string name="pump_basebasalrate">%.2f U/h</string>
|
||||
<string name="combo_actvity_reading_basal_profile">Reading basal profile</string>
|
||||
<string name="combo_bolus_rejected_due_to_pump_history_change">The pump history has changed after the bolus calculation was performed. The bolus was not delivered. Please recalculate if a bolus is still needed. If the same bolus amount is required, please wait a minute since boluses with the same amount are blocked when requested with less than tow minutes between them for safety (regardless of whether they were administered or not).</string>
|
||||
<string name="combo_error_updating_treatment_record">Bolus successfully delivered, but adding the treatment entry failed. This can happen if two small boluses of the same size are administered within the last two minutes. Please check the pump history and treatment entries and use the Careportal to add missing entries. Make sure not to add any entries for the exact same minute and same amount.</string>
|
||||
<string name="combo_high_temp_rejected_due_to_pump_history_changes">Rejecting high temp since calculation didn\'t consider recently changed pump history</string>
|
||||
<string name="combo_activity_checking_pump_state">Refreshing pump state</string>
|
||||
<string name="combo_warning_pump_basal_rate_changed">The basal rate on the pump has changed and will be updated soon</string>
|
||||
<string name="combo_error_failure_reading_changed_basal_rate">Basal rate changed on pump, but reading it failed</string>
|
||||
<string name="combo_activity_checking_for_history_changes">Checking for history changes</string>
|
||||
</resources>
|
||||
|
||||
|
|
1
ruffy-spi/.gitignore
vendored
1
ruffy-spi/.gitignore
vendored
|
@ -1 +0,0 @@
|
|||
/build
|
|
@ -1,32 +0,0 @@
|
|||
apply plugin: 'com.android.library'
|
||||
|
||||
android {
|
||||
compileSdkVersion 23
|
||||
buildToolsVersion "26.0.2"
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 23
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||
compile 'com.android.support:appcompat-v7:23.4.0'
|
||||
testCompile 'junit:junit:4.12'
|
||||
}
|
25
ruffy-spi/proguard-rules.pro
vendored
25
ruffy-spi/proguard-rules.pro
vendored
|
@ -1,25 +0,0 @@
|
|||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in /home/joe/opt/android/sdk/tools/proguard/proguard-android.txt
|
||||
# You can edit the include path and order by changing the proguardFiles
|
||||
# directive in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# Add any project specific keep options here:
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
|
@ -1,3 +0,0 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="de.jotomo.ruffy">
|
||||
</manifest>
|
1
ruffyscripter/.gitignore
vendored
1
ruffyscripter/.gitignore
vendored
|
@ -1 +0,0 @@
|
|||
/build
|
|
@ -1,35 +0,0 @@
|
|||
apply plugin: 'com.android.library'
|
||||
|
||||
android {
|
||||
compileSdkVersion 23
|
||||
buildToolsVersion "26.0.2"
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 23
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile fileTree(include: ['*.jar'], dir: 'libs')
|
||||
compile 'com.android.support:appcompat-v7:23.4.0'
|
||||
testCompile 'junit:junit:4.12'
|
||||
compile project(':ruffy-spi')
|
||||
compile 'org.slf4j:slf4j-api:1.7.12'
|
||||
compile 'com.google.guava:guava:20.0'
|
||||
}
|
25
ruffyscripter/proguard-rules.pro
vendored
25
ruffyscripter/proguard-rules.pro
vendored
|
@ -1,25 +0,0 @@
|
|||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in /home/joe/opt/android/sdk/tools/proguard/proguard-android.txt
|
||||
# You can edit the include path and order by changing the proguardFiles
|
||||
# directive in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# Add any project specific keep options here:
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
|
@ -1,7 +0,0 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
|
||||
package="de.jotomo.ruffyscripter">
|
||||
|
||||
<uses-permission android:name="android.permission.BLUETOOTH" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
|
||||
</manifest>
|
|
@ -1,127 +0,0 @@
|
|||
package de.jotomo.ruffyscripter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import de.jotomo.ruffy.spi.BasalProfile;
|
||||
import de.jotomo.ruffy.spi.BolusProgressReporter;
|
||||
import de.jotomo.ruffy.spi.CommandResult;
|
||||
import de.jotomo.ruffy.spi.RuffyCommands;
|
||||
import de.jotomo.ruffy.spi.history.PumpHistory;
|
||||
import de.jotomo.ruffy.spi.history.PumpHistoryRequest;
|
||||
|
||||
|
||||
public class RuffyCommandsV1Impl implements RuffyCommands {
|
||||
private static RuffyCommandsV1Impl instance;
|
||||
private static RuffyCommands delegate;
|
||||
|
||||
@NonNull
|
||||
public static RuffyCommands getInstance(Context context) {
|
||||
if (instance == null) {
|
||||
instance = new RuffyCommandsV1Impl();
|
||||
delegate = new RuffyScripter(context);
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
private RuffyCommandsV1Impl() {}
|
||||
|
||||
/** Not supported by RuffyScripter */
|
||||
@Override
|
||||
public CommandResult getDateAndTime() {
|
||||
return new CommandResult().success(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult readReservoirLevelAndLastBolus() {
|
||||
return delegate.readReservoirLevelAndLastBolus();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult confirmAlert(int warningCode) {
|
||||
return delegate.confirmAlert(warningCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult deliverBolus(double amount, BolusProgressReporter bolusProgressReporter) {
|
||||
return delegate.deliverBolus(amount, bolusProgressReporter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelBolus() {
|
||||
delegate.cancelBolus();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult setTbr(int percent, int duration) {
|
||||
return delegate.setTbr(percent, duration);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult cancelTbr() {
|
||||
return delegate.cancelTbr();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPumpAvailable() {
|
||||
return delegate.isPumpAvailable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPumpBusy() {
|
||||
return delegate.isPumpBusy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConnected() {
|
||||
return delegate.isConnected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnect() {
|
||||
delegate.disconnect();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult readPumpState() {
|
||||
return delegate.readPumpState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult readHistory(PumpHistoryRequest request) {
|
||||
return delegate.readHistory(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult readBasalProfile() {
|
||||
return delegate.readBasalProfile();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult setBasalProfile(BasalProfile basalProfile) {
|
||||
return delegate.setBasalProfile(basalProfile);
|
||||
}
|
||||
|
||||
/** Not supported by RuffyScripter */
|
||||
@Override
|
||||
public CommandResult setDateAndTime() {
|
||||
return new CommandResult().success(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestPairing() {
|
||||
delegate.requestPairing();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendAuthKey(String key) {
|
||||
delegate.sendAuthKey(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unpair() {
|
||||
delegate.unpair();
|
||||
}
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
package de.jotomo.ruffyscripter.commands;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import de.jotomo.ruffy.spi.CommandResult;
|
||||
import de.jotomo.ruffyscripter.RuffyScripter;
|
||||
|
||||
public abstract class BaseCommand implements Command {
|
||||
// RS will inject itself here
|
||||
protected RuffyScripter scripter;
|
||||
|
||||
protected CommandResult result;
|
||||
|
||||
public BaseCommand() {
|
||||
result = new CommandResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setScripter(RuffyScripter scripter) {
|
||||
this.scripter = scripter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean needsRunMode() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* A warning id (or null) caused by a disconnect we can safely confirm on reconnect,
|
||||
* knowing it's not severe as it was caused by this command.
|
||||
* @see de.jotomo.ruffy.spi.PumpWarningCodes
|
||||
*/
|
||||
@Override
|
||||
public Integer getReconnectWarningId() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> validateArguments() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult getResult() {
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
package de.jotomo.ruffyscripter.commands;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.monkey.d.ruffy.ruffy.driver.display.MenuAttribute;
|
||||
import org.monkey.d.ruffy.ruffy.driver.display.MenuType;
|
||||
import org.monkey.d.ruffy.ruffy.driver.display.menu.BolusType;
|
||||
import org.monkey.d.ruffy.ruffy.driver.display.menu.MenuDate;
|
||||
import org.monkey.d.ruffy.ruffy.driver.display.menu.MenuTime;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import de.jotomo.ruffy.spi.history.Bolus;
|
||||
|
||||
public class ReadReservoirLevelAndLastBolus extends BaseCommand {
|
||||
@Override
|
||||
public void execute() {
|
||||
scripter.verifyRootMenuIsDisplayed();
|
||||
scripter.pressCheckKey();
|
||||
scripter.waitForMenuToBeLeft(MenuType.MAIN_MENU);
|
||||
scripter.waitForMenuToBeLeft(MenuType.STOP);
|
||||
scripter.verifyMenuIsDisplayed(MenuType.QUICK_INFO);
|
||||
result.reservoirLevel = ((Double) scripter.getCurrentMenu().getAttribute(MenuAttribute.REMAINING_INSULIN)).intValue();
|
||||
scripter.pressCheckKey();
|
||||
result.lastBolus = readBolusRecord();
|
||||
scripter.returnToRootMenu();
|
||||
result.success = true;
|
||||
}
|
||||
|
||||
// TODO deduplicate -> ReadHistoryCommand
|
||||
@NonNull
|
||||
private Bolus readBolusRecord() {
|
||||
scripter.verifyMenuIsDisplayed(MenuType.BOLUS_DATA);
|
||||
BolusType bolusType = (BolusType) scripter.getCurrentMenu().getAttribute(MenuAttribute.BOLUS_TYPE);
|
||||
boolean isValid = bolusType == BolusType.NORMAL;
|
||||
Double bolus = (Double) scripter.getCurrentMenu().getAttribute(MenuAttribute.BOLUS);
|
||||
long recordDate = readRecordDate();
|
||||
return new Bolus(recordDate, bolus, isValid);
|
||||
}
|
||||
|
||||
private long readRecordDate() {
|
||||
MenuDate date = (MenuDate) scripter.getCurrentMenu().getAttribute(MenuAttribute.DATE);
|
||||
MenuTime time = (MenuTime) scripter.getCurrentMenu().getAttribute(MenuAttribute.TIME);
|
||||
|
||||
int currentMonth = new Date().getMonth() + 1;
|
||||
int currentYear = new Date().getYear() + 1900;
|
||||
if (currentMonth == 1 && date.getMonth() == 12) {
|
||||
currentYear -= 1;
|
||||
}
|
||||
return new Date(currentYear - 1900, date.getMonth() - 1, date.getDay(), time.getHour(), time.getMinute()).getTime();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean needsRunMode() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ReadReservoirLevelAndLastBolus{}";
|
||||
}
|
||||
}
|
|
@ -1 +1 @@
|
|||
include ':app', ':wear', ':ruffyscripter', ':ruffy-spi'
|
||||
include ':app', ':wear'
|
||||
|
|
Loading…
Reference in a new issue