Skip to content
Snippets Groups Projects
Commit f96db32b authored by Lennart Goedhart's avatar Lennart Goedhart
Browse files

Merge branch 'pazaan/develop-basal-rates' of...

Merge branch 'pazaan/develop-basal-rates' of https://github.com/pazaan/600SeriesAndroidUploader into pazaan/develop-basal-rates

* 'pazaan/develop-basal-rates' of https://github.com/pazaan/600SeriesAndroidUploader:
  don't add path & query
  add Nightscout auto config scanning
  recentBolusWizard seems not to be reliable. Only test if IOB is greater
  add logging remove useless logging
  revert to bugfender 0.7.2. because of 03-30 18:06:04.489 10335-10397/info.nightscout.android W/System.err: org.json.JSONException: No value for batteryLevel 03-30 18:06:04.489 10335-10397/info.nightscout.android W/System.err:     at org.json.JSONObject.get(JSONObject.java:389) 03-30 18:06:04.489 10335-10397/info.nightscout.android W/System.err:     at org.json.JSONObject.getDouble(JSONObject.java:444) 03-30 18:06:04.489 10335-10397/info.nightscout.android W/System.err:     at com.bugfender.sdk.a.a.a.c.b.a(Unknown Source) 03-30 18:06:04.489 10335-10397/info.nightscout.android W/System.err:     at com.bugfender.sdk.a.a.a.c.b.b(Unknown Source) 03-30 18:06:04.489 10335-10397/info.nightscout.android W/System.err:     at com.bugfender.sdk.a.a.a.c.a.a(Unknown Source) 03-30 18:06:04.489 10335-10397/info.nightscout.android W/System.err:     at com.bugfender.sdk.a.d.a.c(Unknown Source) 03-30 18:06:04.490 10335-10397/info.nightscout.android W/System.err:     at com.bugfender.sdk.a.a.k.a.c.d.a(Unknown Source) 03-30 18:06:04.490 10335-10397/info.nightscout.android W/System.err:     at com.bugfender.sdk.a.a.k.a.c.d.call(Unknown Source) 03-30 18:06:04.490 10335-10397/info.nightscout.android W/System.err:     at java.util.concurrent.FutureTask.run(FutureTask.java:237) 03-30 18:06:04.490 10335-10397/info.nightscout.android W/System.err:     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113) 03-30 18:06:04.490 10335-10397/info.nightscout.android W/System.err:     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588) 03-30 18:06:04.490 10335-10397/info.nightscout.android W/System.err:     at java.lang.Thread.run(Thread.java:818)
  close Realm also after getInstance
  update bugfender to 0.7.5
  create a copy of lastPumpStatus
  create a copy of lastPumpStatus
  create a copy of lastPumpStatus
  cleanup
  Move more static stuff into a configuration & data storage
  Move all the public static stuff into a configuration & data storage
  add check on successfull while pushing to NS rename bolusApi to bolusEndpoints to be consistant
  remove old & useless log
parents d45e2934 a29f487c
Branches
Tags
No related merge requests found
Showing
with 981 additions and 107 deletions
/*
* Copyright 2009 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.zxing.integration.android;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Fragment;
import android.content.ActivityNotFoundException;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
/**
* <p>A utility class which helps ease integration with Barcode Scanner via {@link Intent}s. This is a simple
* way to invoke barcode scanning and receive the result, without any need to integrate, modify, or learn the
* project's source code.</p>
*
* <h2>Initiating a barcode scan</h2>
*
* <p>To integrate, create an instance of {@code IntentIntegrator} and call {@link #initiateScan()} and wait
* for the result in your app.</p>
*
* <p>It does require that the Barcode Scanner (or work-alike) application is installed. The
* {@link #initiateScan()} method will prompt the user to download the application, if needed.</p>
*
* <p>There are a few steps to using this integration. First, your {@link Activity} must implement
* the method {@link Activity#onActivityResult(int, int, Intent)} and include a line of code like this:</p>
*
* <pre>{@code
* public void onActivityResult(int requestCode, int resultCode, Intent intent) {
* IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
* if (scanResult != null) {
* // handle scan result
* }
* // else continue with any other code you need in the method
* ...
* }
* }</pre>
*
* <p>This is where you will handle a scan result.</p>
*
* <p>Second, just call this in response to a user action somewhere to begin the scan process:</p>
*
* <pre>{@code
* IntentIntegrator integrator = new IntentIntegrator(yourActivity);
* integrator.initiateScan();
* }</pre>
*
* <p>Note that {@link #initiateScan()} returns an {@link AlertDialog} which is non-null if the
* user was prompted to download the application. This lets the calling app potentially manage the dialog.
* In particular, ideally, the app dismisses the dialog if it's still active in its {@link Activity#onPause()}
* method.</p>
*
* <p>You can use {@link #setTitle(String)} to customize the title of this download prompt dialog (or, use
* {@link #setTitleByID(int)} to set the title by string resource ID.) Likewise, the prompt message, and
* yes/no button labels can be changed.</p>
*
* <p>Finally, you can use {@link #addExtra(String, Object)} to add more parameters to the Intent used
* to invoke the scanner. This can be used to set additional options not directly exposed by this
* simplified API.</p>
*
* <p>By default, this will only allow applications that are known to respond to this intent correctly
* do so. The apps that are allowed to response can be set with {@link #setTargetApplications(List)}.
* For example, set to {@link #TARGET_BARCODE_SCANNER_ONLY} to only target the Barcode Scanner app itself.</p>
*
* <h2>Sharing text via barcode</h2>
*
* <p>To share text, encoded as a QR Code on-screen, similarly, see {@link #shareText(CharSequence)}.</p>
*
* <p>Some code, particularly download integration, was contributed from the Anobiit application.</p>
*
* <h2>Enabling experimental barcode formats</h2>
*
* <p>Some formats are not enabled by default even when scanning with {@link #ALL_CODE_TYPES}, such as
* PDF417. Use {@link #initiateScan(Collection)} with
* a collection containing the names of formats to scan for explicitly, like "PDF_417", to use such
* formats.</p>
*
* @author Sean Owen
* @author Fred Lin
* @author Isaac Potoczny-Jones
* @author Brad Drehmer
* @author gcstang
*/
public class IntentIntegrator {
public static final int REQUEST_CODE = 0x0000c0de; // Only use bottom 16 bits
private static final String TAG = IntentIntegrator.class.getSimpleName();
public static final String DEFAULT_TITLE = "Install Barcode Scanner?";
public static final String DEFAULT_MESSAGE =
"This application requires Barcode Scanner. Would you like to install it?";
public static final String DEFAULT_YES = "Yes";
public static final String DEFAULT_NO = "No";
private static final String BS_PACKAGE = "com.google.zxing.client.android";
private static final String BSPLUS_PACKAGE = "com.srowen.bs.android";
// supported barcode formats
public static final Collection<String> PRODUCT_CODE_TYPES = list("UPC_A", "UPC_E", "EAN_8", "EAN_13", "RSS_14");
public static final Collection<String> ONE_D_CODE_TYPES =
list("UPC_A", "UPC_E", "EAN_8", "EAN_13", "CODE_39", "CODE_93", "CODE_128",
"ITF", "RSS_14", "RSS_EXPANDED");
public static final Collection<String> QR_CODE_TYPES = Collections.singleton("QR_CODE");
public static final Collection<String> DATA_MATRIX_TYPES = Collections.singleton("DATA_MATRIX");
public static final Collection<String> ALL_CODE_TYPES = null;
public static final List<String> TARGET_BARCODE_SCANNER_ONLY = Collections.singletonList(BS_PACKAGE);
public static final List<String> TARGET_ALL_KNOWN = list(
BSPLUS_PACKAGE, // Barcode Scanner+
BSPLUS_PACKAGE + ".simple", // Barcode Scanner+ Simple
BS_PACKAGE // Barcode Scanner
// What else supports this intent?
);
private final Activity activity;
private final Fragment fragment;
private String title;
private String message;
private String buttonYes;
private String buttonNo;
private List<String> targetApplications;
private final Map<String,Object> moreExtras = new HashMap<String,Object>(3);
/**
* @param activity {@link Activity} invoking the integration
*/
public IntentIntegrator(Activity activity) {
this.activity = activity;
this.fragment = null;
initializeConfiguration();
}
/**
* @param fragment {@link Fragment} invoking the integration.
* {@link #startActivityForResult(Intent, int)} will be called on the {@link Fragment} instead
* of an {@link Activity}
*/
public IntentIntegrator(Fragment fragment) {
this.activity = fragment.getActivity();
this.fragment = fragment;
initializeConfiguration();
}
private void initializeConfiguration() {
title = DEFAULT_TITLE;
message = DEFAULT_MESSAGE;
buttonYes = DEFAULT_YES;
buttonNo = DEFAULT_NO;
targetApplications = TARGET_ALL_KNOWN;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public void setTitleByID(int titleID) {
title = activity.getString(titleID);
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public void setMessageByID(int messageID) {
message = activity.getString(messageID);
}
public String getButtonYes() {
return buttonYes;
}
public void setButtonYes(String buttonYes) {
this.buttonYes = buttonYes;
}
public void setButtonYesByID(int buttonYesID) {
buttonYes = activity.getString(buttonYesID);
}
public String getButtonNo() {
return buttonNo;
}
public void setButtonNo(String buttonNo) {
this.buttonNo = buttonNo;
}
public void setButtonNoByID(int buttonNoID) {
buttonNo = activity.getString(buttonNoID);
}
public Collection<String> getTargetApplications() {
return targetApplications;
}
public final void setTargetApplications(List<String> targetApplications) {
if (targetApplications.isEmpty()) {
throw new IllegalArgumentException("No target applications");
}
this.targetApplications = targetApplications;
}
public void setSingleTargetApplication(String targetApplication) {
this.targetApplications = Collections.singletonList(targetApplication);
}
public Map<String,?> getMoreExtras() {
return moreExtras;
}
public final void addExtra(String key, Object value) {
moreExtras.put(key, value);
}
/**
* Initiates a scan for all known barcode types with the default camera.
*
* @return the {@link AlertDialog} that was shown to the user prompting them to download the app
* if a prompt was needed, or null otherwise.
*/
public final AlertDialog initiateScan() {
return initiateScan(ALL_CODE_TYPES, -1);
}
/**
* Initiates a scan for all known barcode types with the specified camera.
*
* @param cameraId camera ID of the camera to use. A negative value means "no preference".
* @return the {@link AlertDialog} that was shown to the user prompting them to download the app
* if a prompt was needed, or null otherwise.
*/
public final AlertDialog initiateScan(int cameraId) {
return initiateScan(ALL_CODE_TYPES, cameraId);
}
/**
* Initiates a scan, using the default camera, only for a certain set of barcode types, given as strings corresponding
* to their names in ZXing's {@code BarcodeFormat} class like "UPC_A". You can supply constants
* like {@link #PRODUCT_CODE_TYPES} for example.
*
* @param desiredBarcodeFormats names of {@code BarcodeFormat}s to scan for
* @return the {@link AlertDialog} that was shown to the user prompting them to download the app
* if a prompt was needed, or null otherwise.
*/
public final AlertDialog initiateScan(Collection<String> desiredBarcodeFormats) {
return initiateScan(desiredBarcodeFormats, -1);
}
/**
* Initiates a scan, using the specified camera, only for a certain set of barcode types, given as strings corresponding
* to their names in ZXing's {@code BarcodeFormat} class like "UPC_A". You can supply constants
* like {@link #PRODUCT_CODE_TYPES} for example.
*
* @param desiredBarcodeFormats names of {@code BarcodeFormat}s to scan for
* @param cameraId camera ID of the camera to use. A negative value means "no preference".
* @return the {@link AlertDialog} that was shown to the user prompting them to download the app
* if a prompt was needed, or null otherwise
*/
public final AlertDialog initiateScan(Collection<String> desiredBarcodeFormats, int cameraId) {
Intent intentScan = new Intent(BS_PACKAGE + ".SCAN");
intentScan.addCategory(Intent.CATEGORY_DEFAULT);
// check which types of codes to scan for
if (desiredBarcodeFormats != null) {
// set the desired barcode types
StringBuilder joinedByComma = new StringBuilder();
for (String format : desiredBarcodeFormats) {
if (joinedByComma.length() > 0) {
joinedByComma.append(',');
}
joinedByComma.append(format);
}
intentScan.putExtra("SCAN_FORMATS", joinedByComma.toString());
}
// check requested camera ID
if (cameraId >= 0) {
intentScan.putExtra("SCAN_CAMERA_ID", cameraId);
}
String targetAppPackage = findTargetAppPackage(intentScan);
if (targetAppPackage == null) {
return showDownloadDialog();
}
intentScan.setPackage(targetAppPackage);
intentScan.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intentScan.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
attachMoreExtras(intentScan);
startActivityForResult(intentScan, REQUEST_CODE);
return null;
}
/**
* Start an activity. This method is defined to allow different methods of activity starting for
* newer versions of Android and for compatibility library.
*
* @param intent Intent to start.
* @param code Request code for the activity
* @see Activity#startActivityForResult(Intent, int)
* @see Fragment#startActivityForResult(Intent, int)
*/
protected void startActivityForResult(Intent intent, int code) {
if (fragment == null) {
activity.startActivityForResult(intent, code);
} else {
fragment.startActivityForResult(intent, code);
}
}
private String findTargetAppPackage(Intent intent) {
PackageManager pm = activity.getPackageManager();
List<ResolveInfo> availableApps = pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
if (availableApps != null) {
for (String targetApp : targetApplications) {
if (contains(availableApps, targetApp)) {
return targetApp;
}
}
}
return null;
}
private static boolean contains(Iterable<ResolveInfo> availableApps, String targetApp) {
for (ResolveInfo availableApp : availableApps) {
String packageName = availableApp.activityInfo.packageName;
if (targetApp.equals(packageName)) {
return true;
}
}
return false;
}
private AlertDialog showDownloadDialog() {
AlertDialog.Builder downloadDialog = new AlertDialog.Builder(activity);
downloadDialog.setTitle(title);
downloadDialog.setMessage(message);
downloadDialog.setPositiveButton(buttonYes, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
String packageName;
if (targetApplications.contains(BS_PACKAGE)) {
// Prefer to suggest download of BS if it's anywhere in the list
packageName = BS_PACKAGE;
} else {
// Otherwise, first option:
packageName = targetApplications.get(0);
}
Uri uri = Uri.parse("market://details?id=" + packageName);
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
try {
if (fragment == null) {
activity.startActivity(intent);
} else {
fragment.startActivity(intent);
}
} catch (ActivityNotFoundException anfe) {
// Hmm, market is not installed
Log.w(TAG, "Google Play is not installed; cannot install " + packageName);
}
}
});
downloadDialog.setNegativeButton(buttonNo, null);
downloadDialog.setCancelable(true);
return downloadDialog.show();
}
/**
* <p>Call this from your {@link Activity}'s
* {@link Activity#onActivityResult(int, int, Intent)} method.</p>
*
* @param requestCode request code from {@code onActivityResult()}
* @param resultCode result code from {@code onActivityResult()}
* @param intent {@link Intent} from {@code onActivityResult()}
* @return null if the event handled here was not related to this class, or
* else an {@link IntentResult} containing the result of the scan. If the user cancelled scanning,
* the fields will be null.
*/
public static IntentResult parseActivityResult(int requestCode, int resultCode, Intent intent) {
if (requestCode == REQUEST_CODE) {
if (resultCode == Activity.RESULT_OK) {
String contents = intent.getStringExtra("SCAN_RESULT");
String formatName = intent.getStringExtra("SCAN_RESULT_FORMAT");
byte[] rawBytes = intent.getByteArrayExtra("SCAN_RESULT_BYTES");
int intentOrientation = intent.getIntExtra("SCAN_RESULT_ORIENTATION", Integer.MIN_VALUE);
Integer orientation = intentOrientation == Integer.MIN_VALUE ? null : intentOrientation;
String errorCorrectionLevel = intent.getStringExtra("SCAN_RESULT_ERROR_CORRECTION_LEVEL");
return new IntentResult(contents,
formatName,
rawBytes,
orientation,
errorCorrectionLevel);
}
return new IntentResult();
}
return null;
}
/**
* Defaults to type "TEXT_TYPE".
*
* @param text the text string to encode as a barcode
* @return the {@link AlertDialog} that was shown to the user prompting them to download the app
* if a prompt was needed, or null otherwise
* @see #shareText(CharSequence, CharSequence)
*/
public final AlertDialog shareText(CharSequence text) {
return shareText(text, "TEXT_TYPE");
}
/**
* Shares the given text by encoding it as a barcode, such that another user can
* scan the text off the screen of the device.
*
* @param text the text string to encode as a barcode
* @param type type of data to encode. See {@code com.google.zxing.client.android.Contents.Type} constants.
* @return the {@link AlertDialog} that was shown to the user prompting them to download the app
* if a prompt was needed, or null otherwise
*/
public final AlertDialog shareText(CharSequence text, CharSequence type) {
Intent intent = new Intent();
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.setAction(BS_PACKAGE + ".ENCODE");
intent.putExtra("ENCODE_TYPE", type);
intent.putExtra("ENCODE_DATA", text);
String targetAppPackage = findTargetAppPackage(intent);
if (targetAppPackage == null) {
return showDownloadDialog();
}
intent.setPackage(targetAppPackage);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
attachMoreExtras(intent);
if (fragment == null) {
activity.startActivity(intent);
} else {
fragment.startActivity(intent);
}
return null;
}
private static List<String> list(String... values) {
return Collections.unmodifiableList(Arrays.asList(values));
}
private void attachMoreExtras(Intent intent) {
for (Map.Entry<String,Object> entry : moreExtras.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
// Kind of hacky
if (value instanceof Integer) {
intent.putExtra(key, (Integer) value);
} else if (value instanceof Long) {
intent.putExtra(key, (Long) value);
} else if (value instanceof Boolean) {
intent.putExtra(key, (Boolean) value);
} else if (value instanceof Double) {
intent.putExtra(key, (Double) value);
} else if (value instanceof Float) {
intent.putExtra(key, (Float) value);
} else if (value instanceof Bundle) {
intent.putExtra(key, (Bundle) value);
} else {
intent.putExtra(key, value.toString());
}
}
}
}
/*
* Copyright 2009 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.zxing.integration.android;
/**
* <p>Encapsulates the result of a barcode scan invoked through {@link IntentIntegrator}.</p>
*
* @author Sean Owen
*/
public final class IntentResult {
private final String contents;
private final String formatName;
private final byte[] rawBytes;
private final Integer orientation;
private final String errorCorrectionLevel;
IntentResult() {
this(null, null, null, null, null);
}
IntentResult(String contents,
String formatName,
byte[] rawBytes,
Integer orientation,
String errorCorrectionLevel) {
this.contents = contents;
this.formatName = formatName;
this.rawBytes = rawBytes;
this.orientation = orientation;
this.errorCorrectionLevel = errorCorrectionLevel;
}
/**
* @return raw content of barcode
*/
public String getContents() {
return contents;
}
/**
* @return name of format, like "QR_CODE", "UPC_A". See {@code BarcodeFormat} for more format names.
*/
public String getFormatName() {
return formatName;
}
/**
* @return raw bytes of the barcode content, if applicable, or null otherwise
*/
public byte[] getRawBytes() {
return rawBytes;
}
/**
* @return rotation of the image, in degrees, which resulted in a successful scan. May be null.
*/
public Integer getOrientation() {
return orientation;
}
/**
* @return name of the error correction level used in the barcode, if applicable
*/
public String getErrorCorrectionLevel() {
return errorCorrectionLevel;
}
@Override
public String toString() {
int rawBytesLength = rawBytes == null ? 0 : rawBytes.length;
return "Format: " + formatName + '\n' +
"Contents: " + contents + '\n' +
"Raw bytes: (" + rawBytesLength + " bytes)\n" +
"Orientation: " + orientation + '\n' +
"EC level: " + errorCorrectionLevel + '\n';
}
}
...@@ -75,6 +75,8 @@ import info.nightscout.android.model.medtronicNg.PumpInfo; ...@@ -75,6 +75,8 @@ import info.nightscout.android.model.medtronicNg.PumpInfo;
import info.nightscout.android.model.medtronicNg.PumpStatusEvent; import info.nightscout.android.model.medtronicNg.PumpStatusEvent;
import info.nightscout.android.settings.SettingsActivity; import info.nightscout.android.settings.SettingsActivity;
import info.nightscout.android.upload.nightscout.NightscoutUploadIntentService; import info.nightscout.android.upload.nightscout.NightscoutUploadIntentService;
import info.nightscout.android.utils.ConfigurationStore;
import info.nightscout.android.utils.DataStore;
import io.realm.Realm; import io.realm.Realm;
import io.realm.RealmChangeListener; import io.realm.RealmChangeListener;
import io.realm.RealmResults; import io.realm.RealmResults;
...@@ -85,25 +87,15 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc ...@@ -85,25 +87,15 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
private static final String TAG = MainActivity.class.getSimpleName(); private static final String TAG = MainActivity.class.getSimpleName();
public static final float MMOLXLFACTOR = 18.016f; public static final float MMOLXLFACTOR = 18.016f;
public static int batLevel = 0; private DataStore dataStore = DataStore.getInstance();
public static boolean reducePollOnPumpAway = false; private ConfigurationStore configurationStore = ConfigurationStore.getInstance();
public static long pollInterval = MedtronicCnlIntentService.POLL_PERIOD_MS;
public static long lowBatteryPollInterval = MedtronicCnlIntentService.LOW_BATTERY_POLL_PERIOD_MS;
private static long activePumpMac;
private int chartZoom = 3; private int chartZoom = 3;
private boolean hasZoomedChart = false; private boolean hasZoomedChart = false;
private NumberFormat sgvFormatter; private NumberFormat sgvFormatter;
private static boolean mmolxl;
private static boolean mmolxlDecimals;
public static long timeLastGoodSGV = 0;
public static short pumpBattery = 0;
public static int countUnavailableSGV = 0;
boolean mEnableCgmService = true; private boolean mEnableCgmService = true;
SharedPreferences prefs = null; private SharedPreferences prefs = null;
private PumpInfo mActivePump; private PumpInfo mActivePump;
private TextView mTextViewLog; // This will eventually move to a status page. private TextView mTextViewLog; // This will eventually move to a status page.
private GraphView mChart; private GraphView mChart;
...@@ -122,22 +114,23 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc ...@@ -122,22 +114,23 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
*/ */
public static long getNextPoll(PumpStatusEvent pumpStatusData) { public static long getNextPoll(PumpStatusEvent pumpStatusData) {
long nextPoll = pumpStatusData.getEventDate().getTime() + pumpStatusData.getPumpTimeOffset(), long nextPoll = pumpStatusData.getEventDate().getTime() + pumpStatusData.getPumpTimeOffset(),
now = System.currentTimeMillis(); now = System.currentTimeMillis(),
pollInterval = ConfigurationStore.getInstance().getPollInterval();
// align to next poll slot // align to next poll slot
if (nextPoll + 2 * 60 * 60 * 1000 < now) { // last event more than 2h old -> could be a calibration if (nextPoll + 2 * 60 * 60 * 1000 < now) { // last event more than 2h old -> could be a calibration
nextPoll = System.currentTimeMillis() + 1000; nextPoll = System.currentTimeMillis() + 1000;
} else { } else {
// align to poll interval // align to poll interval
nextPoll += (((now - nextPoll) / MainActivity.pollInterval)) * MainActivity.pollInterval nextPoll += (((now - nextPoll) / pollInterval)) * pollInterval
+ MedtronicCnlIntentService.POLL_GRACE_PERIOD_MS; + MedtronicCnlIntentService.POLL_GRACE_PERIOD_MS;
if (pumpStatusData.getBatteryPercentage() > 25) { if (pumpStatusData.getBatteryPercentage() > 25) {
// poll every 5 min // poll every 5 min
nextPoll += MainActivity.pollInterval; nextPoll += pollInterval;
} else { } else {
// if pump battery seems to be empty reduce polling to save battery (every 15 min) // if pump battery seems to be empty reduce polling to save battery (every 15 min)
//TODO add message & document it //TODO add message & document it
nextPoll += MainActivity.lowBatteryPollInterval; nextPoll += ConfigurationStore.getInstance().getLowBatteryPollInterval();
} }
} }
...@@ -145,9 +138,10 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc ...@@ -145,9 +138,10 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
} }
public static String strFormatSGV(float sgvValue) { public static String strFormatSGV(float sgvValue) {
if (mmolxl) { ConfigurationStore configurationStore = ConfigurationStore.getInstance();
if (configurationStore.isMmolxl()) {
NumberFormat sgvFormatter; NumberFormat sgvFormatter;
if (mmolxlDecimals) { if (configurationStore.isMmolxlDecimals()) {
sgvFormatter = new DecimalFormat("0.00"); sgvFormatter = new DecimalFormat("0.00");
} else { } else {
sgvFormatter = new DecimalFormat("0.0"); sgvFormatter = new DecimalFormat("0.0");
...@@ -164,6 +158,12 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc ...@@ -164,6 +158,12 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
mRealm = Realm.getDefaultInstance(); mRealm = Realm.getDefaultInstance();
RealmResults<PumpStatusEvent> data = mRealm.where(PumpStatusEvent.class)
.findAllSorted("eventDate", Sort.DESCENDING);
if (data.size() > 0)
dataStore.setLastPumpStatus(data.first());
mNightscoutUploadService = new Intent(this, NightscoutUploadIntentService.class); mNightscoutUploadService = new Intent(this, NightscoutUploadIntentService.class);
setContentView(R.layout.activity_main); setContentView(R.layout.activity_main);
...@@ -176,15 +176,16 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc ...@@ -176,15 +176,16 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
} }
// setup preferences // setup preferences
MainActivity.pollInterval = Long.parseLong(prefs.getString("pollInterval", Long.toString(MedtronicCnlIntentService.POLL_PERIOD_MS))); configurationStore.setPollInterval(Long.parseLong(prefs.getString("pollInterval", Long.toString(MedtronicCnlIntentService.POLL_PERIOD_MS))));
MainActivity.lowBatteryPollInterval = Long.parseLong(prefs.getString("lowBatPollInterval", Long.toString(MedtronicCnlIntentService.LOW_BATTERY_POLL_PERIOD_MS))); configurationStore.setLowBatteryPollInterval(Long.parseLong(prefs.getString("lowBatPollInterval", Long.toString(MedtronicCnlIntentService.LOW_BATTERY_POLL_PERIOD_MS))));
MainActivity.reducePollOnPumpAway = prefs.getBoolean("doublePollOnPumpAway", false); configurationStore.setReducePollOnPumpAway(prefs.getBoolean("doublePollOnPumpAway", false));
chartZoom = Integer.parseInt(prefs.getString("chartZoom", "3")); chartZoom = Integer.parseInt(prefs.getString("chartZoom", "3"));
mmolxl = prefs.getBoolean("mmolxl", false); configurationStore.setMmolxl(prefs.getBoolean("mmolxl", false));
mmolxlDecimals = prefs.getBoolean("mmolDecimals", false); configurationStore.setMmolxlDecimals(prefs.getBoolean("mmolDecimals", false));
if (mmolxl) { if (configurationStore.isMmolxl()) {
if (mmolxlDecimals) if (configurationStore.isMmolxlDecimals())
sgvFormatter = new DecimalFormat("0.00"); sgvFormatter = new DecimalFormat("0.00");
else else
sgvFormatter = new DecimalFormat("0.0"); sgvFormatter = new DecimalFormat("0.0");
...@@ -534,10 +535,10 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc ...@@ -534,10 +535,10 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
startCgmService(); startCgmService();
} }
} else if (key.equals("mmolxl") || key.equals("mmolDecimals")) { } else if (key.equals("mmolxl") || key.equals("mmolDecimals")) {
mmolxl = sharedPreferences.getBoolean("mmolxl", false); configurationStore.setMmolxl(sharedPreferences.getBoolean("mmolxl", false));
mmolxlDecimals = sharedPreferences.getBoolean("mmolDecimals", false); configurationStore.setMmolxlDecimals(sharedPreferences.getBoolean("mmolDecimals", false));
if (mmolxl) { if (configurationStore.isMmolxl()) {
if (mmolxlDecimals) if (configurationStore.isMmolxlDecimals())
sgvFormatter = new DecimalFormat("0.00"); sgvFormatter = new DecimalFormat("0.00");
else else
sgvFormatter = new DecimalFormat("0.0"); sgvFormatter = new DecimalFormat("0.0");
...@@ -546,13 +547,13 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc ...@@ -546,13 +547,13 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
} }
refreshDisplay(); refreshDisplay();
} else if (key.equals("pollInterval")) { } else if (key.equals("pollInterval")) {
MainActivity.pollInterval = Long.parseLong(sharedPreferences.getString("pollInterval", configurationStore.setPollInterval(Long.parseLong(sharedPreferences.getString("pollInterval",
Long.toString(MedtronicCnlIntentService.POLL_PERIOD_MS))); Long.toString(MedtronicCnlIntentService.POLL_PERIOD_MS))));
} else if (key.equals("lowBatPollInterval")) { } else if (key.equals("lowBatPollInterval")) {
MainActivity.lowBatteryPollInterval = Long.parseLong(sharedPreferences.getString("lowBatPollInterval", configurationStore.setLowBatteryPollInterval(Long.parseLong(sharedPreferences.getString("lowBatPollInterval",
Long.toString(MedtronicCnlIntentService.LOW_BATTERY_POLL_PERIOD_MS))); Long.toString(MedtronicCnlIntentService.LOW_BATTERY_POLL_PERIOD_MS))));
} else if (key.equals("doublePollOnPumpAway")) { } else if (key.equals("doublePollOnPumpAway")) {
MainActivity.reducePollOnPumpAway = sharedPreferences.getBoolean("doublePollOnPumpAway", false); configurationStore.setReducePollOnPumpAway(sharedPreferences.getBoolean("doublePollOnPumpAway", false));
} else if (key.equals("chartZoom")) { } else if (key.equals("chartZoom")) {
chartZoom = Integer.parseInt(sharedPreferences.getString("chartZoom", "3")); chartZoom = Integer.parseInt(sharedPreferences.getString("chartZoom", "3"));
hasZoomedChart = false; hasZoomedChart = false;
...@@ -601,11 +602,8 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc ...@@ -601,11 +602,8 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
} }
} }
public static void setActivePumpMac(long pumpMac) {
activePumpMac = pumpMac;
}
private PumpInfo getActivePump() { private PumpInfo getActivePump() {
long activePumpMac = dataStore.getActivePumpMac();
if (activePumpMac != 0L && (mActivePump == null || !mActivePump.isValid() || mActivePump.getPumpMac() != activePumpMac)) { if (activePumpMac != 0L && (mActivePump == null || !mActivePump.isValid() || mActivePump.getPumpMac() != activePumpMac)) {
if (mActivePump != null) { if (mActivePump != null) {
// remove listener on old pump // remove listener on old pump
...@@ -615,7 +613,7 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc ...@@ -615,7 +613,7 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
PumpInfo pump = mRealm PumpInfo pump = mRealm
.where(PumpInfo.class) .where(PumpInfo.class)
.equalTo("pumpMac", MainActivity.activePumpMac) .equalTo("pumpMac", activePumpMac)
.findFirst(); .findFirst();
if (pump != null && pump.isValid()) { if (pump != null && pump.isValid()) {
...@@ -736,7 +734,7 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc ...@@ -736,7 +734,7 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
TextView textViewBg = (TextView) findViewById(R.id.textview_bg); TextView textViewBg = (TextView) findViewById(R.id.textview_bg);
TextView textViewBgTime = (TextView) findViewById(R.id.textview_bg_time); TextView textViewBgTime = (TextView) findViewById(R.id.textview_bg_time);
TextView textViewUnits = (TextView) findViewById(R.id.textview_units); TextView textViewUnits = (TextView) findViewById(R.id.textview_units);
if (mmolxl) { if (configurationStore.isMmolxl()) {
textViewUnits.setText(R.string.text_unit_mmolxl); textViewUnits.setText(R.string.text_unit_mmolxl);
} else { } else {
textViewUnits.setText(R.string.text_unit_mgxdl); textViewUnits.setText(R.string.text_unit_mgxdl);
...@@ -747,23 +745,20 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc ...@@ -747,23 +745,20 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
// Get the most recently written CGM record for the active pump. // Get the most recently written CGM record for the active pump.
PumpStatusEvent pumpStatusData = null; PumpStatusEvent pumpStatusData = null;
PumpInfo pump = getActivePump(); // ignoring activePump atm
//PumpInfo pump = getActivePump();
if (pump != null && pump.isValid() && pump.getPumpHistory().size() > 0) { if (dataStore.getLastPumpStatus().getEventDate().getTime() > 0) {
Log.d(TAG, "history display refresh size: " + pump.getPumpHistory().size()); pumpStatusData = dataStore.getLastPumpStatus();
Log.d(TAG, "history display refresh date: " + pump.getPumpHistory().last().getEventDate());
pumpStatusData = pump.getPumpHistory().last();
} }
// FIXME - grab the last item from the activePump's getPumpHistory
updateChart(mRealm.where(PumpStatusEvent.class) updateChart(mRealm.where(PumpStatusEvent.class)
.greaterThan("eventDate", new Date(System.currentTimeMillis() - 1000*60*60*24)) .greaterThan("eventDate", new Date(System.currentTimeMillis() - 1000*60*60*24))
.findAllSorted("eventDate", Sort.ASCENDING)); .findAllSorted("eventDate", Sort.ASCENDING));
if (pumpStatusData != null) { if (pumpStatusData != null) {
String sgvString; String sgvString;
if (mmolxl) { if (configurationStore.isMmolxl()) {
float fBgValue = (float) pumpStatusData.getSgv(); float fBgValue = (float) pumpStatusData.getSgv();
sgvString = sgvFormatter.format(fBgValue / MMOLXLFACTOR); sgvString = sgvFormatter.format(fBgValue / MMOLXLFACTOR);
Log.d(TAG, sgvString + " mmol/L"); Log.d(TAG, sgvString + " mmol/L");
...@@ -826,7 +821,7 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc ...@@ -826,7 +821,7 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
mChart.getViewport().setMinX(left); mChart.getViewport().setMinX(left);
mChart.getViewport().setYAxisBoundsManual(true); mChart.getViewport().setYAxisBoundsManual(true);
if (mmolxl) { if (configurationStore.isMmolxl()) {
mChart.getViewport().setMinY(80 / MMOLXLFACTOR); mChart.getViewport().setMinY(80 / MMOLXLFACTOR);
mChart.getViewport().setMaxY(120 / MMOLXLFACTOR); mChart.getViewport().setMaxY(120 / MMOLXLFACTOR);
} else { } else {
...@@ -845,7 +840,7 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc ...@@ -845,7 +840,7 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
// turn your data into Entry objects // turn your data into Entry objects
int sgv = pumpStatus.getSgv(); int sgv = pumpStatus.getSgv();
if (mmolxl) { if (configurationStore.isMmolxl()) {
entries[pos++] = new DataPoint(pumpStatus.getEventDate(), (float) pumpStatus.getSgv() / MMOLXLFACTOR); entries[pos++] = new DataPoint(pumpStatus.getEventDate(), (float) pumpStatus.getSgv() / MMOLXLFACTOR);
} else { } else {
entries[pos++] = new DataPoint(pumpStatus.getEventDate(), (float) pumpStatus.getSgv()); entries[pos++] = new DataPoint(pumpStatus.getEventDate(), (float) pumpStatus.getSgv());
...@@ -883,6 +878,7 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc ...@@ -883,6 +878,7 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
@Override @Override
public void draw(Canvas canvas, Paint paint, float x, float y, DataPointInterface dataPoint) { public void draw(Canvas canvas, Paint paint, float x, float y, DataPointInterface dataPoint) {
double sgv = dataPoint.getY(); double sgv = dataPoint.getY();
boolean mmolxl = configurationStore.isMmolxl();
if (sgv < (mmolxl?4.5:80)) if (sgv < (mmolxl?4.5:80))
paint.setColor(Color.RED); paint.setColor(Color.RED);
else if (sgv <= (mmolxl?10:180)) else if (sgv <= (mmolxl?10:180))
...@@ -972,7 +968,7 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc ...@@ -972,7 +968,7 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
if (arg1.getAction().equalsIgnoreCase(Intent.ACTION_BATTERY_LOW) if (arg1.getAction().equalsIgnoreCase(Intent.ACTION_BATTERY_LOW)
|| arg1.getAction().equalsIgnoreCase(Intent.ACTION_BATTERY_CHANGED) || arg1.getAction().equalsIgnoreCase(Intent.ACTION_BATTERY_CHANGED)
|| arg1.getAction().equalsIgnoreCase(Intent.ACTION_BATTERY_OKAY)) { || arg1.getAction().equalsIgnoreCase(Intent.ACTION_BATTERY_OKAY)) {
batLevel = arg1.getIntExtra(BatteryManager.EXTRA_LEVEL, 0); dataStore.setUplooaderBatteryLevel(arg1.getIntExtra(BatteryManager.EXTRA_LEVEL, 0));
} }
} }
} }
......
...@@ -175,7 +175,8 @@ public class MedtronicCnlReader { ...@@ -175,7 +175,8 @@ public class MedtronicCnlReader {
// CNL<-->PUMP comms can have occasional short lived noise causing errors, retrying once catches this // CNL<-->PUMP comms can have occasional short lived noise causing errors, retrying once catches this
try { try {
PumpTimeResponseMessage response = new PumpTimeRequestMessage(mPumpSession).send(mDevice); PumpTimeResponseMessage response = new PumpTimeRequestMessage(mPumpSession).send(mDevice);
Log.d(TAG, "Finished getPumpTime with date " + response.getPumpTime()); // ignore the first error. Just log retry
// Log.d(TAG, "Finished getPumpTime with date " + response.getPumpTime());
return response.getPumpTime(); return response.getPumpTime();
} catch (UnexpectedMessageException e) { } catch (UnexpectedMessageException e) {
Log.e(TAG, "Unexpected Message", e); Log.e(TAG, "Unexpected Message", e);
...@@ -196,7 +197,7 @@ public class MedtronicCnlReader { ...@@ -196,7 +197,7 @@ public class MedtronicCnlReader {
try { try {
PumpStatusResponseMessage response = new PumpStatusRequestMessage(mPumpSession).send(mDevice); PumpStatusResponseMessage response = new PumpStatusRequestMessage(mPumpSession).send(mDevice);
response.updatePumpRecord(pumpRecord); response.updatePumpRecord(pumpRecord);
Log.d(TAG, "Finished updatePumpStatus"); Log.d(TAG, "Finished updatePumpStatus: " + pumpRecord.toString());
return pumpRecord; return pumpRecord;
} catch (UnexpectedMessageException e) { } catch (UnexpectedMessageException e) {
Log.e(TAG, "Unexpected Message", e); Log.e(TAG, "Unexpected Message", e);
...@@ -207,7 +208,7 @@ public class MedtronicCnlReader { ...@@ -207,7 +208,7 @@ public class MedtronicCnlReader {
PumpStatusResponseMessage response = new PumpStatusRequestMessage(mPumpSession).send(mDevice); PumpStatusResponseMessage response = new PumpStatusRequestMessage(mPumpSession).send(mDevice);
response.updatePumpRecord(pumpRecord); response.updatePumpRecord(pumpRecord);
Log.d(TAG, "Finished updatePumpStatus"); Log.d(TAG, "Finished updatePumpStatus: " + pumpRecord.toString());
return pumpRecord; return pumpRecord;
} }
......
...@@ -14,6 +14,7 @@ import info.nightscout.android.medtronic.exception.ChecksumException; ...@@ -14,6 +14,7 @@ import info.nightscout.android.medtronic.exception.ChecksumException;
import info.nightscout.android.medtronic.exception.EncryptionException; import info.nightscout.android.medtronic.exception.EncryptionException;
import info.nightscout.android.medtronic.exception.UnexpectedMessageException; import info.nightscout.android.medtronic.exception.UnexpectedMessageException;
import info.nightscout.android.model.medtronicNg.PumpStatusEvent; import info.nightscout.android.model.medtronicNg.PumpStatusEvent;
import info.nightscout.android.utils.DataStore;
import info.nightscout.android.utils.HexDump; import info.nightscout.android.utils.HexDump;
/** /**
...@@ -197,6 +198,10 @@ public class PumpStatusResponseMessage extends MedtronicSendMessageResponseMessa ...@@ -197,6 +198,10 @@ public class PumpStatusResponseMessage extends MedtronicSendMessageResponseMessa
// Recent Bolus Wizard BGL // Recent Bolus Wizard BGL
pumpRecord.setRecentBolusWizard(recentBolusWizard); pumpRecord.setRecentBolusWizard(recentBolusWizard);
if (/*recentBolusWizard && */activeInsulin > DataStore.getInstance().getLastPumpStatus().getActiveInsulin()) { // there is a BolusWizard usage & the IOB increaseed
pumpRecord.setBolusWizardBGL(bolusWizardBGL); // In mg/DL pumpRecord.setBolusWizardBGL(bolusWizardBGL); // In mg/DL
} else {
pumpRecord.setBolusWizardBGL(0); // In mg/DL
}
} }
} }
...@@ -11,6 +11,7 @@ import android.util.Log; ...@@ -11,6 +11,7 @@ import android.util.Log;
import java.util.Date; import java.util.Date;
import info.nightscout.android.medtronic.MainActivity; import info.nightscout.android.medtronic.MainActivity;
import info.nightscout.android.utils.ConfigurationStore;
/** /**
* Created by lgoedhart on 14/07/2016. * Created by lgoedhart on 14/07/2016.
...@@ -81,7 +82,7 @@ public class MedtronicCnlAlarmManager { ...@@ -81,7 +82,7 @@ public class MedtronicCnlAlarmManager {
// restarting the alarm after MedtronicCnlIntentService.POLL_PERIOD_MS from now // restarting the alarm after MedtronicCnlIntentService.POLL_PERIOD_MS from now
public static void restartAlarm() { public static void restartAlarm() {
//setAlarmAfterMillis(MainActivity.pollInterval + MedtronicCnlIntentService.POLL_GRACE_PERIOD_MS); //setAlarmAfterMillis(MainActivity.pollInterval + MedtronicCnlIntentService.POLL_GRACE_PERIOD_MS);
setAlarmAfterMillis(MainActivity.pollInterval); // grace already accounted for when using current intent time to set default restart setAlarmAfterMillis(ConfigurationStore.getInstance().getPollInterval()); // grace already accounted for when using current intent time to set default restart
} }
// Cancel the alarm. // Cancel the alarm.
......
...@@ -35,6 +35,8 @@ import info.nightscout.android.model.medtronicNg.ContourNextLinkInfo; ...@@ -35,6 +35,8 @@ import info.nightscout.android.model.medtronicNg.ContourNextLinkInfo;
import info.nightscout.android.model.medtronicNg.PumpInfo; import info.nightscout.android.model.medtronicNg.PumpInfo;
import info.nightscout.android.model.medtronicNg.PumpStatusEvent; import info.nightscout.android.model.medtronicNg.PumpStatusEvent;
import info.nightscout.android.upload.nightscout.NightscoutUploadReceiver; import info.nightscout.android.upload.nightscout.NightscoutUploadReceiver;
import info.nightscout.android.utils.ConfigurationStore;
import info.nightscout.android.utils.DataStore;
import info.nightscout.android.xdrip_plus.XDripPlusUploadReceiver; import info.nightscout.android.xdrip_plus.XDripPlusUploadReceiver;
import io.realm.Realm; import io.realm.Realm;
import io.realm.RealmResults; import io.realm.RealmResults;
...@@ -48,10 +50,13 @@ public class MedtronicCnlIntentService extends IntentService { ...@@ -48,10 +50,13 @@ public class MedtronicCnlIntentService extends IntentService {
// Number of additional seconds to wait after the next expected CGM poll, so that we don't interfere with CGM radio comms. // Number of additional seconds to wait after the next expected CGM poll, so that we don't interfere with CGM radio comms.
public final static long POLL_GRACE_PERIOD_MS = 30000L; public final static long POLL_GRACE_PERIOD_MS = 30000L;
private static final String TAG = MedtronicCnlIntentService.class.getSimpleName(); private static final String TAG = MedtronicCnlIntentService.class.getSimpleName();
private UsbHidDriver mHidDevice; private UsbHidDriver mHidDevice;
private Context mContext; private Context mContext;
private NotificationManagerCompat nm; private NotificationManagerCompat nm;
private UsbManager mUsbManager; private UsbManager mUsbManager;
private DataStore dataStore = DataStore.getInstance();
private ConfigurationStore configurationStore = ConfigurationStore.getInstance();
public MedtronicCnlIntentService() { public MedtronicCnlIntentService() {
super(MedtronicCnlIntentService.class.getName()); super(MedtronicCnlIntentService.class.getName());
...@@ -100,10 +105,14 @@ public class MedtronicCnlIntentService extends IntentService { ...@@ -100,10 +105,14 @@ public class MedtronicCnlIntentService extends IntentService {
protected void onHandleIntent(Intent intent) { protected void onHandleIntent(Intent intent) {
Log.d(TAG, "onHandleIntent called"); Log.d(TAG, "onHandleIntent called");
long timePollStarted = System.currentTimeMillis(); long timePollStarted = System.currentTimeMillis(),
long timePollExpected = timePollStarted; timePollExpected = timePollStarted,
if (MainActivity.timeLastGoodSGV != 0) { timeLastGoodSGV = dataStore.getLastPumpStatus().getEventDate().getTime();
timePollExpected = MainActivity.timeLastGoodSGV + POLL_PERIOD_MS + POLL_GRACE_PERIOD_MS + (POLL_PERIOD_MS * ((timePollStarted - 1000L - (MainActivity.timeLastGoodSGV + POLL_GRACE_PERIOD_MS)) / POLL_PERIOD_MS));
short pumpBatteryLevel = dataStore.getLastPumpStatus().getBatteryPercentage();
if (timeLastGoodSGV != 0) {
timePollExpected = timeLastGoodSGV + POLL_PERIOD_MS + POLL_GRACE_PERIOD_MS + (POLL_PERIOD_MS * ((timePollStarted - 1000L - (timeLastGoodSGV + POLL_GRACE_PERIOD_MS)) / POLL_PERIOD_MS));
} }
// avoid polling when too close to sensor-pump comms // avoid polling when too close to sensor-pump comms
...@@ -114,9 +123,9 @@ public class MedtronicCnlIntentService extends IntentService { ...@@ -114,9 +123,9 @@ public class MedtronicCnlIntentService extends IntentService {
return; return;
} }
long pollInterval = MainActivity.pollInterval; long pollInterval = configurationStore.getPollInterval();
if ((MainActivity.pumpBattery > 0) && (MainActivity.pumpBattery <= 25)) { if ((pumpBatteryLevel > 0) && (pumpBatteryLevel <= 25)) {
pollInterval = MainActivity.lowBatteryPollInterval; pollInterval = configurationStore.getLowBatteryPollInterval();
} }
if (!hasUsbHostFeature()) { if (!hasUsbHostFeature()) {
...@@ -216,9 +225,10 @@ public class MedtronicCnlIntentService extends IntentService { ...@@ -216,9 +225,10 @@ public class MedtronicCnlIntentService extends IntentService {
if (radioChannel == 0) { if (radioChannel == 0) {
sendStatus("Could not communicate with the 640g. Are you near the pump?"); sendStatus("Could not communicate with the 640g. Are you near the pump?");
Log.i(TAG, "Could not communicate with the 640g. Are you near the pump?"); Log.i(TAG, "Could not communicate with the 640g. Are you near the pump?");
pollInterval = MainActivity.pollInterval / (MainActivity.reducePollOnPumpAway?2L:1L); // reduce polling interval to half until pump is available pollInterval = configurationStore.getPollInterval() / (configurationStore.isReducePollOnPumpAway()?2L:1L); // reduce polling interval to half until pump is available
} else { } else {
setActivePumpMac(pumpMAC); dataStore.setActivePumpMac(pumpMAC);
activePump.setLastRadioChannel(radioChannel); activePump.setLastRadioChannel(radioChannel);
sendStatus(String.format(Locale.getDefault(), "Connected on channel %d RSSI: %d%%", (int) radioChannel, cnlReader.getPumpSession().getRadioRSSIpercentage())); sendStatus(String.format(Locale.getDefault(), "Connected on channel %d RSSI: %d%%", (int) radioChannel, cnlReader.getPumpSession().getRadioRSSIpercentage()));
Log.d(TAG, String.format("Connected to Contour Next Link on channel %d.", (int) radioChannel)); Log.d(TAG, String.format("Connected to Contour Next Link on channel %d.", (int) radioChannel));
...@@ -242,7 +252,6 @@ public class MedtronicCnlIntentService extends IntentService { ...@@ -242,7 +252,6 @@ public class MedtronicCnlIntentService extends IntentService {
cnlReader.updatePumpStatus(pumpRecord); cnlReader.updatePumpStatus(pumpRecord);
if (pumpRecord.getSgv() != 0) { if (pumpRecord.getSgv() != 0) {
String offsetSign = ""; String offsetSign = "";
if (pumpOffset > 0) { if (pumpOffset > 0) {
offsetSign = "+"; offsetSign = "+";
...@@ -250,14 +259,14 @@ public class MedtronicCnlIntentService extends IntentService { ...@@ -250,14 +259,14 @@ public class MedtronicCnlIntentService extends IntentService {
sendStatus("SGV: " + MainActivity.strFormatSGV(pumpRecord.getSgv()) + " At: " + df.format(pumpRecord.getEventDate().getTime()) + " Pump: " + offsetSign + (pumpOffset / 1000L) + "sec"); //note: event time is currently stored with offset sendStatus("SGV: " + MainActivity.strFormatSGV(pumpRecord.getSgv()) + " At: " + df.format(pumpRecord.getEventDate().getTime()) + " Pump: " + offsetSign + (pumpOffset / 1000L) + "sec"); //note: event time is currently stored with offset
// Check if pump sent old event when new expected and schedule a re-poll // Check if pump sent old event when new expected and schedule a re-poll
if (((pumpRecord.getEventDate().getTime() - MainActivity.timeLastGoodSGV) < 5000L) && ((timePollExpected - timePollStarted) < 5000L)) { if (((pumpRecord.getEventDate().getTime() - dataStore.getLastPumpStatus().getEventDate().getTime()) < 5000L) && ((timePollExpected - timePollStarted) < 5000L)) {
pollInterval = 90000L; // polling interval set to 90 seconds pollInterval = 90000L; // polling interval set to 90 seconds
sendStatus("Pump sent old SGV event, re-polling..."); sendStatus("Pump sent old SGV event, re-polling...");
} }
MainActivity.timeLastGoodSGV = pumpRecord.getEventDate().getTime(); // track last good sgv event time //MainActivity.timeLastGoodSGV = pumpRecord.getEventDate().getTime(); // track last good sgv event time
MainActivity.pumpBattery = pumpRecord.getBatteryPercentage(); // track pump battery //MainActivity.pumpBattery = pumpRecord.getBatteryPercentage(); // track pump battery
MainActivity.countUnavailableSGV = 0; // reset unavailable sgv count dataStore.clearUnavailableSGVCount(); // reset unavailable sgv count
// Check that the record doesn't already exist before committing // Check that the record doesn't already exist before committing
RealmResults<PumpStatusEvent> checkExistingRecords = activePump.getPumpHistory() RealmResults<PumpStatusEvent> checkExistingRecords = activePump.getPumpHistory()
...@@ -269,13 +278,12 @@ public class MedtronicCnlIntentService extends IntentService { ...@@ -269,13 +278,12 @@ public class MedtronicCnlIntentService extends IntentService {
// There should be the 1 record we've already added in this transaction. // There should be the 1 record we've already added in this transaction.
if (checkExistingRecords.size() == 0) { if (checkExistingRecords.size() == 0) {
activePump.getPumpHistory().add(pumpRecord); activePump.getPumpHistory().add(pumpRecord);
dataStore.setLastPumpStatus(pumpRecord);
} }
Log.d(TAG, "history reading size: " + activePump.getPumpHistory().size());
Log.d(TAG, "history reading date: " + activePump.getPumpHistory().last().getEventDate());
} else { } else {
sendStatus("SGV: unavailable from pump"); sendStatus("SGV: unavailable from pump");
MainActivity.countUnavailableSGV ++; // poll clash detection dataStore.incUnavailableSGVCount(); // poll clash detection
} }
realm.commitTransaction(); realm.commitTransaction();
...@@ -286,11 +294,11 @@ public class MedtronicCnlIntentService extends IntentService { ...@@ -286,11 +294,11 @@ public class MedtronicCnlIntentService extends IntentService {
} catch (UnexpectedMessageException e) { } catch (UnexpectedMessageException e) {
Log.e(TAG, "Unexpected Message", e); Log.e(TAG, "Unexpected Message", e);
sendStatus("Communication Error: " + e.getMessage()); sendStatus("Communication Error: " + e.getMessage());
pollInterval = MainActivity.pollInterval / (MainActivity.reducePollOnPumpAway?2L:1L); pollInterval = configurationStore.getPollInterval() / (configurationStore.isReducePollOnPumpAway()?2L:1L);
} catch (TimeoutException e) { } catch (TimeoutException e) {
Log.e(TAG, "Timeout communicating with the Contour Next Link.", e); Log.e(TAG, "Timeout communicating with the Contour Next Link.", e);
sendStatus("Timeout communicating with the Contour Next Link."); sendStatus("Timeout communicating with the Contour Next Link.");
pollInterval = MainActivity.pollInterval / (MainActivity.reducePollOnPumpAway?2L:1L); pollInterval = configurationStore.getPollInterval() / (configurationStore.isReducePollOnPumpAway()?2L:1L);
} catch (NoSuchAlgorithmException e) { } catch (NoSuchAlgorithmException e) {
Log.e(TAG, "Could not determine CNL HMAC", e); Log.e(TAG, "Could not determine CNL HMAC", e);
sendStatus("Error connecting to Contour Next Link: Hashing error."); sendStatus("Error connecting to Contour Next Link: Hashing error.");
...@@ -331,8 +339,8 @@ public class MedtronicCnlIntentService extends IntentService { ...@@ -331,8 +339,8 @@ public class MedtronicCnlIntentService extends IntentService {
// smart polling and pump-sensor poll clash detection // smart polling and pump-sensor poll clash detection
long lastActualPollTime = timePollStarted; long lastActualPollTime = timePollStarted;
if (MainActivity.timeLastGoodSGV > 0) { if (timeLastGoodSGV > 0) {
lastActualPollTime = MainActivity.timeLastGoodSGV + POLL_GRACE_PERIOD_MS + (POLL_PERIOD_MS * ((System.currentTimeMillis() - (MainActivity.timeLastGoodSGV + POLL_GRACE_PERIOD_MS)) / POLL_PERIOD_MS)); lastActualPollTime = timeLastGoodSGV + POLL_GRACE_PERIOD_MS + (POLL_PERIOD_MS * ((System.currentTimeMillis() - (timeLastGoodSGV + POLL_GRACE_PERIOD_MS)) / POLL_PERIOD_MS));
} }
long nextActualPollTime = lastActualPollTime + POLL_PERIOD_MS; long nextActualPollTime = lastActualPollTime + POLL_PERIOD_MS;
long nextRequestedPollTime = lastActualPollTime + pollInterval; long nextRequestedPollTime = lastActualPollTime + pollInterval;
...@@ -341,13 +349,13 @@ public class MedtronicCnlIntentService extends IntentService { ...@@ -341,13 +349,13 @@ public class MedtronicCnlIntentService extends IntentService {
} }
// extended unavailable SGV may be due to clash with the current polling time // extended unavailable SGV may be due to clash with the current polling time
// while we wait for a good SGV event, polling is auto adjusted by offsetting the next poll based on miss count // while we wait for a good SGV event, polling is auto adjusted by offsetting the next poll based on miss count
if (MainActivity.countUnavailableSGV > 0) { if (dataStore.getUnavailableSGVCount() > 0) {
if (MainActivity.timeLastGoodSGV == 0) { if (timeLastGoodSGV == 0) {
nextRequestedPollTime += POLL_PERIOD_MS / 5L; // if there is a uploader/sensor poll clash on startup then this will push the next attempt out by 60 seconds nextRequestedPollTime += POLL_PERIOD_MS / 5L; // if there is a uploader/sensor poll clash on startup then this will push the next attempt out by 60 seconds
} }
else if (MainActivity.countUnavailableSGV > 2) { else if (dataStore.getUnavailableSGVCount() > 2) {
sendStatus("Warning: No SGV available from pump for " + MainActivity.countUnavailableSGV + " attempts"); sendStatus("Warning: No SGV available from pump for " +dataStore.getUnavailableSGVCount() + " attempts");
nextRequestedPollTime += ((long) ((MainActivity.countUnavailableSGV - 2) % 5)) * (POLL_PERIOD_MS / 10L); // adjust poll time in 1/10 steps to avoid potential poll clash (max adjustment at 5/10) nextRequestedPollTime += ((long) ((dataStore.getUnavailableSGVCount() - 2) % 5)) * (POLL_PERIOD_MS / 10L); // adjust poll time in 1/10 steps to avoid potential poll clash (max adjustment at 5/10)
} }
} }
MedtronicCnlAlarmManager.setAlarm(nextRequestedPollTime); MedtronicCnlAlarmManager.setAlarm(nextRequestedPollTime);
...@@ -357,10 +365,6 @@ public class MedtronicCnlIntentService extends IntentService { ...@@ -357,10 +365,6 @@ public class MedtronicCnlIntentService extends IntentService {
} }
} }
private void setActivePumpMac(long pumpMAC) {
MainActivity.setActivePumpMac(pumpMAC);
}
// reliable wake alarm manager wake up for all android versions // reliable wake alarm manager wake up for all android versions
public static void wakeUpIntent(Context context, long wakeTime, PendingIntent pendingIntent) { public static void wakeUpIntent(Context context, long wakeTime, PendingIntent pendingIntent) {
final AlarmManager alarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); final AlarmManager alarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
......
...@@ -302,4 +302,37 @@ public class PumpStatusEvent extends RealmObject { ...@@ -302,4 +302,37 @@ public class PumpStatusEvent extends RealmObject {
} }
} }
} }
@Override
public String toString() {
return "PumpStatusEvent{" +
"eventDate=" + eventDate +
", pumpDate=" + pumpDate +
", deviceName='" + deviceName + '\'' +
", suspended=" + suspended +
", bolusing=" + bolusing +
", deliveringInsulin=" + deliveringInsulin +
", tempBasalActive=" + tempBasalActive +
", cgmActive=" + cgmActive +
", activeBasalPattern=" + activeBasalPattern +
", basalRate=" + basalRate +
", tempBasalRate=" + tempBasalRate +
", tempBasalPercentage=" + tempBasalPercentage +
", tempBasalMinutesRemaining=" + tempBasalMinutesRemaining +
", basalUnitsDeliveredToday=" + basalUnitsDeliveredToday +
", batteryPercentage=" + batteryPercentage +
", reservoirAmount=" + reservoirAmount +
", minutesOfInsulinRemaining=" + minutesOfInsulinRemaining +
", activeInsulin=" + activeInsulin +
", sgv=" + sgv +
", sgvDate=" + sgvDate +
", lowSuspendActive=" + lowSuspendActive +
", cgmTrend='" + cgmTrend + '\'' +
", recentBolusWizard=" + recentBolusWizard +
", bolusWizardBGL=" + bolusWizardBGL +
", pumpTimeOffset=" + pumpTimeOffset +
", uploaded=" + uploaded +
'}';
}
} }
package info.nightscout.android.settings; package info.nightscout.android.settings;
import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.os.Bundle; import android.os.Bundle;
...@@ -9,14 +10,32 @@ import android.preference.MultiSelectListPreference; ...@@ -9,14 +10,32 @@ import android.preference.MultiSelectListPreference;
import android.preference.Preference; import android.preference.Preference;
import android.preference.PreferenceCategory; import android.preference.PreferenceCategory;
import android.preference.PreferenceFragment; import android.preference.PreferenceFragment;
import android.support.annotation.Nullable;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.zxing.integration.android.IntentIntegrator;
import com.google.zxing.integration.android.IntentResult;
import java.net.MalformedURLException;
import java.net.URL;
import info.nightscout.android.R; import info.nightscout.android.R;
import info.nightscout.android.medtronic.message.PumpTimeResponseMessage;
public class SettingsFragment extends PreferenceFragment implements OnSharedPreferenceChangeListener { public class SettingsFragment extends PreferenceFragment implements OnSharedPreferenceChangeListener {
private static final String TAG = SettingsFragment.class.getSimpleName();
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
final SettingsFragment that = this;
/* set preferences */ /* set preferences */
addPreferencesFromResource(R.xml.preferences); addPreferencesFromResource(R.xml.preferences);
...@@ -27,13 +46,23 @@ public class SettingsFragment extends PreferenceFragment implements OnSharedPref ...@@ -27,13 +46,23 @@ public class SettingsFragment extends PreferenceFragment implements OnSharedPref
} }
setMinBatPollIntervall((ListPreference) findPreference("pollInterval"), (ListPreference) findPreference("lowBatPollInterval")); setMinBatPollIntervall((ListPreference) findPreference("pollInterval"), (ListPreference) findPreference("lowBatPollInterval"));
Preference button = findPreference("scanButton");
button.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
IntentIntegrator integrator = new IntentIntegrator(that);
integrator.initiateScan();
return true;
}
});
} }
@Override @Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
Preference pref = findPreference(key); Preference pref = findPreference(key);
if ("pollInterval".equals(key)) { if ("pollInterval".equals(key)) {
setMinBatPollIntervall((ListPreference) pref, (ListPreference) findPreference("lowBatPollInterval")); setMinBatPollIntervall((ListPreference) pref, (ListPreference) findPreference("lowBatPollInterval"));
} }
...@@ -110,4 +139,54 @@ public class SettingsFragment extends PreferenceFragment implements OnSharedPref ...@@ -110,4 +139,54 @@ public class SettingsFragment extends PreferenceFragment implements OnSharedPref
p.setSummary(editTextPref.getText()); p.setSummary(editTextPref.getText());
} }
} }
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode==IntentIntegrator.REQUEST_CODE)
{
IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
if (scanResult != null)
{
Log.d(TAG, "scanResult returns: " + scanResult.toString());
JsonParser json = new JsonParser();
JsonElement jsonElement = json.parse(scanResult.getContents());
if (jsonElement != null && jsonElement.isJsonObject()) {
jsonElement = (jsonElement.getAsJsonObject()).get("rest");
if (jsonElement != null && jsonElement.isJsonObject()) {
jsonElement = (jsonElement.getAsJsonObject()).get("endpoint");
if (jsonElement != null && jsonElement.isJsonArray() && jsonElement.getAsJsonArray().size() > 0) {
String endpoint = jsonElement.getAsJsonArray().get(0).getAsString();
Log.d(TAG, "endpoint: " + endpoint);
try {
URL uri = new URL(endpoint);
StringBuffer url = new StringBuffer(uri.getProtocol())
.append("://").append(uri.getHost());
if (uri.getPort() > -1)
url.append(":").append(uri.getPort());
EditTextPreference editPref = (EditTextPreference) findPreference(getString(R.string.preference_nightscout_url));
editPref.setText(url.toString());
updatePrefSummary(editPref);
editPref = (EditTextPreference) findPreference(getString(R.string.preference_api_secret));
editPref.setText(uri.getUserInfo());
updatePrefSummary(editPref);
} catch (MalformedURLException e) {
Log.w (TAG, e.getMessage());
}
}
}
}
}
else
{
Log.d(TAG, "scanResult is null.");
}
}
}
} }
\ No newline at end of file
...@@ -27,6 +27,9 @@ import info.nightscout.api.DeviceEndpoints.Battery; ...@@ -27,6 +27,9 @@ import info.nightscout.api.DeviceEndpoints.Battery;
import info.nightscout.api.DeviceEndpoints.PumpStatus; import info.nightscout.api.DeviceEndpoints.PumpStatus;
import info.nightscout.api.DeviceEndpoints.PumpInfo; import info.nightscout.api.DeviceEndpoints.PumpInfo;
import info.nightscout.api.DeviceEndpoints.DeviceStatus; import info.nightscout.api.DeviceEndpoints.DeviceStatus;
import okhttp3.ResponseBody;
import retrofit2.Response;
import retrofit2.Retrofit;
class NightScoutUpload { class NightScoutUpload {
...@@ -59,7 +62,7 @@ class NightScoutUpload { ...@@ -59,7 +62,7 @@ class NightScoutUpload {
UploadApi uploadApi = new UploadApi(baseURL, formToken(secret)); UploadApi uploadApi = new UploadApi(baseURL, formToken(secret));
boolean eventsUploaded = uploadEvents(uploadApi.getGlucoseEndpoints(), boolean eventsUploaded = uploadEvents(uploadApi.getGlucoseEndpoints(),
uploadApi.getBolusApi(), uploadApi.getBolusEndpoints(),
records); records);
boolean deviceStatusUploaded = uploadDeviceStatus(uploadApi.getDeviceEndpoints(), boolean deviceStatusUploaded = uploadDeviceStatus(uploadApi.getDeviceEndpoints(),
...@@ -103,15 +106,16 @@ class NightScoutUpload { ...@@ -103,15 +106,16 @@ class NightScoutUpload {
} }
boolean uploaded = true;
if (glucoseEntries.size() > 0) { if (glucoseEntries.size() > 0) {
glucoseEndpoints.sendEntries(glucoseEntries).execute(); Response<ResponseBody> result = glucoseEndpoints.sendEntries(glucoseEntries).execute();
uploaded = uploaded && result.isSuccessful();
} }
if (bolusEntries.size() > 0) { if (bolusEntries.size() > 0) {
bolusEndpoints.sendEntries(bolusEntries).execute(); Response<ResponseBody> result = bolusEndpoints.sendEntries(bolusEntries).execute();
uploaded = uploaded && result.isSuccessful();
} }
return uploaded;
return true;
} }
private boolean uploadDeviceStatus(DeviceEndpoints deviceEndpoints, private boolean uploadDeviceStatus(DeviceEndpoints deviceEndpoints,
...@@ -152,11 +156,13 @@ class NightScoutUpload { ...@@ -152,11 +156,13 @@ class NightScoutUpload {
deviceEntries.add(deviceStatus); deviceEntries.add(deviceStatus);
} }
boolean uploaded = true;
for (DeviceStatus status : deviceEntries) { for (DeviceStatus status : deviceEntries) {
deviceEndpoints.sendDeviceStatus(status).execute(); Response<ResponseBody> result = deviceEndpoints.sendDeviceStatus(status).execute();
uploaded = uploaded && result.isSuccessful();
} }
return true; return uploaded;
} }
@NonNull @NonNull
......
...@@ -11,8 +11,8 @@ import android.support.v4.content.LocalBroadcastManager; ...@@ -11,8 +11,8 @@ import android.support.v4.content.LocalBroadcastManager;
import android.util.Log; import android.util.Log;
import info.nightscout.android.R; import info.nightscout.android.R;
import info.nightscout.android.medtronic.MainActivity;
import info.nightscout.android.model.medtronicNg.PumpStatusEvent; import info.nightscout.android.model.medtronicNg.PumpStatusEvent;
import info.nightscout.android.utils.DataStore;
import io.realm.Realm; import io.realm.Realm;
import io.realm.RealmResults; import io.realm.RealmResults;
...@@ -67,9 +67,8 @@ public class NightscoutUploadIntentService extends IntentService { ...@@ -67,9 +67,8 @@ public class NightscoutUploadIntentService extends IntentService {
Log.i(TAG, String.format("Starting upload of %s record using a REST API", records.size())); Log.i(TAG, String.format("Starting upload of %s record using a REST API", records.size()));
String urlSetting = prefs.getString(mContext.getString(R.string.preference_nightscout_url), ""); String urlSetting = prefs.getString(mContext.getString(R.string.preference_nightscout_url), "");
String secretSetting = prefs.getString(mContext.getString(R.string.preference_api_secret), "YOURAPISECRET"); String secretSetting = prefs.getString(mContext.getString(R.string.preference_api_secret), "YOURAPISECRET");
int uploaderBatteryLevel = MainActivity.batLevel;
Boolean uploadSuccess = mNightScoutUpload.doRESTUpload(urlSetting, Boolean uploadSuccess = mNightScoutUpload.doRESTUpload(urlSetting,
secretSetting, uploaderBatteryLevel, records); secretSetting, DataStore.getInstance().getUplooaderBatteryLevel(), records);
if (uploadSuccess) { if (uploadSuccess) {
mRealm.beginTransaction(); mRealm.beginTransaction();
for (PumpStatusEvent updateRecord : records) { for (PumpStatusEvent updateRecord : records) {
......
package info.nightscout.android.utils;
import info.nightscout.android.medtronic.service.MedtronicCnlIntentService;
import info.nightscout.android.model.medtronicNg.PumpStatusEvent;
/**
* Created by volker on 30.03.2017.
*/
public class ConfigurationStore {
private static ConfigurationStore instance;
private boolean reducePollOnPumpAway = false;
private long pollInterval = MedtronicCnlIntentService.POLL_PERIOD_MS;
private long lowBatteryPollInterval = MedtronicCnlIntentService.LOW_BATTERY_POLL_PERIOD_MS;
private boolean mmolxl;
private boolean mmolxlDecimals;
public static ConfigurationStore getInstance() {
if (ConfigurationStore.instance == null) {
instance = new ConfigurationStore();
}
return instance;
}
public boolean isReducePollOnPumpAway() {
return reducePollOnPumpAway;
}
public void setReducePollOnPumpAway(boolean reducePollOnPumpAway) {
this.reducePollOnPumpAway = reducePollOnPumpAway;
}
public long getPollInterval() {
return pollInterval;
}
public void setPollInterval(long pollInterval) {
this.pollInterval = pollInterval;
}
public long getLowBatteryPollInterval() {
return lowBatteryPollInterval;
}
public void setLowBatteryPollInterval(long lowBatteryPollInterval) {
this.lowBatteryPollInterval = lowBatteryPollInterval;
}
public boolean isMmolxl() {
return mmolxl;
}
public void setMmolxl(boolean mmolxl) {
this.mmolxl = mmolxl;
}
public boolean isMmolxlDecimals() {
return mmolxlDecimals;
}
public void setMmolxlDecimals(boolean mmolxlDecimals) {
this.mmolxlDecimals = mmolxlDecimals;
}
}
package info.nightscout.android.utils;
import com.bugfender.sdk.a.a.k.a;
import java.util.Date;
import info.nightscout.android.model.medtronicNg.PumpStatusEvent;
import io.realm.Realm;
/**
* Created by volker on 30.03.2017.
*/
public class DataStore {
private static DataStore instance;
private PumpStatusEvent lastPumpStatus;
private int uplooaderBatteryLevel = 0;
private int unavailableSGVCount = 0;
private long activePumpMac = 0;
private DataStore() {}
public static DataStore getInstance() {
if (DataStore.instance == null) {
instance = new DataStore();
// set some initial dummy values
PumpStatusEvent dummyStatus = new PumpStatusEvent();
dummyStatus.setEventDate(new Date(0));
// bypass setter to avoid dealing with a real Realm object
instance.lastPumpStatus = dummyStatus;
}
return instance;
}
public PumpStatusEvent getLastPumpStatus() {
return lastPumpStatus;
}
public void setLastPumpStatus(PumpStatusEvent lastPumpStatus) {
Realm realm = Realm.getDefaultInstance();
this.lastPumpStatus = realm.copyFromRealm(lastPumpStatus);
if (!realm.isClosed()) realm.close();
}
public int getUplooaderBatteryLevel() {
return uplooaderBatteryLevel;
}
public void setUplooaderBatteryLevel(int uplooaderBatteryLevel) {
this.uplooaderBatteryLevel = uplooaderBatteryLevel;
}
public int getUnavailableSGVCount() {
return unavailableSGVCount;
}
public int incUnavailableSGVCount() {
return unavailableSGVCount++;
}
public void clearUnavailableSGVCount() {
this.unavailableSGVCount = 0;
}
public void setUnavailableSGVCount(int unavailableSGVCount) {
this.unavailableSGVCount = unavailableSGVCount;
}
public long getActivePumpMac() {
return activePumpMac;
}
public void setActivePumpMac(long activePumpMac) {
this.activePumpMac = activePumpMac;
}
}
...@@ -16,9 +16,9 @@ import java.text.SimpleDateFormat; ...@@ -16,9 +16,9 @@ import java.text.SimpleDateFormat;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import info.nightscout.android.medtronic.MainActivity;
import info.nightscout.android.model.medtronicNg.PumpStatusEvent; import info.nightscout.android.model.medtronicNg.PumpStatusEvent;
import info.nightscout.android.upload.nightscout.serializer.EntriesSerializer; import info.nightscout.android.upload.nightscout.serializer.EntriesSerializer;
import info.nightscout.android.utils.DataStore;
import io.realm.Realm; import io.realm.Realm;
import io.realm.RealmResults; import io.realm.RealmResults;
import io.realm.Sort; import io.realm.Sort;
...@@ -116,7 +116,7 @@ public class XDripPlusUploadIntentService extends IntentService { ...@@ -116,7 +116,7 @@ public class XDripPlusUploadIntentService extends IntentService {
private void addDeviceStatus(JSONArray devicestatusArray, PumpStatusEvent record) throws Exception { private void addDeviceStatus(JSONArray devicestatusArray, PumpStatusEvent record) throws Exception {
JSONObject json = new JSONObject(); JSONObject json = new JSONObject();
json.put("uploaderBattery", MainActivity.batLevel); json.put("uploaderBattery", DataStore.getInstance().getUplooaderBatteryLevel());
json.put("device", record.getDeviceName()); json.put("device", record.getDeviceName());
json.put("created_at", ISO8601_DATE_FORMAT.format(record.getPumpDate())); json.put("created_at", ISO8601_DATE_FORMAT.format(record.getPumpDate()));
......
...@@ -15,15 +15,15 @@ import retrofit2.converter.gson.GsonConverterFactory; ...@@ -15,15 +15,15 @@ import retrofit2.converter.gson.GsonConverterFactory;
public class UploadApi { public class UploadApi {
private Retrofit retrofit; private Retrofit retrofit;
private GlucoseEndpoints glucoseEndpoints; private GlucoseEndpoints glucoseEndpoints;
private BolusEndpoints bolusApi; private BolusEndpoints bolusEndpoints;
private DeviceEndpoints deviceEndpoints; private DeviceEndpoints deviceEndpoints;
public GlucoseEndpoints getGlucoseEndpoints() { public GlucoseEndpoints getGlucoseEndpoints() {
return glucoseEndpoints; return glucoseEndpoints;
} }
public BolusEndpoints getBolusApi() { public BolusEndpoints getBolusEndpoints() {
return bolusApi; return bolusEndpoints;
} }
public DeviceEndpoints getDeviceEndpoints() { public DeviceEndpoints getDeviceEndpoints() {
...@@ -71,8 +71,7 @@ public class UploadApi { ...@@ -71,8 +71,7 @@ public class UploadApi {
.build(); .build();
glucoseEndpoints = retrofit.create(GlucoseEndpoints.class); glucoseEndpoints = retrofit.create(GlucoseEndpoints.class);
bolusApi = retrofit.create(BolusEndpoints.class); bolusEndpoints = retrofit.create(BolusEndpoints.class);
deviceEndpoints = retrofit.create(DeviceEndpoints.class); deviceEndpoints = retrofit.create(DeviceEndpoints.class);
} }
} }
...@@ -70,6 +70,10 @@ ...@@ -70,6 +70,10 @@
android:dialogTitle="Enter your Nightscout API secret" android:dialogTitle="Enter your Nightscout API secret"
android:key="@string/preference_api_secret" android:key="@string/preference_api_secret"
android:title="API Secret"/> android:title="API Secret"/>
<Preference android:title="scan NS-Autoconfig QR-Code"
android:key="scanButton"
android:dependency="@string/preference_enable_rest_upload"
android:summary="Click here to scan QR-Code from http://nightscout.github.io/pages/configure/ using ZXing barcode scanner."/>
<CheckBoxPreference <CheckBoxPreference
android:key="@string/preference_enable_xdrip_plus" android:key="@string/preference_enable_xdrip_plus"
android:summary="Enable local broadcast of data to xDrip+" android:summary="Enable local broadcast of data to xDrip+"
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment