Merge branch 'dev' into smb060
This commit is contained in:
commit
98e850b1b3
49 changed files with 1057 additions and 460 deletions
|
@ -7,12 +7,15 @@ android:
|
|||
components:
|
||||
- platform-tools
|
||||
- tools
|
||||
- build-tools-26.0.2
|
||||
- build-tools-27.0.2
|
||||
- android-23
|
||||
- extra-google-m2repository
|
||||
- extra-android-m2repository
|
||||
- extra-google-google_play_services
|
||||
|
||||
before_install:
|
||||
- yes | sdkmanager "platforms;android-27"
|
||||
|
||||
script:
|
||||
# Unit Test
|
||||
- ./gradlew test jacocoTestReport
|
||||
|
|
|
@ -12,9 +12,10 @@ buildscript {
|
|||
apply plugin: "com.android.application"
|
||||
apply plugin: "io.fabric"
|
||||
apply plugin: "jacoco-android"
|
||||
apply plugin: 'com.jakewharton.butterknife'
|
||||
|
||||
ext {
|
||||
supportLibraryVersion = "23.4.0"
|
||||
supportLibraryVersion = "27.0.2"
|
||||
ormLiteVersion = "4.46"
|
||||
powermockVersion = "1.7.3"
|
||||
dexmakerVersion = "1.2"
|
||||
|
@ -47,8 +48,8 @@ def generateGitBuild = { ->
|
|||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 23
|
||||
buildToolsVersion "26.0.2"
|
||||
compileSdkVersion 27
|
||||
buildToolsVersion "${supportLibraryVersion}"
|
||||
|
||||
defaultConfig {
|
||||
applicationId "info.nightscout.androidaps"
|
||||
|
@ -204,6 +205,9 @@ dependencies {
|
|||
|
||||
compile "net.danlew:android.joda:2.9.9.1"
|
||||
|
||||
api "com.jakewharton:butterknife:8.8.1"
|
||||
annotationProcessor "com.jakewharton:butterknife-compiler:8.8.1"
|
||||
|
||||
testCompile "junit:junit:4.12"
|
||||
testCompile "org.json:json:20140107"
|
||||
testCompile "org.mockito:mockito-core:2.7.22"
|
||||
|
|
|
@ -82,7 +82,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
|
|||
Manifest.permission.WRITE_EXTERNAL_STORAGE}, CASE_STORAGE);
|
||||
}
|
||||
askForBatteryOptimizationPermission();
|
||||
checkUpgradeToProfileTarget();
|
||||
doMigrations();
|
||||
if (Config.logFunctionCalls)
|
||||
log.debug("onCreate");
|
||||
|
||||
|
@ -163,6 +163,19 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
|
|||
}
|
||||
}
|
||||
|
||||
private void doMigrations() {
|
||||
|
||||
checkUpgradeToProfileTarget();
|
||||
|
||||
// guarantee that the unreachable threshold is at least 30 and of type String
|
||||
// Added in 1.57 at 21.01.2018
|
||||
Integer unreachable_threshold = SP.getInt(R.string.key_pump_unreachable_threshold, 30);
|
||||
SP.remove(R.string.key_pump_unreachable_threshold);
|
||||
if(unreachable_threshold < 30) unreachable_threshold = 30;
|
||||
SP.putString(R.string.key_pump_unreachable_threshold, unreachable_threshold.toString());
|
||||
}
|
||||
|
||||
|
||||
private void checkUpgradeToProfileTarget() { // TODO: can be removed in the future
|
||||
boolean oldKeyExists = SP.contains("openapsma_min_bg");
|
||||
if (oldKeyExists) {
|
||||
|
|
|
@ -235,6 +235,10 @@ public class MainApp extends Application {
|
|||
return sResources.getString(id);
|
||||
}
|
||||
|
||||
public static String gs(int id, Object... args) {
|
||||
return sResources.getString(id, args);
|
||||
}
|
||||
|
||||
public static MainApp instance() {
|
||||
return sInstance;
|
||||
}
|
||||
|
|
|
@ -15,20 +15,22 @@ import org.slf4j.LoggerFactory;
|
|||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.data.ProfileStore;
|
||||
import info.nightscout.androidaps.db.BgReading;
|
||||
import info.nightscout.androidaps.db.CareportalEvent;
|
||||
import info.nightscout.androidaps.events.EventNewBasalProfile;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.ConstraintsObjectives.ObjectivesPlugin;
|
||||
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSDeviceStatus;
|
||||
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSMbg;
|
||||
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSgv;
|
||||
import info.nightscout.androidaps.data.ProfileStore;
|
||||
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSettingsStatus;
|
||||
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
|
||||
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSgv;
|
||||
import info.nightscout.androidaps.plugins.Overview.OverviewPlugin;
|
||||
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
|
||||
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
|
||||
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
|
||||
import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin;
|
||||
import info.nightscout.androidaps.plugins.ProfileNS.events.EventNSProfileUpdateGUI;
|
||||
import info.nightscout.androidaps.plugins.PumpDanaR.activities.DanaRNSHistorySync;
|
||||
import info.nightscout.androidaps.plugins.SmsCommunicator.events.EventNewSMS;
|
||||
import info.nightscout.androidaps.plugins.SourceDexcomG5.SourceDexcomG5Plugin;
|
||||
|
@ -37,7 +39,6 @@ import info.nightscout.androidaps.plugins.SourceMM640g.SourceMM640gPlugin;
|
|||
import info.nightscout.androidaps.plugins.SourceNSClient.SourceNSClientPlugin;
|
||||
import info.nightscout.androidaps.plugins.SourceXdrip.SourceXdripPlugin;
|
||||
import info.nightscout.androidaps.receivers.DataReceiver;
|
||||
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSDeviceStatus;
|
||||
import info.nightscout.utils.BundleLogger;
|
||||
import info.nightscout.utils.NSUpload;
|
||||
import info.nightscout.utils.SP;
|
||||
|
@ -365,8 +366,10 @@ public class DataService extends IntentService {
|
|||
String profile = bundles.getString("profile");
|
||||
ProfileStore profileStore = new ProfileStore(new JSONObject(profile));
|
||||
NSProfilePlugin.storeNewProfile(profileStore);
|
||||
MainApp.bus().post(new EventNSProfileUpdateGUI());
|
||||
// if there are no profile switches this should lead to profile update
|
||||
if (MainApp.getConfigBuilder().getProfileSwitchesFromHistory().size() == 0)
|
||||
MainApp.bus().post(new EventNewBasalProfile());
|
||||
|
||||
if (Config.logIncommingData)
|
||||
log.debug("Received profileStore: " + activeProfile + " " + profile);
|
||||
} catch (JSONException e) {
|
||||
|
|
|
@ -239,6 +239,7 @@ public class Profile {
|
|||
// if pump not available (at start)
|
||||
// do not store converted array
|
||||
basal_v = null;
|
||||
isValidated = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -191,6 +191,17 @@ public class CareportalEvent implements DataPointWithLabelInterface {
|
|||
return Translator.translate(eventType);
|
||||
}
|
||||
|
||||
public String getNotes() {
|
||||
try {
|
||||
JSONObject object = new JSONObject(json);
|
||||
if (object.has("notes"))
|
||||
return object.getString("notes");
|
||||
} catch (JSONException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getDuration() {
|
||||
try {
|
||||
|
|
|
@ -507,7 +507,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
return 0;
|
||||
}
|
||||
|
||||
public int deleteDbRequestbyMongoId(String action, String id) {
|
||||
public void deleteDbRequestbyMongoId(String action, String id) {
|
||||
try {
|
||||
QueryBuilder<DbRequest, String> queryBuilder = getDaoDbRequest().queryBuilder();
|
||||
Where where = queryBuilder.where();
|
||||
|
@ -515,16 +515,13 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
queryBuilder.limit(10L);
|
||||
PreparedQuery<DbRequest> preparedQuery = queryBuilder.prepare();
|
||||
List<DbRequest> dbList = getDaoDbRequest().query(preparedQuery);
|
||||
if (dbList.size() != 1) {
|
||||
log.error("deleteDbRequestbyMongoId query size: " + dbList.size());
|
||||
} else {
|
||||
//log.debug("Treatment findTreatmentById found: " + trList.get(0).log());
|
||||
return delete(dbList.get(0));
|
||||
for (DbRequest r : dbList) {
|
||||
delete(r);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void deleteAllDbRequests() {
|
||||
|
@ -1473,7 +1470,21 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
} catch (SQLException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
return new ArrayList<CareportalEvent>();
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
public List<CareportalEvent> getCareportalEventsFromTime(boolean ascending) {
|
||||
try {
|
||||
List<CareportalEvent> careportalEvents;
|
||||
QueryBuilder<CareportalEvent, Long> queryBuilder = getDaoCareportalEvents().queryBuilder();
|
||||
queryBuilder.orderBy("date", ascending);
|
||||
PreparedQuery<CareportalEvent> preparedQuery = queryBuilder.prepare();
|
||||
careportalEvents = getDaoCareportalEvents().query(preparedQuery);
|
||||
return careportalEvents;
|
||||
} catch (SQLException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
public void deleteCareportalEventById(String _id) {
|
||||
|
|
|
@ -70,7 +70,7 @@ public class FoodHelper {
|
|||
public boolean createOrUpdate(Food food) {
|
||||
try {
|
||||
// find by NS _id
|
||||
if (food._id != null) {
|
||||
if (food._id != null && !food._id.equals("")) {
|
||||
Food old;
|
||||
|
||||
QueryBuilder<Food, Long> queryBuilder = getDaoFood().queryBuilder();
|
||||
|
@ -90,12 +90,13 @@ public class FoodHelper {
|
|||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
getDaoFood().createOrUpdate(food);
|
||||
log.debug("FOOD: New record: " + food.toString());
|
||||
scheduleFoodChange();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
package info.nightscout.androidaps.events;
|
||||
|
||||
/**
|
||||
* Created by mike on 23.01.2018.
|
||||
*/
|
||||
|
||||
public class EventAppInitialized extends Event {
|
||||
}
|
|
@ -35,4 +35,6 @@ public class PumpDescription {
|
|||
public double basalMinimumRate = 0.04d;
|
||||
|
||||
public boolean isRefillingCapable = false;
|
||||
|
||||
public boolean storesCarbInfo = true;
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ import info.nightscout.androidaps.db.Source;
|
|||
import info.nightscout.androidaps.db.TempTarget;
|
||||
import info.nightscout.androidaps.db.TemporaryBasal;
|
||||
import info.nightscout.androidaps.db.Treatment;
|
||||
import info.nightscout.androidaps.events.EventAppInitialized;
|
||||
import info.nightscout.androidaps.interfaces.APSInterface;
|
||||
import info.nightscout.androidaps.interfaces.BgSourceInterface;
|
||||
import info.nightscout.androidaps.interfaces.ConstraintsInterface;
|
||||
|
@ -146,6 +147,7 @@ public class ConfigBuilderPlugin implements PluginBase, ConstraintsInterface, Tr
|
|||
public void initialize() {
|
||||
pluginList = MainApp.getPluginsList();
|
||||
loadSettings();
|
||||
MainApp.bus().post(new EventAppInitialized());
|
||||
}
|
||||
|
||||
public void storeSettings() {
|
||||
|
|
|
@ -197,6 +197,7 @@ public class ObjectivesFragment extends Fragment {
|
|||
ObjectivesPlugin.objectives.get(4).objective = MainApp.sResources.getString(R.string.objectives_4_objective);
|
||||
ObjectivesPlugin.objectives.get(5).objective = MainApp.sResources.getString(R.string.objectives_5_objective);
|
||||
ObjectivesPlugin.objectives.get(6).objective = MainApp.sResources.getString(R.string.objectives_6_objective);
|
||||
ObjectivesPlugin.objectives.get(7).objective = MainApp.sResources.getString(R.string.objectives_7_objective);
|
||||
ObjectivesPlugin.objectives.get(0).gate = MainApp.sResources.getString(R.string.objectives_0_gate);
|
||||
ObjectivesPlugin.objectives.get(1).gate = MainApp.sResources.getString(R.string.objectives_1_gate);
|
||||
ObjectivesPlugin.objectives.get(2).gate = MainApp.sResources.getString(R.string.objectives_2_gate);
|
||||
|
|
|
@ -161,14 +161,14 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface {
|
|||
boolean isVirtualPump = VirtualPumpPlugin.getPlugin().isEnabled(PluginBase.PUMP);
|
||||
boolean vpUploadEnabled = SP.getBoolean("virtualpump_uploadstatus", false);
|
||||
boolean vpUploadNeeded = !isVirtualPump || vpUploadEnabled;
|
||||
boolean hasBGData = DatabaseHelper.lastBg()!=null;
|
||||
boolean hasBGData = DatabaseHelper.lastBg() != null;
|
||||
|
||||
boolean apsEnabled = false;
|
||||
APSInterface usedAPS = ConfigBuilderPlugin.getActiveAPS();
|
||||
if (usedAPS != null && ((PluginBase) usedAPS).isEnabled(PluginBase.APS))
|
||||
apsEnabled = true;
|
||||
|
||||
return new RequirementResult(hasBGData&&bgIsAvailableInNS && pumpStatusIsAvailableInNS && NSClientInternalPlugin.getPlugin().hasWritePermission() && LoopPlugin.getPlugin().isEnabled(PluginBase.LOOP) && apsEnabled && vpUploadNeeded,
|
||||
return new RequirementResult(hasBGData && bgIsAvailableInNS && pumpStatusIsAvailableInNS && NSClientInternalPlugin.getPlugin().hasWritePermission() && LoopPlugin.getPlugin().isEnabled(PluginBase.LOOP) && apsEnabled && vpUploadNeeded,
|
||||
MainApp.sResources.getString(R.string.objectives_bgavailableinns) + ": " + yesOrNo(bgIsAvailableInNS)
|
||||
+ "\n" + MainApp.sResources.getString(R.string.nsclienthaswritepermission) + ": " + yesOrNo(NSClientInternalPlugin.getPlugin().hasWritePermission())
|
||||
+ (isVirtualPump ? "\n" + MainApp.sResources.getString(R.string.virtualpump_uploadstatus_title) + ": " + yesOrNo(vpUploadEnabled) : "")
|
||||
|
@ -320,12 +320,12 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface {
|
|||
|
||||
@Override
|
||||
public Double applyMaxIOBConstraints(Double maxIob) {
|
||||
if (objectives.get(4).started.getTime() > 0 || objectives.get(2).accomplished.getTime() == 0)
|
||||
return maxIob;
|
||||
else {
|
||||
if (objectives.get(3).started.getTime() > 0 && objectives.get(3).accomplished.getTime() == 0) {
|
||||
if (Config.logConstraintsChanges)
|
||||
log.debug("Limiting maxIOB " + maxIob + " to " + 0 + "U");
|
||||
return 0d;
|
||||
} else {
|
||||
return maxIob;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -61,7 +61,6 @@ public class FoodFragment extends SubscriberFragment {
|
|||
Bundle savedInstanceState) {
|
||||
try {
|
||||
View view = inflater.inflate(R.layout.food_fragment, container, false);
|
||||
|
||||
filter = (EditText) view.findViewById(R.id.food_filter);
|
||||
clearFilter = (ImageView) view.findViewById(R.id.food_clearfilter);
|
||||
category = new SpinnerHelper(view.findViewById(R.id.food_category));
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
package info.nightscout.androidaps.plugins.IobCobCalculator;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.Process;
|
||||
import android.os.SystemClock;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.util.LongSparseArray;
|
||||
|
||||
|
@ -24,16 +22,16 @@ import info.nightscout.androidaps.data.IobTotal;
|
|||
import info.nightscout.androidaps.data.Profile;
|
||||
import info.nightscout.androidaps.db.BgReading;
|
||||
import info.nightscout.androidaps.db.TemporaryBasal;
|
||||
import info.nightscout.androidaps.db.Treatment;
|
||||
import info.nightscout.androidaps.events.EventAppInitialized;
|
||||
import info.nightscout.androidaps.events.EventConfigBuilderChange;
|
||||
import info.nightscout.androidaps.events.EventNewBG;
|
||||
import info.nightscout.androidaps.events.EventNewBasalProfile;
|
||||
import info.nightscout.androidaps.events.EventPreferenceChange;
|
||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventAutosensCalculationFinished;
|
||||
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventNewHistoryData;
|
||||
import info.nightscout.androidaps.plugins.OpenAPSSMB.OpenAPSSMBPlugin;
|
||||
import info.nightscout.utils.DateUtil;
|
||||
|
||||
/**
|
||||
* Created by mike on 24.04.2017.
|
||||
|
@ -51,10 +49,10 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
|||
|
||||
private static double dia = Constants.defaultDIA;
|
||||
|
||||
private static Handler sHandler = null;
|
||||
private static HandlerThread sHandlerThread = null;
|
||||
static final Object dataLock = new Object();
|
||||
|
||||
private static final Object dataLock = new Object();
|
||||
boolean stopCalculationTrigger = false;
|
||||
IobCobThread thread = null;
|
||||
|
||||
private static IobCobCalculatorPlugin plugin = null;
|
||||
|
||||
|
@ -134,12 +132,6 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
|||
|
||||
IobCobCalculatorPlugin() {
|
||||
MainApp.bus().register(this);
|
||||
if (sHandlerThread == null) {
|
||||
sHandlerThread = new HandlerThread(IobCobCalculatorPlugin.class.getSimpleName(), Process.THREAD_PRIORITY_LOWEST);
|
||||
sHandlerThread.start();
|
||||
sHandler = new Handler(sHandlerThread.getLooper());
|
||||
}
|
||||
onNewBg(new EventNewBG());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
@ -176,15 +168,10 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
|||
return rouded;
|
||||
}
|
||||
|
||||
private void loadBgData() {
|
||||
//log.debug("Locking loadBgData");
|
||||
synchronized (dataLock) {
|
||||
onNewProfile(null);
|
||||
void loadBgData() {
|
||||
bgReadings = MainApp.getDbHelper().getBgreadingsDataFromTime((long) (System.currentTimeMillis() - 60 * 60 * 1000L * (24 + dia)), false);
|
||||
log.debug("BG data loaded. Size: " + bgReadings.size());
|
||||
}
|
||||
//log.debug("Releasing loadBgData");
|
||||
}
|
||||
|
||||
private boolean isAbout5minData() {
|
||||
synchronized (dataLock) {
|
||||
|
@ -210,7 +197,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
|||
}
|
||||
}
|
||||
|
||||
private void createBucketedData() {
|
||||
void createBucketedData() {
|
||||
if (isAbout5minData())
|
||||
createBucketedData5min();
|
||||
else
|
||||
|
@ -242,7 +229,6 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
|||
}
|
||||
|
||||
private void createBucketedDataRecalculated() {
|
||||
synchronized (dataLock) {
|
||||
if (bgReadings == null || bgReadings.size() < 3) {
|
||||
bucketed_data = null;
|
||||
return;
|
||||
|
@ -272,12 +258,9 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
|||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void createBucketedData5min() {
|
||||
//log.debug("Locking createBucketedData");
|
||||
synchronized (dataLock) {
|
||||
if (bgReadings == null || bgReadings.size() < 3) {
|
||||
bucketed_data = null;
|
||||
return;
|
||||
|
@ -338,163 +321,6 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
|||
}
|
||||
log.debug("Bucketed data created. Size: " + bucketed_data.size());
|
||||
}
|
||||
//log.debug("Releasing createBucketedData");
|
||||
}
|
||||
|
||||
private void calculateSensitivityData() {
|
||||
if (MainApp.getConfigBuilder() == null)
|
||||
return; // app still initializing
|
||||
if (MainApp.getConfigBuilder().getProfile() == null)
|
||||
return; // app still initializing
|
||||
//log.debug("Locking calculateSensitivityData");
|
||||
long oldestTimeWithData = oldestDataAvailable();
|
||||
|
||||
synchronized (dataLock) {
|
||||
|
||||
if (bucketed_data == null || bucketed_data.size() < 3) {
|
||||
log.debug("calculateSensitivityData: No bucketed data available");
|
||||
return;
|
||||
}
|
||||
|
||||
long prevDataTime = roundUpTime(bucketed_data.get(bucketed_data.size() - 3).date);
|
||||
log.debug("Prev data time: " + new Date(prevDataTime).toLocaleString());
|
||||
AutosensData previous = autosensDataTable.get(prevDataTime);
|
||||
|
||||
// start from oldest to be able sub cob
|
||||
for (int i = bucketed_data.size() - 4; i >= 0; i--) {
|
||||
// check if data already exists
|
||||
long bgTime = bucketed_data.get(i).date;
|
||||
bgTime = roundUpTime(bgTime);
|
||||
if (bgTime > System.currentTimeMillis())
|
||||
continue;
|
||||
Profile profile = MainApp.getConfigBuilder().getProfile(bgTime);
|
||||
|
||||
AutosensData existing;
|
||||
if ((existing = autosensDataTable.get(bgTime)) != null) {
|
||||
previous = existing;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (profile.getIsf(bgTime) == null)
|
||||
return; // profile not set yet
|
||||
|
||||
double sens = Profile.toMgdl(profile.getIsf(bgTime), profile.getUnits());
|
||||
|
||||
AutosensData autosensData = new AutosensData();
|
||||
autosensData.time = bgTime;
|
||||
if (previous != null)
|
||||
autosensData.activeCarbsList = new ArrayList<>(previous.activeCarbsList);
|
||||
else
|
||||
autosensData.activeCarbsList = new ArrayList<>();
|
||||
|
||||
//console.error(bgTime , bucketed_data[i].glucose);
|
||||
|
||||
double bg = bucketed_data.get(i).value;
|
||||
if (bg < 39 || bucketed_data.get(i + 3).value < 39) {
|
||||
log.error("! value < 39");
|
||||
continue;
|
||||
}
|
||||
double avgDelta = (bg - bucketed_data.get(i + 3).value) / 3;
|
||||
double delta = (bg - bucketed_data.get(i + 1).value);
|
||||
|
||||
IobTotal iob = calculateFromTreatmentsAndTemps(bgTime);
|
||||
|
||||
double bgi = -iob.activity * sens * 5;
|
||||
double deviation = delta - bgi;
|
||||
double avgDeviation = Math.round((avgDelta - bgi) * 1000) / 1000;
|
||||
|
||||
double currentDeviation;
|
||||
double slopeFromMaxDeviation = 0;
|
||||
double slopeFromMinDeviation = 999;
|
||||
double maxDeviation = 0;
|
||||
double minDeviation = 999;
|
||||
|
||||
// https://github.com/openaps/oref0/blob/master/lib/determine-basal/cob-autosens.js#L169
|
||||
if (i < bucketed_data.size() - 16) { // we need 1h of data to calculate minDeviationSlope
|
||||
long hourago = bgTime + 10 * 1000 - 60 * 60 * 1000L;
|
||||
AutosensData hourAgoData = getAutosensData(hourago);
|
||||
currentDeviation = hourAgoData.avgDeviation;
|
||||
int initialIndex = autosensDataTable.indexOfKey(hourAgoData.time);
|
||||
|
||||
for (int past = 1; past < 12; past++) {
|
||||
AutosensData ad = autosensDataTable.valueAt(initialIndex + past);
|
||||
double deviationSlope = (ad.avgDeviation - currentDeviation) / (ad.time - bgTime) * 1000 * 60 * 5;
|
||||
if (ad.avgDeviation > maxDeviation) {
|
||||
slopeFromMaxDeviation = Math.min(0, deviationSlope);
|
||||
maxDeviation = ad.avgDeviation;
|
||||
}
|
||||
if (avgDeviation < minDeviation) {
|
||||
slopeFromMinDeviation = Math.max(0, deviationSlope);
|
||||
minDeviation = avgDeviation;
|
||||
}
|
||||
|
||||
//if (Config.logAutosensData)
|
||||
// log.debug("Deviations: " + new Date(bgTime) + new Date(ad.time) + " avgDeviation=" + avgDeviation + " deviationSlope=" + deviationSlope + " slopeFromMaxDeviation=" + slopeFromMaxDeviation + " slopeFromMinDeviation=" + slopeFromMinDeviation);
|
||||
}
|
||||
}
|
||||
|
||||
List<Treatment> recentTreatments = MainApp.getConfigBuilder().getTreatments5MinBackFromHistory(bgTime);
|
||||
for (int ir = 0; ir < recentTreatments.size(); ir++) {
|
||||
autosensData.carbsFromBolus += recentTreatments.get(ir).carbs;
|
||||
autosensData.activeCarbsList.add(new AutosensData.CarbsInPast(recentTreatments.get(ir)));
|
||||
}
|
||||
|
||||
|
||||
// if we are absorbing carbs
|
||||
if (previous != null && previous.cob > 0) {
|
||||
// calculate sum of min carb impact from all active treatments
|
||||
double totalMinCarbsImpact = 0d;
|
||||
for (int ii = 0; ii < autosensData.activeCarbsList.size(); ++ii) {
|
||||
AutosensData.CarbsInPast c = autosensData.activeCarbsList.get(ii);
|
||||
totalMinCarbsImpact += c.min5minCarbImpact;
|
||||
}
|
||||
|
||||
// figure out how many carbs that represents
|
||||
// but always assume at least 3mg/dL/5m (default) absorption per active treatment
|
||||
double ci = Math.max(deviation, totalMinCarbsImpact);
|
||||
autosensData.absorbed = ci * profile.getIc(bgTime) / sens;
|
||||
// and add that to the running total carbsAbsorbed
|
||||
autosensData.cob = Math.max(previous.cob - autosensData.absorbed, 0d);
|
||||
autosensData.substractAbosorbedCarbs();
|
||||
}
|
||||
autosensData.removeOldCarbs(bgTime);
|
||||
autosensData.cob += autosensData.carbsFromBolus;
|
||||
autosensData.deviation = deviation;
|
||||
autosensData.bgi = bgi;
|
||||
autosensData.delta = delta;
|
||||
autosensData.avgDelta = avgDelta;
|
||||
autosensData.avgDeviation = avgDeviation;
|
||||
autosensData.slopeFromMaxDeviation = slopeFromMaxDeviation;
|
||||
autosensData.slopeFromMinDeviation = slopeFromMinDeviation;
|
||||
|
||||
// calculate autosens only without COB
|
||||
if (autosensData.cob <= 0) {
|
||||
if (Math.abs(deviation) < Constants.DEVIATION_TO_BE_EQUAL) {
|
||||
autosensData.pastSensitivity += "=";
|
||||
autosensData.nonEqualDeviation = true;
|
||||
} else if (deviation > 0) {
|
||||
autosensData.pastSensitivity += "+";
|
||||
autosensData.nonEqualDeviation = true;
|
||||
} else {
|
||||
autosensData.pastSensitivity += "-";
|
||||
autosensData.nonEqualDeviation = true;
|
||||
}
|
||||
autosensData.nonCarbsDeviation = true;
|
||||
} else {
|
||||
autosensData.pastSensitivity += "C";
|
||||
}
|
||||
//log.debug("TIME: " + new Date(bgTime).toString() + " BG: " + bg + " SENS: " + sens + " DELTA: " + delta + " AVGDELTA: " + avgDelta + " IOB: " + iob.iob + " ACTIVITY: " + iob.activity + " BGI: " + bgi + " DEVIATION: " + deviation);
|
||||
|
||||
previous = autosensData;
|
||||
autosensDataTable.put(bgTime, autosensData);
|
||||
autosensData.autosensRatio = detectSensitivity(oldestTimeWithData, bgTime).ratio;
|
||||
//if (Config.logAutosensData)
|
||||
// log.debug(autosensData.log(bgTime));
|
||||
}
|
||||
}
|
||||
MainApp.bus().post(new EventAutosensCalculationFinished());
|
||||
//log.debug("Releasing calculateSensitivityData");
|
||||
}
|
||||
|
||||
public static long oldestDataAvailable() {
|
||||
long now = System.currentTimeMillis();
|
||||
|
@ -631,11 +457,11 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
|||
return null;
|
||||
}
|
||||
if (data.time < System.currentTimeMillis() - 11 * 60 * 1000) {
|
||||
log.debug("AUTOSENSDATA null: data is old (" + reason + ")");
|
||||
log.debug("AUTOSENSDATA null: data is old (" + reason + ") size()=" + autosensDataTable.size() + " lastdata=" + DateUtil.dateAndTimeString(data.time));
|
||||
return null;
|
||||
} else {
|
||||
if (data == null)
|
||||
log.debug("AUTOSENSDATA null: data == null (" + " " + reason + ")");
|
||||
log.debug("AUTOSENSDATA null: data == null (" + " " + reason + ") size()=" + autosensDataTable.size() + " lastdata=" + DateUtil.dateAndTimeString(data.time));
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
@ -680,7 +506,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
|||
}
|
||||
}
|
||||
|
||||
private static AutosensResult detectSensitivity(long fromTime, long toTime) {
|
||||
static AutosensResult detectSensitivity(long fromTime, long toTime) {
|
||||
return ConfigBuilderPlugin.getActiveSensitivity().detectSensitivity(fromTime, toTime);
|
||||
}
|
||||
|
||||
|
@ -693,15 +519,33 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
|||
}
|
||||
|
||||
@Subscribe
|
||||
public void onNewBg(EventNewBG ev) {
|
||||
sHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
loadBgData();
|
||||
createBucketedData();
|
||||
calculateSensitivityData();
|
||||
public void onEventAppInitialized(EventAppInitialized ev) {
|
||||
runCalculation("onEventAppInitialized", true);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onEventNewBG(EventNewBG ev) {
|
||||
stopCalculation("onEventNewBG");
|
||||
runCalculation("onEventNewBG", true);
|
||||
}
|
||||
|
||||
private void stopCalculation(String from) {
|
||||
if (thread != null && thread.getState() != Thread.State.TERMINATED) {
|
||||
stopCalculationTrigger = true;
|
||||
log.debug("Stopping calculation thread: " + from);
|
||||
while (thread.getState() != Thread.State.TERMINATED) {
|
||||
SystemClock.sleep(100);
|
||||
}
|
||||
log.debug("Calculation thread stopped: " + from);
|
||||
}
|
||||
}
|
||||
|
||||
private void runCalculation(String from, boolean bgDataReload) {
|
||||
log.debug("Starting calculation thread: " + from);
|
||||
if (thread == null || thread.getState() == Thread.State.TERMINATED) {
|
||||
thread = new IobCobThread(this, from, bgDataReload);
|
||||
thread.start();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
|
@ -715,64 +559,53 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
|||
if (ev == null) { // on init no need of reset
|
||||
return;
|
||||
}
|
||||
stopCalculation("onNewProfile");
|
||||
synchronized (dataLock) {
|
||||
log.debug("Invalidating cached data because of new profile. IOB: " + iobTable.size() + " Autosens: " + autosensDataTable.size() + " records");
|
||||
iobTable = new LongSparseArray<>();
|
||||
autosensDataTable = new LongSparseArray<>();
|
||||
}
|
||||
sHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
calculateSensitivityData();
|
||||
}
|
||||
});
|
||||
runCalculation("onNewProfile", false);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onStatusEvent(EventPreferenceChange ev) {
|
||||
public void onEventPreferenceChange(EventPreferenceChange ev) {
|
||||
if (ev.isChanged(R.string.key_openapsama_autosens_period) ||
|
||||
ev.isChanged(R.string.key_age) ||
|
||||
ev.isChanged(R.string.key_absorption_maxtime)
|
||||
) {
|
||||
stopCalculation("onEventPreferenceChange");
|
||||
synchronized (dataLock) {
|
||||
log.debug("Invalidating cached data because of preference change. IOB: " + iobTable.size() + " Autosens: " + autosensDataTable.size() + " records");
|
||||
iobTable = new LongSparseArray<>();
|
||||
autosensDataTable = new LongSparseArray<>();
|
||||
}
|
||||
sHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
calculateSensitivityData();
|
||||
}
|
||||
});
|
||||
runCalculation("onEventPreferenceChange", false);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onStatusEvent(EventConfigBuilderChange ev) {
|
||||
public void onEventConfigBuilderChange(EventConfigBuilderChange ev) {
|
||||
stopCalculation("onEventConfigBuilderChange");
|
||||
synchronized (dataLock) {
|
||||
log.debug("Invalidating cached data because of configuration change. IOB: " + iobTable.size() + " Autosens: " + autosensDataTable.size() + " records");
|
||||
iobTable = new LongSparseArray<>();
|
||||
autosensDataTable = new LongSparseArray<>();
|
||||
}
|
||||
sHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
calculateSensitivityData();
|
||||
}
|
||||
});
|
||||
runCalculation("onEventConfigBuilderChange", false);
|
||||
}
|
||||
|
||||
// When historical data is changed (comming from NS etc) finished calculations after this date must be invalidated
|
||||
@Subscribe
|
||||
public void onNewHistoryData(EventNewHistoryData ev) {
|
||||
public void onEventNewHistoryData(EventNewHistoryData ev) {
|
||||
//log.debug("Locking onNewHistoryData");
|
||||
stopCalculation("onEventNewHistoryData");
|
||||
synchronized (dataLock) {
|
||||
long time = ev.time;
|
||||
// clear up 5 min back for proper COB calculation
|
||||
long time = ev.time - 5 * 60 * 1000L;
|
||||
log.debug("Invalidating cached data to: " + new Date(time).toLocaleString());
|
||||
for (int index = iobTable.size() - 1; index >= 0; index--) {
|
||||
if (iobTable.keyAt(index) > time) {
|
||||
if (Config.logAutosensData)
|
||||
if (Config.logAutosensData)
|
||||
log.debug("Removing from iobTable: " + new Date(iobTable.keyAt(index)).toLocaleString());
|
||||
iobTable.removeAt(index);
|
||||
|
@ -799,12 +632,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
|||
}
|
||||
}
|
||||
}
|
||||
sHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
calculateSensitivityData();
|
||||
}
|
||||
});
|
||||
runCalculation("onEventNewHistoryData", false);
|
||||
//log.debug("Releasing onNewHistoryData");
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,206 @@
|
|||
package info.nightscout.androidaps.plugins.IobCobCalculator;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.PowerManager;
|
||||
import android.support.v4.util.LongSparseArray;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.Constants;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.data.IobTotal;
|
||||
import info.nightscout.androidaps.data.Profile;
|
||||
import info.nightscout.androidaps.db.BgReading;
|
||||
import info.nightscout.androidaps.db.Treatment;
|
||||
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventAutosensCalculationFinished;
|
||||
import info.nightscout.androidaps.queue.QueueThread;
|
||||
|
||||
import static info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin.getBucketedData;
|
||||
import static info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin.oldestDataAvailable;
|
||||
import static info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin.roundUpTime;
|
||||
|
||||
/**
|
||||
* Created by mike on 23.01.2018.
|
||||
*/
|
||||
|
||||
public class IobCobThread extends Thread {
|
||||
private static Logger log = LoggerFactory.getLogger(QueueThread.class);
|
||||
|
||||
private IobCobCalculatorPlugin iobCobCalculatorPlugin;
|
||||
private boolean bgDataReload;
|
||||
private String from;
|
||||
|
||||
private PowerManager.WakeLock mWakeLock;
|
||||
|
||||
public IobCobThread(IobCobCalculatorPlugin plugin, String from, boolean bgDataReload) {
|
||||
super();
|
||||
|
||||
this.iobCobCalculatorPlugin = plugin;
|
||||
this.bgDataReload = bgDataReload;
|
||||
this.from = from;
|
||||
|
||||
PowerManager powerManager = (PowerManager) MainApp.instance().getApplicationContext().getSystemService(Context.POWER_SERVICE);
|
||||
mWakeLock = powerManager.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "iobCobThread");
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void run() {
|
||||
mWakeLock.acquire();
|
||||
try {
|
||||
if (MainApp.getConfigBuilder() == null) {
|
||||
log.debug("Aborting calculation thread (ConfigBuilder not ready): " + from);
|
||||
return; // app still initializing
|
||||
}
|
||||
if (MainApp.getConfigBuilder().getProfile() == null) {
|
||||
log.debug("Aborting calculation thread (No profile): " + from);
|
||||
return; // app still initializing
|
||||
}
|
||||
//log.debug("Locking calculateSensitivityData");
|
||||
|
||||
Object dataLock = iobCobCalculatorPlugin.dataLock;
|
||||
|
||||
long oldestTimeWithData = oldestDataAvailable();
|
||||
|
||||
synchronized (dataLock) {
|
||||
if (bgDataReload) {
|
||||
iobCobCalculatorPlugin.loadBgData();
|
||||
iobCobCalculatorPlugin.createBucketedData();
|
||||
}
|
||||
List<BgReading> bucketed_data = getBucketedData();
|
||||
LongSparseArray<AutosensData> autosensDataTable = iobCobCalculatorPlugin.getAutosensDataTable();
|
||||
|
||||
if (bucketed_data == null || bucketed_data.size() < 3) {
|
||||
log.debug("Aborting calculation thread (No bucketed data available): " + from);
|
||||
return;
|
||||
}
|
||||
|
||||
long prevDataTime = roundUpTime(bucketed_data.get(bucketed_data.size() - 3).date);
|
||||
log.debug("Prev data time: " + new Date(prevDataTime).toLocaleString());
|
||||
AutosensData previous = autosensDataTable.get(prevDataTime);
|
||||
// start from oldest to be able sub cob
|
||||
for (int i = bucketed_data.size() - 4; i >= 0; i--) {
|
||||
if (iobCobCalculatorPlugin.stopCalculationTrigger) {
|
||||
iobCobCalculatorPlugin.stopCalculationTrigger = false;
|
||||
log.debug("Aborting calculation thread (trigger): " + from);
|
||||
return;
|
||||
}
|
||||
// check if data already exists
|
||||
long bgTime = bucketed_data.get(i).date;
|
||||
bgTime = roundUpTime(bgTime);
|
||||
if (bgTime > System.currentTimeMillis())
|
||||
continue;
|
||||
Profile profile = MainApp.getConfigBuilder().getProfile(bgTime);
|
||||
|
||||
AutosensData existing;
|
||||
if ((existing = autosensDataTable.get(bgTime)) != null) {
|
||||
previous = existing;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (profile == null) {
|
||||
log.debug("Aborting calculation thread (no profile): " + from);
|
||||
return; // profile not set yet
|
||||
}
|
||||
|
||||
if (profile.getIsf(bgTime) == null) {
|
||||
log.debug("Aborting calculation thread (no ISF): " + from);
|
||||
return; // profile not set yet
|
||||
}
|
||||
|
||||
if (Config.logAutosensData)
|
||||
log.debug("Processing calculation thread: " + from + " (" + i + "/" + bucketed_data.size() + ")");
|
||||
|
||||
double sens = Profile.toMgdl(profile.getIsf(bgTime), profile.getUnits());
|
||||
|
||||
AutosensData autosensData = new AutosensData();
|
||||
autosensData.time = bgTime;
|
||||
if (previous != null)
|
||||
autosensData.activeCarbsList = new ArrayList<>(previous.activeCarbsList);
|
||||
else
|
||||
autosensData.activeCarbsList = new ArrayList<>();
|
||||
|
||||
//console.error(bgTime , bucketed_data[i].glucose);
|
||||
double bg;
|
||||
double avgDelta;
|
||||
double delta;
|
||||
bg = bucketed_data.get(i).value;
|
||||
if (bg < 39 || bucketed_data.get(i + 3).value < 39) {
|
||||
log.error("! value < 39");
|
||||
continue;
|
||||
}
|
||||
delta = (bg - bucketed_data.get(i + 1).value);
|
||||
|
||||
IobTotal iob = iobCobCalculatorPlugin.calculateFromTreatmentsAndTemps(bgTime);
|
||||
|
||||
double bgi = -iob.activity * sens * 5;
|
||||
double deviation = delta - bgi;
|
||||
|
||||
List<Treatment> recentTreatments = MainApp.getConfigBuilder().getTreatments5MinBackFromHistory(bgTime);
|
||||
for (int ir = 0; ir < recentTreatments.size(); ir++) {
|
||||
autosensData.carbsFromBolus += recentTreatments.get(ir).carbs;
|
||||
autosensData.activeCarbsList.add(new AutosensData.CarbsInPast(recentTreatments.get(ir)));
|
||||
}
|
||||
|
||||
|
||||
// if we are absorbing carbs
|
||||
if (previous != null && previous.cob > 0) {
|
||||
// calculate sum of min carb impact from all active treatments
|
||||
double totalMinCarbsImpact = 0d;
|
||||
for (int ii = 0; ii < autosensData.activeCarbsList.size(); ++ii) {
|
||||
AutosensData.CarbsInPast c = autosensData.activeCarbsList.get(ii);
|
||||
totalMinCarbsImpact += c.min5minCarbImpact;
|
||||
}
|
||||
|
||||
// figure out how many carbs that represents
|
||||
// but always assume at least 3mg/dL/5m (default) absorption per active treatment
|
||||
double ci = Math.max(deviation, totalMinCarbsImpact);
|
||||
autosensData.absorbed = ci * profile.getIc(bgTime) / sens;
|
||||
// and add that to the running total carbsAbsorbed
|
||||
autosensData.cob = Math.max(previous.cob - autosensData.absorbed, 0d);
|
||||
autosensData.substractAbosorbedCarbs();
|
||||
}
|
||||
autosensData.removeOldCarbs(bgTime);
|
||||
autosensData.cob += autosensData.carbsFromBolus;
|
||||
autosensData.deviation = deviation;
|
||||
autosensData.bgi = bgi;
|
||||
autosensData.delta = delta;
|
||||
|
||||
// calculate autosens only without COB
|
||||
if (autosensData.cob <= 0) {
|
||||
if (Math.abs(deviation) < Constants.DEVIATION_TO_BE_EQUAL) {
|
||||
autosensData.pastSensitivity += "=";
|
||||
autosensData.nonEqualDeviation = true;
|
||||
} else if (deviation > 0) {
|
||||
autosensData.pastSensitivity += "+";
|
||||
autosensData.nonEqualDeviation = true;
|
||||
} else {
|
||||
autosensData.pastSensitivity += "-";
|
||||
autosensData.nonEqualDeviation = true;
|
||||
}
|
||||
autosensData.nonCarbsDeviation = true;
|
||||
} else {
|
||||
autosensData.pastSensitivity += "C";
|
||||
}
|
||||
//log.debug("TIME: " + new Date(bgTime).toString() + " BG: " + bg + " SENS: " + sens + " DELTA: " + delta + " AVGDELTA: " + avgDelta + " IOB: " + iob.iob + " ACTIVITY: " + iob.activity + " BGI: " + bgi + " DEVIATION: " + deviation);
|
||||
|
||||
previous = autosensData;
|
||||
autosensDataTable.put(bgTime, autosensData);
|
||||
autosensData.autosensRatio = iobCobCalculatorPlugin.detectSensitivity(oldestTimeWithData, bgTime).ratio;
|
||||
if (Config.logAutosensData)
|
||||
log.debug(autosensData.log(bgTime));
|
||||
}
|
||||
}
|
||||
MainApp.bus().post(new EventAutosensCalculationFinished());
|
||||
log.debug("Finishing calculation thread: " + from);
|
||||
} finally {
|
||||
mWakeLock.release();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -6,7 +6,7 @@ import android.app.PendingIntent;
|
|||
import android.app.TaskStackBuilder;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.support.v7.app.NotificationCompat;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
|
||||
import com.crashlytics.android.answers.Answers;
|
||||
import com.crashlytics.android.answers.CustomEvent;
|
||||
|
|
|
@ -159,6 +159,7 @@ public class NewTreatmentDialog extends DialogFragment implements OnClickListene
|
|||
detailedBolusInfo.carbs = finalCarbsAfterConstraints;
|
||||
detailedBolusInfo.context = context;
|
||||
detailedBolusInfo.source = Source.USER;
|
||||
if (detailedBolusInfo.insulin > 0 || ConfigBuilderPlugin.getActivePump().getPumpDescription().storesCarbInfo) {
|
||||
ConfigBuilderPlugin.getCommandQueue().bolus(detailedBolusInfo, new Callback() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
@ -172,6 +173,9 @@ public class NewTreatmentDialog extends DialogFragment implements OnClickListene
|
|||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
MainApp.getConfigBuilder().addToHistoryTreatment(detailedBolusInfo);
|
||||
}
|
||||
Answers.getInstance().logCustom(new CustomEvent("Bolus"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -365,6 +365,7 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com
|
|||
detailedBolusInfo.carbTime = carbTime;
|
||||
detailedBolusInfo.boluscalc = boluscalcJSON;
|
||||
detailedBolusInfo.source = Source.USER;
|
||||
if (detailedBolusInfo.insulin > 0 || ConfigBuilderPlugin.getActivePump().getPumpDescription().storesCarbInfo) {
|
||||
ConfigBuilderPlugin.getCommandQueue().bolus(detailedBolusInfo, new Callback() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
@ -378,6 +379,9 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com
|
|||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
MainApp.getConfigBuilder().addToHistoryTreatment(detailedBolusInfo);
|
||||
}
|
||||
Answers.getInstance().logCustom(new CustomEvent("Wizard"));
|
||||
}
|
||||
}
|
||||
|
@ -528,12 +532,12 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com
|
|||
if (calculatedTotalInsulin > 0d || calculatedCarbs > 0d) {
|
||||
String insulinText = calculatedTotalInsulin > 0d ? (DecimalFormatter.to2Decimal(calculatedTotalInsulin) + "U") : "";
|
||||
String carbsText = calculatedCarbs > 0d ? (DecimalFormatter.to0Decimal(calculatedCarbs) + "g") : "";
|
||||
total.setText(getString(R.string.result) + ": " + insulinText + " " + carbsText);
|
||||
total.setText(MainApp.gs(R.string.result) + ": " + insulinText + " " + carbsText);
|
||||
okButton.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
// TODO this should also be run when loading the dialog as the OK button is initially visible
|
||||
// but does nothing if neither carbs nor insulin is > 0
|
||||
total.setText(getString(R.string.missing) + " " + DecimalFormatter.to0Decimal(wizard.carbsEquivalent) + "g");
|
||||
total.setText(MainApp.gs(R.string.missing) + " " + DecimalFormatter.to0Decimal(wizard.carbsEquivalent) + "g");
|
||||
okButton.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
|
|
|
@ -147,12 +147,18 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
|
|||
TextView sage;
|
||||
TextView pbage;
|
||||
|
||||
CheckBox showPredictionView;
|
||||
CheckBox showBasalsView;
|
||||
CheckBox showIobView;
|
||||
CheckBox showCobView;
|
||||
CheckBox showDeviationsView;
|
||||
CheckBox showRatiosView;
|
||||
TextView showPredictionLabel;
|
||||
CheckBox showPredictionCheckbox;
|
||||
TextView showBasalsLabel;
|
||||
CheckBox showBasalsCheckbox;
|
||||
TextView showIobLabel;
|
||||
CheckBox showIobCheckbox;
|
||||
TextView showCobLabel;
|
||||
CheckBox showCobCheckbox;
|
||||
TextView showDeviationsLabel;
|
||||
CheckBox showDeviationsCheckbox;
|
||||
TextView showRatiosLabel;
|
||||
CheckBox showRatiosCheckbox;
|
||||
|
||||
RecyclerView notificationsView;
|
||||
LinearLayoutManager llm;
|
||||
|
@ -264,24 +270,37 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
|
|||
|
||||
acceptTempLayout = (LinearLayout) view.findViewById(R.id.overview_accepttemplayout);
|
||||
|
||||
showPredictionView = (CheckBox) view.findViewById(R.id.overview_showprediction);
|
||||
showBasalsView = (CheckBox) view.findViewById(R.id.overview_showbasals);
|
||||
showIobView = (CheckBox) view.findViewById(R.id.overview_showiob);
|
||||
showCobView = (CheckBox) view.findViewById(R.id.overview_showcob);
|
||||
showDeviationsView = (CheckBox) view.findViewById(R.id.overview_showdeviations);
|
||||
showRatiosView = (CheckBox) view.findViewById(R.id.overview_showratios);
|
||||
showPredictionView.setChecked(SP.getBoolean("showprediction", false));
|
||||
showBasalsView.setChecked(SP.getBoolean("showbasals", true));
|
||||
showIobView.setChecked(SP.getBoolean("showiob", false));
|
||||
showCobView.setChecked(SP.getBoolean("showcob", false));
|
||||
showDeviationsView.setChecked(SP.getBoolean("showdeviations", false));
|
||||
showRatiosView.setChecked(SP.getBoolean("showratios", false));
|
||||
showPredictionView.setOnCheckedChangeListener(this);
|
||||
showBasalsView.setOnCheckedChangeListener(this);
|
||||
showIobView.setOnCheckedChangeListener(this);
|
||||
showCobView.setOnCheckedChangeListener(this);
|
||||
showDeviationsView.setOnCheckedChangeListener(this);
|
||||
showRatiosView.setOnCheckedChangeListener(this);
|
||||
showPredictionCheckbox = (CheckBox) view.findViewById(R.id.overview_showprediction);
|
||||
showBasalsCheckbox = (CheckBox) view.findViewById(R.id.overview_showbasals);
|
||||
showIobCheckbox = (CheckBox) view.findViewById(R.id.overview_showiob);
|
||||
showCobCheckbox = (CheckBox) view.findViewById(R.id.overview_showcob);
|
||||
showDeviationsCheckbox = (CheckBox) view.findViewById(R.id.overview_showdeviations);
|
||||
showRatiosCheckbox = (CheckBox) view.findViewById(R.id.overview_showratios);
|
||||
showPredictionCheckbox.setChecked(SP.getBoolean("showprediction", false));
|
||||
showBasalsCheckbox.setChecked(SP.getBoolean("showbasals", true));
|
||||
showIobCheckbox.setChecked(SP.getBoolean("showiob", false));
|
||||
showCobCheckbox.setChecked(SP.getBoolean("showcob", false));
|
||||
showDeviationsCheckbox.setChecked(SP.getBoolean("showdeviations", false));
|
||||
showRatiosCheckbox.setChecked(SP.getBoolean("showratios", false));
|
||||
showPredictionCheckbox.setOnCheckedChangeListener(this);
|
||||
showBasalsCheckbox.setOnCheckedChangeListener(this);
|
||||
showIobCheckbox.setOnCheckedChangeListener(this);
|
||||
showCobCheckbox.setOnCheckedChangeListener(this);
|
||||
showDeviationsCheckbox.setOnCheckedChangeListener(this);
|
||||
showRatiosCheckbox.setOnCheckedChangeListener(this);
|
||||
|
||||
showPredictionLabel = (TextView) view.findViewById(R.id.overview_showprediction_label);
|
||||
showPredictionLabel.setOnClickListener(this);
|
||||
showBasalsLabel = (TextView) view.findViewById(R.id.overview_showbasals_label);
|
||||
showBasalsLabel.setOnClickListener(this);
|
||||
showIobLabel = (TextView) view.findViewById(R.id.overview_showiob_label);
|
||||
showIobLabel.setOnClickListener(this);
|
||||
showCobLabel = (TextView) view.findViewById(R.id.overview_showcob_label);
|
||||
showCobLabel.setOnClickListener(this);
|
||||
showDeviationsLabel = (TextView) view.findViewById(R.id.overview_showdeviations_label);
|
||||
showDeviationsLabel.setOnClickListener(this);
|
||||
showRatiosLabel = (TextView) view.findViewById(R.id.overview_showratios_label);
|
||||
showRatiosLabel.setOnClickListener(this);
|
||||
|
||||
notificationsView = (RecyclerView) view.findViewById(R.id.overview_notifications);
|
||||
notificationsView.setHasFixedSize(true);
|
||||
|
@ -374,24 +393,24 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
|
|||
case R.id.overview_showiob:
|
||||
break;
|
||||
case R.id.overview_showcob:
|
||||
showDeviationsView.setOnCheckedChangeListener(null);
|
||||
showDeviationsView.setChecked(false);
|
||||
showDeviationsView.setOnCheckedChangeListener(this);
|
||||
showDeviationsCheckbox.setOnCheckedChangeListener(null);
|
||||
showDeviationsCheckbox.setChecked(false);
|
||||
showDeviationsCheckbox.setOnCheckedChangeListener(this);
|
||||
break;
|
||||
case R.id.overview_showdeviations:
|
||||
showCobView.setOnCheckedChangeListener(null);
|
||||
showCobView.setChecked(false);
|
||||
showCobView.setOnCheckedChangeListener(this);
|
||||
showCobCheckbox.setOnCheckedChangeListener(null);
|
||||
showCobCheckbox.setChecked(false);
|
||||
showCobCheckbox.setOnCheckedChangeListener(this);
|
||||
break;
|
||||
case R.id.overview_showratios:
|
||||
break;
|
||||
}
|
||||
SP.putBoolean("showiob", showIobView.isChecked());
|
||||
SP.putBoolean("showprediction", showPredictionView.isChecked());
|
||||
SP.putBoolean("showbasals", showBasalsView.isChecked());
|
||||
SP.putBoolean("showcob", showCobView.isChecked());
|
||||
SP.putBoolean("showdeviations", showDeviationsView.isChecked());
|
||||
SP.putBoolean("showratios", showRatiosView.isChecked());
|
||||
SP.putBoolean("showiob", showIobCheckbox.isChecked());
|
||||
SP.putBoolean("showprediction", showPredictionCheckbox.isChecked());
|
||||
SP.putBoolean("showbasals", showBasalsCheckbox.isChecked());
|
||||
SP.putBoolean("showcob", showCobCheckbox.isChecked());
|
||||
SP.putBoolean("showdeviations", showDeviationsCheckbox.isChecked());
|
||||
SP.putBoolean("showratios", showRatiosCheckbox.isChecked());
|
||||
scheduleUpdateGUI("onGraphCheckboxesCheckedChanged");
|
||||
}
|
||||
|
||||
|
@ -496,6 +515,16 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
|
|||
}
|
||||
}
|
||||
});
|
||||
if (MainApp.getConfigBuilder().getActivePump().getPumpDescription().isExtendedBolusCapable && MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) {
|
||||
ConfigBuilderPlugin.getCommandQueue().cancelExtended( new Callback() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!result.success) {
|
||||
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.extendedbolusdeliveryerror));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
NSUpload.uploadOpenAPSOffline(30);
|
||||
return true;
|
||||
} else if (item.getTitle().equals(MainApp.sResources.getString(R.string.disconnectpumpfor1h))) {
|
||||
|
@ -509,6 +538,16 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
|
|||
}
|
||||
}
|
||||
});
|
||||
if (MainApp.getConfigBuilder().getActivePump().getPumpDescription().isExtendedBolusCapable && MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) {
|
||||
ConfigBuilderPlugin.getCommandQueue().cancelExtended( new Callback() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!result.success) {
|
||||
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.extendedbolusdeliveryerror));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
NSUpload.uploadOpenAPSOffline(60);
|
||||
return true;
|
||||
} else if (item.getTitle().equals(MainApp.sResources.getString(R.string.disconnectpumpfor2h))) {
|
||||
|
@ -522,6 +561,16 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
|
|||
}
|
||||
}
|
||||
});
|
||||
if (MainApp.getConfigBuilder().getActivePump().getPumpDescription().isExtendedBolusCapable && MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) {
|
||||
ConfigBuilderPlugin.getCommandQueue().cancelExtended( new Callback() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!result.success) {
|
||||
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.extendedbolusdeliveryerror));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
NSUpload.uploadOpenAPSOffline(120);
|
||||
return true;
|
||||
} else if (item.getTitle().equals(MainApp.sResources.getString(R.string.disconnectpumpfor3h))) {
|
||||
|
@ -535,6 +584,16 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
|
|||
}
|
||||
}
|
||||
});
|
||||
if (MainApp.getConfigBuilder().getActivePump().getPumpDescription().isExtendedBolusCapable && MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) {
|
||||
ConfigBuilderPlugin.getCommandQueue().cancelExtended( new Callback() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!result.success) {
|
||||
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.extendedbolusdeliveryerror));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
NSUpload.uploadOpenAPSOffline(180);
|
||||
return true;
|
||||
} else if (item.getTitle().equals(MainApp.sResources.getString(R.string.careportal_profileswitch))) {
|
||||
|
@ -578,6 +637,24 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
|
|||
if (ConfigBuilderPlugin.getActivePump().isSuspended() || !ConfigBuilderPlugin.getActivePump().isInitialized())
|
||||
ConfigBuilderPlugin.getCommandQueue().readStatus("RefreshClicked", null);
|
||||
break;
|
||||
case R.id.overview_showprediction_label:
|
||||
showPredictionCheckbox.toggle();
|
||||
break;
|
||||
case R.id.overview_showbasals_label:
|
||||
showBasalsCheckbox.toggle();
|
||||
break;
|
||||
case R.id.overview_showiob_label:
|
||||
showIobCheckbox.toggle();
|
||||
break;
|
||||
case R.id.overview_showcob_label:
|
||||
showCobCheckbox.toggle();
|
||||
break;
|
||||
case R.id.overview_showdeviations_label:
|
||||
showDeviationsCheckbox.toggle();
|
||||
break;
|
||||
case R.id.overview_showratios_label:
|
||||
showRatiosCheckbox.toggle();
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1208,11 +1285,11 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
|
|||
|
||||
final boolean predictionsAvailable = finalLastRun != null && finalLastRun.request.hasPredictions;
|
||||
if (predictionsAvailable) {
|
||||
showPredictionView.setVisibility(View.VISIBLE);
|
||||
getActivity().findViewById(R.id.overview_showprediction_label).setVisibility(View.VISIBLE);
|
||||
showPredictionCheckbox.setVisibility(View.VISIBLE);
|
||||
showPredictionLabel.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
showPredictionView.setVisibility(View.GONE);
|
||||
getActivity().findViewById(R.id.overview_showprediction_label).setVisibility(View.GONE);
|
||||
showPredictionCheckbox.setVisibility(View.GONE);
|
||||
showPredictionLabel.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
// pump status from ns
|
||||
|
@ -1265,7 +1342,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
|
|||
final long toTime;
|
||||
final long fromTime;
|
||||
final long endTime;
|
||||
if (predictionsAvailable && showPredictionView.isChecked()) {
|
||||
if (predictionsAvailable && showPredictionCheckbox.isChecked()) {
|
||||
int predHours = (int) (Math.ceil(finalLastRun.constraintsProcessed.getLatestPredictionsTime() - System.currentTimeMillis()) / (60 * 60 * 1000));
|
||||
predHours = Math.min(2, predHours);
|
||||
predHours = Math.max(0, predHours);
|
||||
|
@ -1292,7 +1369,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
|
|||
graphData.addInRangeArea(fromTime, endTime, lowLine, highLine);
|
||||
|
||||
// **** BG ****
|
||||
if (predictionsAvailable && showPredictionView.isChecked())
|
||||
if (predictionsAvailable && showPredictionCheckbox.isChecked())
|
||||
graphData.addBgReadings(fromTime, toTime, lowLine, highLine, finalLastRun.constraintsProcessed);
|
||||
else
|
||||
graphData.addBgReadings(fromTime, toTime, lowLine, highLine, null);
|
||||
|
@ -1304,7 +1381,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
|
|||
graphData.addTreatments(fromTime, endTime);
|
||||
|
||||
// add basal data
|
||||
if (pump.getPumpDescription().isTempBasalCapable && showBasalsView.isChecked()) {
|
||||
if (pump.getPumpDescription().isTempBasalCapable && showBasalsCheckbox.isChecked()) {
|
||||
graphData.addBasals(fromTime, now, lowLine / graphData.maxY / 1.2d);
|
||||
}
|
||||
|
||||
|
@ -1322,25 +1399,25 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
|
|||
boolean useRatioForScale = false;
|
||||
boolean useDSForScale = false;
|
||||
|
||||
if (showIobView.isChecked()) {
|
||||
if (showIobCheckbox.isChecked()) {
|
||||
useIobForScale = true;
|
||||
} else if (showCobView.isChecked()) {
|
||||
} else if (showCobCheckbox.isChecked()) {
|
||||
useCobForScale = true;
|
||||
} else if (showDeviationsView.isChecked()) {
|
||||
} else if (showDeviationsCheckbox.isChecked()) {
|
||||
useDevForScale = true;
|
||||
} else if (showRatiosView.isChecked()) {
|
||||
} else if (showRatiosCheckbox.isChecked()) {
|
||||
useRatioForScale = true;
|
||||
} else if (Config.displayDeviationSlope) {
|
||||
useDSForScale = true;
|
||||
}
|
||||
|
||||
if (showIobView.isChecked())
|
||||
if (showIobCheckbox.isChecked())
|
||||
secondGraphData.addIob(fromTime, now, useIobForScale, 1d);
|
||||
if (showCobView.isChecked())
|
||||
if (showCobCheckbox.isChecked())
|
||||
secondGraphData.addCob(fromTime, now, useCobForScale, useCobForScale ? 1d : 0.5d);
|
||||
if (showDeviationsView.isChecked())
|
||||
if (showDeviationsCheckbox.isChecked())
|
||||
secondGraphData.addDeviations(fromTime, now, useDevForScale, 1d);
|
||||
if (showRatiosView.isChecked())
|
||||
if (showRatiosCheckbox.isChecked())
|
||||
secondGraphData.addRatio(fromTime, now, useRatioForScale, 1d);
|
||||
if (Config.displayDeviationSlope)
|
||||
secondGraphData.addDeviationSlope(fromTime, now, useDSForScale, 1d);
|
||||
|
@ -1356,7 +1433,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
|
|||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (showIobView.isChecked() || showCobView.isChecked() || showDeviationsView.isChecked() || showRatiosView.isChecked() || Config.displayDeviationSlope) {
|
||||
if (showIobCheckbox.isChecked() || showCobCheckbox.isChecked() || showDeviationsCheckbox.isChecked() || showRatiosCheckbox.isChecked() || Config.displayDeviationSlope) {
|
||||
iobGraph.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
iobGraph.setVisibility(View.GONE);
|
||||
|
|
|
@ -250,7 +250,7 @@ public class GraphData {
|
|||
}
|
||||
|
||||
// Careportal
|
||||
List<CareportalEvent> careportalEvents = MainApp.getDbHelper().getCareportalEventsFromTime(fromTime, true);
|
||||
List<CareportalEvent> careportalEvents = MainApp.getDbHelper().getCareportalEventsFromTime(fromTime - 6 * 60 * 60 * 1000, true);
|
||||
|
||||
for (int tx = 0; tx < careportalEvents.size(); tx++) {
|
||||
DataPointWithLabelInterface t = careportalEvents.get(tx);
|
||||
|
|
|
@ -136,9 +136,6 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
|
|||
Iterator<E> values = getValues(minX, maxX);
|
||||
|
||||
// draw background
|
||||
double lastEndY = 0;
|
||||
double lastEndX = 0;
|
||||
|
||||
// draw data
|
||||
|
||||
double diffY = maxY - minY;
|
||||
|
@ -149,9 +146,8 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
|
|||
float graphLeft = graphView.getGraphContentLeft();
|
||||
float graphTop = graphView.getGraphContentTop();
|
||||
|
||||
lastEndY = 0;
|
||||
lastEndX = 0;
|
||||
float firstX = 0;
|
||||
float scaleX = (float) (graphWidth / diffX);
|
||||
|
||||
int i=0;
|
||||
while (values.hasNext()) {
|
||||
E value = values.next();
|
||||
|
@ -166,9 +162,6 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
|
|||
double ratX = valX / diffX;
|
||||
double x = graphWidth * ratX;
|
||||
|
||||
double orgX = x;
|
||||
double orgY = y;
|
||||
|
||||
// overdraw
|
||||
boolean overdraw = false;
|
||||
if (x > graphWidth) { // end right
|
||||
|
@ -180,6 +173,14 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
|
|||
if (y > graphHeight) { // end top
|
||||
overdraw = true;
|
||||
}
|
||||
|
||||
long duration = value.getDuration();
|
||||
float endWithDuration = (float) (x + duration * scaleX + graphLeft + 1);
|
||||
// cut off to graph start if needed
|
||||
if (x < 0 && endWithDuration > 0) {
|
||||
x = 0;
|
||||
}
|
||||
|
||||
/* Fix a bug that continue to show the DOT after Y axis */
|
||||
if(x < 0) {
|
||||
overdraw = true;
|
||||
|
@ -190,8 +191,8 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
|
|||
registerDataPoint(endX, endY, value);
|
||||
|
||||
float xpluslength = 0;
|
||||
if (value.getDuration() > 0) {
|
||||
xpluslength = endX + Math.min((float) (value.getDuration() * graphWidth / diffX), graphLeft + graphWidth);
|
||||
if (duration > 0) {
|
||||
xpluslength = Math.min(endWithDuration, graphLeft + graphWidth);
|
||||
}
|
||||
|
||||
// draw data point
|
||||
|
|
|
@ -7,7 +7,7 @@ import android.content.Intent;
|
|||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.support.v4.app.TaskStackBuilder;
|
||||
import android.support.v7.app.NotificationCompat;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
|
||||
import com.squareup.otto.Subscribe;
|
||||
|
||||
|
|
|
@ -110,6 +110,8 @@ public class DanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, C
|
|||
pumpDescription.basalMinimumRate = 0.04d;
|
||||
|
||||
pumpDescription.isRefillingCapable = true;
|
||||
|
||||
pumpDescription.storesCarbInfo = true;
|
||||
}
|
||||
|
||||
private ServiceConnection mConnection = new ServiceConnection() {
|
||||
|
|
|
@ -112,6 +112,8 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, DanaRInterf
|
|||
pumpDescription.basalMinimumRate = 0.1d;
|
||||
|
||||
pumpDescription.isRefillingCapable = true;
|
||||
|
||||
pumpDescription.storesCarbInfo = true;
|
||||
}
|
||||
|
||||
private ServiceConnection mConnection = new ServiceConnection() {
|
||||
|
|
|
@ -189,6 +189,8 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface,
|
|||
pumpDescription.basalMinimumRate = 0.04d;
|
||||
|
||||
pumpDescription.isRefillingCapable = true;
|
||||
|
||||
pumpDescription.storesCarbInfo = true;
|
||||
}
|
||||
|
||||
private ServiceConnection mConnection = new ServiceConnection() {
|
||||
|
|
|
@ -9,6 +9,7 @@ import java.util.Calendar;
|
|||
import java.util.GregorianCalendar;
|
||||
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.utils.DateUtil;
|
||||
|
||||
public class DanaRS_Packet_APS_Set_Event_History extends DanaRS_Packet {
|
||||
private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_APS_Set_Event_History.class);
|
||||
|
@ -30,6 +31,8 @@ public class DanaRS_Packet_APS_Set_Event_History extends DanaRS_Packet {
|
|||
this.time = time;
|
||||
this.param1 = param1;
|
||||
this.param2 = param2;
|
||||
if (Config.logDanaMessageDetail)
|
||||
log.debug("Set history entry: " + DateUtil.dateAndTimeString(time) + " type: " + type + " param1: " + param1 + " param2: " + param2);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -164,6 +164,8 @@ public class BLEComm {
|
|||
scheduledDisconnection = null;
|
||||
|
||||
if ((mBluetoothAdapter == null) || (mBluetoothGatt == null)) {
|
||||
log.debug("disconnect not possible: (mBluetoothAdapter == null) " + (mBluetoothAdapter == null));
|
||||
log.debug("disconnect not possible: (mBluetoothGatt == null) " + (mBluetoothGatt == null));
|
||||
return;
|
||||
}
|
||||
setCharacteristicNotification(getUARTReadBTGattChar(), false);
|
||||
|
@ -257,6 +259,8 @@ public class BLEComm {
|
|||
log.debug("setCharacteristicNotification");
|
||||
if ((mBluetoothAdapter == null) || (mBluetoothGatt == null)) {
|
||||
log.debug("BluetoothAdapter not initialized_ERROR");
|
||||
isConnecting = false;
|
||||
isConnected = false;
|
||||
return;
|
||||
}
|
||||
mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
|
||||
|
@ -266,6 +270,8 @@ public class BLEComm {
|
|||
log.debug("readCharacteristic");
|
||||
if ((mBluetoothAdapter == null) || (mBluetoothGatt == null)) {
|
||||
log.debug("BluetoothAdapter not initialized_ERROR");
|
||||
isConnecting = false;
|
||||
isConnected = false;
|
||||
return;
|
||||
}
|
||||
mBluetoothGatt.readCharacteristic(characteristic);
|
||||
|
@ -274,6 +280,8 @@ public class BLEComm {
|
|||
public void writeCharacteristic_NO_RESPONSE(final BluetoothGattCharacteristic characteristic, final byte[] data) {
|
||||
if ((mBluetoothAdapter == null) || (mBluetoothGatt == null)) {
|
||||
log.debug("BluetoothAdapter not initialized_ERROR");
|
||||
isConnecting = false;
|
||||
isConnected = false;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -306,6 +314,8 @@ public class BLEComm {
|
|||
log.debug("getSupportedGattServices");
|
||||
if ((mBluetoothAdapter == null) || (mBluetoothGatt == null)) {
|
||||
log.debug("BluetoothAdapter not initialized_ERROR");
|
||||
isConnecting = false;
|
||||
isConnected = false;
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -109,6 +109,8 @@ public class DanaRv2Plugin implements PluginBase, PumpInterface, DanaRInterface,
|
|||
pumpDescription.basalMinimumRate = 0.04d;
|
||||
|
||||
pumpDescription.isRefillingCapable = true;
|
||||
|
||||
pumpDescription.storesCarbInfo = true;
|
||||
}
|
||||
|
||||
private ServiceConnection mConnection = new ServiceConnection() {
|
||||
|
|
|
@ -11,6 +11,7 @@ import java.util.Arrays;
|
|||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.data.Profile;
|
||||
|
@ -191,8 +192,10 @@ public class SensitivityAAPSPlugin implements PluginBase, SensitivityInterface{
|
|||
log.debug(ratioLimit);
|
||||
}
|
||||
|
||||
log.debug("Sensitivity to: " + new Date(toTime).toLocaleString() + " percentile: " + percentile + " ratio: " + ratio);
|
||||
if (Config.logAutosensData) {
|
||||
log.debug("Sensitivity to: " + new Date(toTime).toLocaleString() + " percentile: " + percentile + " ratio: " + ratio + " mealCOB: " + current.cob);
|
||||
log.debug("Sensitivity to: deviations " + Arrays.toString(deviations));
|
||||
}
|
||||
|
||||
AutosensResult output = new AutosensResult();
|
||||
output.ratio = Round.roundTo(ratio, 0.01);
|
||||
|
|
|
@ -7,8 +7,10 @@ import org.slf4j.LoggerFactory;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.data.Profile;
|
||||
|
@ -118,7 +120,7 @@ public class SensitivityOref0Plugin implements PluginBase, SensitivityInterface
|
|||
return new AutosensResult();
|
||||
}
|
||||
|
||||
AutosensData current = IobCobCalculatorPlugin.getLastAutosensData("SensitivityOref0"); // this is running inside lock already
|
||||
AutosensData current = IobCobCalculatorPlugin.getAutosensData(toTime); // this is running inside lock already
|
||||
if (current == null) {
|
||||
log.debug("No current autosens data available");
|
||||
return new AutosensResult();
|
||||
|
@ -199,10 +201,8 @@ public class SensitivityOref0Plugin implements PluginBase, SensitivityInterface
|
|||
log.debug(ratioLimit);
|
||||
}
|
||||
|
||||
double newisf = Math.round(Profile.toMgdl(sens, profile.getUnits()) / ratio);
|
||||
if (ratio != 1) {
|
||||
log.debug("ISF adjusted from " + Profile.toMgdl(sens, profile.getUnits()) + " to " + newisf);
|
||||
}
|
||||
if (Config.logAutosensData)
|
||||
log.debug("Sensitivity to: " + new Date(toTime).toLocaleString() + " ratio: " + ratio + " mealCOB: " + current.cob);
|
||||
|
||||
AutosensResult output = new AutosensResult();
|
||||
output.ratio = Round.roundTo(ratio, 0.01);
|
||||
|
|
|
@ -217,7 +217,7 @@ public class SensitivityWeightedAveragePlugin implements PluginBase, Sensitivity
|
|||
}
|
||||
|
||||
if (Config.logAutosensData)
|
||||
log.debug("Sensitivity to: " + new Date(toTime).toLocaleString() + " weightedaverage: " + average + " ratio: " + ratio);
|
||||
log.debug("Sensitivity to: " + new Date(toTime).toLocaleString() + " weightedaverage: " + average + " ratio: " + ratio + " mealCOB: " + current.cob);
|
||||
|
||||
AutosensResult output = new AutosensResult();
|
||||
output.ratio = Round.roundTo(ratio, 0.01);
|
||||
|
|
|
@ -20,6 +20,7 @@ import info.nightscout.androidaps.events.EventExtendedBolusChange;
|
|||
import info.nightscout.androidaps.plugins.Common.SubscriberFragment;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.Treatments.fragments.TreatmentsBolusFragment;
|
||||
import info.nightscout.androidaps.plugins.Treatments.fragments.TreatmentsCareportalFragment;
|
||||
import info.nightscout.androidaps.plugins.Treatments.fragments.TreatmentsExtendedBolusesFragment;
|
||||
import info.nightscout.androidaps.plugins.Treatments.fragments.TreatmentsProfileSwitchFragment;
|
||||
import info.nightscout.androidaps.plugins.Treatments.fragments.TreatmentsTempTargetFragment;
|
||||
|
@ -33,6 +34,7 @@ public class TreatmentsFragment extends SubscriberFragment implements View.OnCli
|
|||
TextView tempBasalsTab;
|
||||
TextView tempTargetTab;
|
||||
TextView profileSwitchTab;
|
||||
TextView careportalTab;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
|
@ -45,11 +47,13 @@ public class TreatmentsFragment extends SubscriberFragment implements View.OnCli
|
|||
tempBasalsTab = (TextView) view.findViewById(R.id.treatments_tempbasals);
|
||||
tempTargetTab = (TextView) view.findViewById(R.id.treatments_temptargets);
|
||||
profileSwitchTab = (TextView) view.findViewById(R.id.treatments_profileswitches);
|
||||
careportalTab = (TextView) view.findViewById(R.id.treatments_careportal);
|
||||
treatmentsTab.setOnClickListener(this);
|
||||
extendedBolusesTab.setOnClickListener(this);
|
||||
tempBasalsTab.setOnClickListener(this);
|
||||
tempTargetTab.setOnClickListener(this);
|
||||
profileSwitchTab.setOnClickListener(this);
|
||||
careportalTab.setOnClickListener(this);
|
||||
|
||||
setFragment(new TreatmentsBolusFragment());
|
||||
setBackgroundColorOnSelected(treatmentsTab);
|
||||
|
@ -87,6 +91,10 @@ public class TreatmentsFragment extends SubscriberFragment implements View.OnCli
|
|||
setFragment(new TreatmentsProfileSwitchFragment());
|
||||
setBackgroundColorOnSelected(profileSwitchTab);
|
||||
break;
|
||||
case R.id.treatments_careportal:
|
||||
setFragment(new TreatmentsCareportalFragment());
|
||||
setBackgroundColorOnSelected(careportalTab);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -104,6 +112,7 @@ public class TreatmentsFragment extends SubscriberFragment implements View.OnCli
|
|||
tempBasalsTab.setBackgroundColor(MainApp.sResources.getColor(R.color.defaultbackground));
|
||||
tempTargetTab.setBackgroundColor(MainApp.sResources.getColor(R.color.defaultbackground));
|
||||
profileSwitchTab.setBackgroundColor(MainApp.sResources.getColor(R.color.defaultbackground));
|
||||
careportalTab.setBackgroundColor(MainApp.sResources.getColor(R.color.defaultbackground));
|
||||
selected.setBackgroundColor(MainApp.sResources.getColor(R.color.tabBgColorSelected));
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,192 @@
|
|||
package info.nightscout.androidaps.plugins.Treatments.fragments;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Paint;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.support.v7.widget.CardView;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.squareup.otto.Subscribe;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.Services.Intents;
|
||||
import info.nightscout.androidaps.db.CareportalEvent;
|
||||
import info.nightscout.androidaps.events.EventCareportalEventChange;
|
||||
import info.nightscout.androidaps.plugins.Common.SubscriberFragment;
|
||||
import info.nightscout.androidaps.plugins.NSClientInternal.UploadQueue;
|
||||
import info.nightscout.utils.DateUtil;
|
||||
import info.nightscout.utils.NSUpload;
|
||||
import info.nightscout.utils.SP;
|
||||
import info.nightscout.utils.Translator;
|
||||
|
||||
/**
|
||||
* Created by mike on 13/01/17.
|
||||
*/
|
||||
|
||||
public class TreatmentsCareportalFragment extends SubscriberFragment implements View.OnClickListener {
|
||||
|
||||
RecyclerView recyclerView;
|
||||
LinearLayoutManager llm;
|
||||
Button refreshFromNS;
|
||||
|
||||
Context context;
|
||||
|
||||
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.CareportalEventsViewHolder> {
|
||||
|
||||
List<CareportalEvent> careportalEventList;
|
||||
|
||||
RecyclerViewAdapter(List<CareportalEvent> careportalEventList) {
|
||||
this.careportalEventList = careportalEventList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CareportalEventsViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
|
||||
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.treatments_careportal_item, viewGroup, false);
|
||||
CareportalEventsViewHolder CareportalEventsViewHolder = new CareportalEventsViewHolder(v);
|
||||
return CareportalEventsViewHolder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(CareportalEventsViewHolder holder, int position) {
|
||||
CareportalEvent careportalEvent = careportalEventList.get(position);
|
||||
holder.ns.setVisibility(NSUpload.isIdValid(careportalEvent._id) ? View.VISIBLE : View.GONE);
|
||||
holder.date.setText(DateUtil.dateAndTimeString(careportalEvent.date));
|
||||
holder.note.setText(careportalEvent.getNotes());
|
||||
holder.type.setText(Translator.translate(careportalEvent.eventType));
|
||||
holder.remove.setTag(careportalEvent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return careportalEventList.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
|
||||
super.onAttachedToRecyclerView(recyclerView);
|
||||
}
|
||||
|
||||
public class CareportalEventsViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
|
||||
CardView cv;
|
||||
TextView date;
|
||||
TextView type;
|
||||
TextView note;
|
||||
TextView remove;
|
||||
TextView ns;
|
||||
|
||||
CareportalEventsViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
cv = (CardView) itemView.findViewById(R.id.careportal_cardview);
|
||||
date = (TextView) itemView.findViewById(R.id.careportal_date);
|
||||
type = (TextView) itemView.findViewById(R.id.careportal_type);
|
||||
note = (TextView) itemView.findViewById(R.id.careportal_note);
|
||||
ns = (TextView) itemView.findViewById(R.id.ns_sign);
|
||||
remove = (TextView) itemView.findViewById(R.id.careportal_remove);
|
||||
remove.setOnClickListener(this);
|
||||
remove.setPaintFlags(remove.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
final CareportalEvent careportalEvent = (CareportalEvent) v.getTag();
|
||||
switch (v.getId()) {
|
||||
case R.id.careportal_remove:
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||
builder.setTitle(MainApp.sResources.getString(R.string.confirmation));
|
||||
builder.setMessage(MainApp.sResources.getString(R.string.removerecord) + "\n" + DateUtil.dateAndTimeString(careportalEvent.date));
|
||||
builder.setPositiveButton(MainApp.sResources.getString(R.string.ok), new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
final String _id = careportalEvent._id;
|
||||
if (NSUpload.isIdValid(_id)) {
|
||||
NSUpload.removeCareportalEntryFromNS(_id);
|
||||
} else {
|
||||
UploadQueue.removeID("dbAdd", _id);
|
||||
}
|
||||
MainApp.getDbHelper().delete(careportalEvent);
|
||||
}
|
||||
});
|
||||
builder.setNegativeButton(MainApp.sResources.getString(R.string.cancel), null);
|
||||
builder.show();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.treatments_careportal_fragment, container, false);
|
||||
|
||||
recyclerView = (RecyclerView) view.findViewById(R.id.careportal_recyclerview);
|
||||
recyclerView.setHasFixedSize(true);
|
||||
llm = new LinearLayoutManager(view.getContext());
|
||||
recyclerView.setLayoutManager(llm);
|
||||
|
||||
RecyclerViewAdapter adapter = new RecyclerViewAdapter(MainApp.getDbHelper().getCareportalEventsFromTime(false));
|
||||
recyclerView.setAdapter(adapter);
|
||||
|
||||
refreshFromNS = (Button) view.findViewById(R.id.careportal_refreshfromnightscout);
|
||||
refreshFromNS.setOnClickListener(this);
|
||||
|
||||
context = getContext();
|
||||
|
||||
boolean nsUploadOnly = SP.getBoolean(R.string.key_ns_upload_only, false);
|
||||
if (nsUploadOnly)
|
||||
refreshFromNS.setVisibility(View.GONE);
|
||||
|
||||
updateGUI();
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
switch (view.getId()) {
|
||||
case R.id.careportal_refreshfromnightscout:
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this.getContext());
|
||||
builder.setTitle(this.getContext().getString(R.string.confirmation));
|
||||
builder.setMessage(this.getContext().getString(R.string.refresheventsfromnightscout) + " ?");
|
||||
builder.setPositiveButton(this.getContext().getString(R.string.ok), new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
MainApp.getDbHelper().resetCareportalEvents();
|
||||
Intent restartNSClient = new Intent(Intents.ACTION_RESTART);
|
||||
MainApp.instance().getApplicationContext().sendBroadcast(restartNSClient);
|
||||
}
|
||||
});
|
||||
builder.setNegativeButton(this.getContext().getString(R.string.cancel), null);
|
||||
builder.show();
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onStatusEvent(final EventCareportalEventChange ev) {
|
||||
updateGUI();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateGUI() {
|
||||
Activity activity = getActivity();
|
||||
if (activity != null)
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
recyclerView.swapAdapter(new RecyclerViewAdapter(MainApp.getDbHelper().getCareportalEventsFromTime(false)), false);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -637,6 +637,11 @@ public class WatchUpdaterService extends WearableListenerService implements
|
|||
private String generateBasalString(TreatmentsInterface treatmentsInterface) {
|
||||
|
||||
String basalStringResult;
|
||||
|
||||
Profile profile = MainApp.getConfigBuilder().getProfile();
|
||||
if (profile == null)
|
||||
return "";
|
||||
|
||||
TemporaryBasal activeTemp = treatmentsInterface.getTempBasalFromHistory(System.currentTimeMillis());
|
||||
if (activeTemp != null) {
|
||||
basalStringResult = activeTemp.toStringShort();
|
||||
|
@ -644,7 +649,7 @@ public class WatchUpdaterService extends WearableListenerService implements
|
|||
if (SP.getBoolean(R.string.key_danar_visualizeextendedaspercentage, false)) {
|
||||
basalStringResult = "100%";
|
||||
} else {
|
||||
basalStringResult = DecimalFormatter.to2Decimal(MainApp.getConfigBuilder().getProfile().getBasal()) + "U/h";
|
||||
basalStringResult = DecimalFormatter.to2Decimal(profile.getBasal()) + "U/h";
|
||||
}
|
||||
}
|
||||
return basalStringResult;
|
||||
|
|
|
@ -148,8 +148,6 @@ public class CommandQueue {
|
|||
public static void independentConnect(String reason, Callback callback) {
|
||||
CommandQueue tempCommandQueue = new CommandQueue();
|
||||
tempCommandQueue.readStatus(reason, callback);
|
||||
QueueThread tempThread = new QueueThread(tempCommandQueue);
|
||||
tempThread.start();
|
||||
}
|
||||
|
||||
// returns true if command is queued
|
||||
|
|
|
@ -16,6 +16,8 @@ import info.nightscout.androidaps.events.EventPumpStatusChanged;
|
|||
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.Overview.events.EventDismissBolusprogressIfRunning;
|
||||
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
|
||||
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
|
||||
import info.nightscout.androidaps.queue.events.EventQueueChanged;
|
||||
import info.nightscout.utils.SP;
|
||||
|
||||
|
@ -35,7 +37,7 @@ public class QueueThread extends Thread {
|
|||
private PowerManager.WakeLock mWakeLock;
|
||||
|
||||
public QueueThread(CommandQueue queue) {
|
||||
super(QueueThread.class.toString());
|
||||
super();
|
||||
|
||||
this.queue = queue;
|
||||
PowerManager powerManager = (PowerManager) MainApp.instance().getApplicationContext().getSystemService(Context.POWER_SERVICE);
|
||||
|
@ -52,12 +54,6 @@ public class QueueThread extends Thread {
|
|||
while (true) {
|
||||
PumpInterface pump = ConfigBuilderPlugin.getActivePump();
|
||||
long secondsElapsed = (System.currentTimeMillis() - connectionStartTime) / 1000;
|
||||
if (pump.isConnecting()) {
|
||||
log.debug("QUEUE: connecting " + secondsElapsed);
|
||||
MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.CONNECTING, (int) secondsElapsed));
|
||||
SystemClock.sleep(1000);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!pump.isConnected() && secondsElapsed > Constants.PUMP_MAX_CONNECTION_TIME_IN_SECONDS) {
|
||||
MainApp.bus().post(new EventDismissBolusprogressIfRunning(null));
|
||||
|
@ -74,19 +70,37 @@ public class QueueThread extends Thread {
|
|||
//write time
|
||||
SP.putLong(R.string.key_btwatchdog_lastbark, System.currentTimeMillis());
|
||||
//toggle BT
|
||||
pump.stopConnecting();
|
||||
pump.disconnect("watchdog");
|
||||
SystemClock.sleep(1000);
|
||||
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
|
||||
mBluetoothAdapter.disable();
|
||||
SystemClock.sleep(1000);
|
||||
mBluetoothAdapter.enable();
|
||||
SystemClock.sleep(1000);
|
||||
//start over again once after watchdog barked
|
||||
//Notification notification = new Notification(Notification.OLD_NSCLIENT, "Watchdog", Notification.URGENT);
|
||||
//MainApp.bus().post(new EventNewNotification(notification));
|
||||
connectionStartTime = lastCommandTime = System.currentTimeMillis();
|
||||
pump.connect("watchdog");
|
||||
} else {
|
||||
queue.clear();
|
||||
log.debug("QUEUE: no connection possible");
|
||||
MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING));
|
||||
pump.disconnect("Queue empty");
|
||||
MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTED));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (pump.isConnecting()) {
|
||||
log.debug("QUEUE: connecting " + secondsElapsed);
|
||||
MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.CONNECTING, (int) secondsElapsed));
|
||||
SystemClock.sleep(1000);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (!pump.isConnected()) {
|
||||
log.debug("QUEUE: connect");
|
||||
MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.CONNECTING, (int) secondsElapsed));
|
||||
|
|
|
@ -270,6 +270,7 @@
|
|||
app:buttonTint="@color/basal" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/overview_showbasals_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
|
@ -286,6 +287,7 @@
|
|||
app:buttonTint="@color/iob" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/overview_showiob_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
|
@ -294,7 +296,6 @@
|
|||
android:textColor="@color/iob"
|
||||
android:textStyle="bold" />
|
||||
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/overview_showcob"
|
||||
android:layout_width="wrap_content"
|
||||
|
@ -303,6 +304,7 @@
|
|||
app:buttonTint="@color/cob" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/overview_showcob_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
|
@ -319,6 +321,7 @@
|
|||
app:buttonTint="@color/deviations" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/overview_showdeviations_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
|
@ -334,6 +337,7 @@
|
|||
android:layout_gravity="center" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/overview_showratios_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
|
|
|
@ -479,7 +479,7 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
app:buttonTint="@color/prediction" />
|
||||
android:buttonTint="@color/prediction" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/overview_showprediction_label"
|
||||
|
@ -496,9 +496,10 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
app:buttonTint="@color/basal" />
|
||||
android:buttonTint="@color/basal" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/overview_showbasals_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
|
@ -512,9 +513,10 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
app:buttonTint="@color/iob" />
|
||||
android:buttonTint="@color/iob" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/overview_showiob_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
|
@ -529,9 +531,10 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
app:buttonTint="@color/cob" />
|
||||
android:buttonTint="@color/cob" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/overview_showcob_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
|
@ -545,9 +548,10 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
app:buttonTint="@color/deviations" />
|
||||
android:buttonTint="@color/deviations" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/overview_showdeviations_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
|
@ -563,6 +567,7 @@
|
|||
android:layout_gravity="center" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/overview_showratios_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
|
|
|
@ -563,7 +563,7 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
app:buttonTint="@color/prediction" />
|
||||
android:buttonTint="@color/prediction" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/overview_showprediction_label"
|
||||
|
@ -580,9 +580,10 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
app:buttonTint="@color/basal" />
|
||||
android:buttonTint="@color/basal" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/overview_showbasals_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
|
@ -596,9 +597,10 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
app:buttonTint="@color/iob" />
|
||||
android:buttonTint="@color/iob" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/overview_showiob_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
|
@ -613,9 +615,10 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
app:buttonTint="@color/cob" />
|
||||
android:buttonTint="@color/cob" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/overview_showcob_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
|
@ -629,9 +632,10 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
app:buttonTint="@color/deviations" />
|
||||
android:buttonTint="@color/deviations" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/overview_showdeviations_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
|
@ -647,6 +651,7 @@
|
|||
android:layout_gravity="center" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/overview_showratios_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
|
|
|
@ -245,7 +245,7 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
app:buttonTint="@color/prediction" />
|
||||
android:buttonTint="@color/prediction" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/overview_showprediction_label"
|
||||
|
@ -262,9 +262,10 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
app:buttonTint="@color/basal" />
|
||||
android:buttonTint="@color/basal" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/overview_showbasals_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
|
@ -278,9 +279,10 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
app:buttonTint="@color/iob" />
|
||||
android:buttonTint="@color/iob" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/overview_showiob_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
|
@ -295,9 +297,10 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
app:buttonTint="@color/cob" />
|
||||
android:buttonTint="@color/cob" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/overview_showcob_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
|
@ -311,9 +314,10 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
app:buttonTint="@color/deviations" />
|
||||
android:buttonTint="@color/deviations" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/overview_showdeviations_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
|
@ -329,6 +333,7 @@
|
|||
android:layout_gravity="center" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/overview_showratios_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
|
|
28
app/src/main/res/layout/treatments_careportal_fragment.xml
Normal file
28
app/src/main/res/layout/treatments_careportal_fragment.xml
Normal file
|
@ -0,0 +1,28 @@
|
|||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context="info.nightscout.androidaps.plugins.Treatments.fragments.TreatmentsCareportalFragment">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<Button
|
||||
android:id="@+id/careportal_refreshfromnightscout"
|
||||
style="?android:attr/buttonStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:text="@string/refresheventsfromnightscout" />
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/careportal_recyclerview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
</android.support.v7.widget.RecyclerView>
|
||||
</LinearLayout>
|
||||
|
||||
</FrameLayout>
|
104
app/src/main/res/layout/treatments_careportal_item.xml
Normal file
104
app/src/main/res/layout/treatments_careportal_item.xml
Normal file
|
@ -0,0 +1,104 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/careportal_cardview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
card_view:cardBackgroundColor="?android:colorBackground">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:baselineAligned="true"
|
||||
android:orientation="horizontal">
|
||||
|
||||
|
||||
<com.joanzapata.iconify.widget.IconTextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:gravity="center_vertical|right"
|
||||
android:paddingLeft="10dp"
|
||||
android:paddingRight="5dp"
|
||||
android:text="{fa-clock-o}" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/careportal_date"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingRight="10dp"
|
||||
android:text="1.1.2000 18:00"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/careportal_type"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_weight="1"
|
||||
android:paddingRight="10dp"
|
||||
android:text=""
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginRight="10dp"
|
||||
android:layout_weight="1"
|
||||
android:text="" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/ns_sign"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginRight="10dp"
|
||||
android:text="NS"
|
||||
android:textColor="@color/colorSetTempButton" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/careportal_note"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_weight="1"
|
||||
android:paddingLeft="10dp"
|
||||
android:paddingRight="10dp"
|
||||
android:text="Activity" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/careportal_remove"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginRight="10dp"
|
||||
android:text="@string/overview_quickwizard_item_remove_button"
|
||||
android:textAlignment="viewEnd"
|
||||
android:textColor="@android:color/holo_orange_light" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="2dip"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:layout_marginLeft="5dp"
|
||||
android:layout_marginRight="5dp"
|
||||
android:layout_marginTop="5dp"
|
||||
android:background="@color/listdelimiter" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</android.support.v7.widget.CardView>
|
|
@ -71,6 +71,16 @@
|
|||
android:paddingRight="5dp"
|
||||
android:text="@string/profileswitch" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/treatments_careportal"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="30dp"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center_vertical|center_horizontal"
|
||||
android:paddingLeft="5dp"
|
||||
android:paddingRight="5dp"
|
||||
android:text="@string/careportal" />
|
||||
|
||||
</com.google.android.flexbox.FlexboxLayout>
|
||||
|
||||
<FrameLayout
|
||||
|
|
|
@ -231,8 +231,8 @@
|
|||
<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 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>
|
||||
<string formatted="false" name="bolusdelivered">Bolo %.2fU entregado con éxito</string>
|
||||
<string formatted="false" name="bolusdelivering">Entregando %.2fU</string>
|
||||
<string name="smscommunicator_remotebolusnotallowed">Bolo remoto no permitido</string>
|
||||
<string name="glucosetype_finger">Dedo</string>
|
||||
<string name="glucosetype_sensor">Sensor</string>
|
||||
|
|
|
@ -871,5 +871,6 @@
|
|||
<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>
|
||||
<string name="combo_error_bolus_recovery_progress">Recovering from connection loss</string>
|
||||
<string name="combo_reservoir_level_insufficient_for_bolus">Not enough insulin for bolus left in reservoir</string>
|
||||
<string name="extendedbolusdeliveryerror">Extended bolus delivery error</string>
|
||||
</resources>
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:validate="http://schemas.android.com/apk/res-auto">
|
||||
<PreferenceCategory
|
||||
android:key="others"
|
||||
android:title="@string/othersettings_title">
|
||||
|
@ -76,12 +77,16 @@
|
|||
android:defaultValue="true"
|
||||
android:key="@string/key_enable_pump_unreachable_alert"
|
||||
android:title="@string/enable_pump_unreachable_alert" />
|
||||
<EditTextPreference
|
||||
<com.andreabaccega.widget.ValidatingEditTextPreference
|
||||
validate:testType="numericRange"
|
||||
validate:minNumber="30"
|
||||
validate:maxNumber="300"
|
||||
android:defaultValue="30"
|
||||
android:dependency="@string/key_enable_pump_unreachable_alert"
|
||||
android:inputType="number"
|
||||
android:key="@string/key_pump_unreachable_threshold"
|
||||
android:title="@string/pump_unreachable_threshold"></EditTextPreference>
|
||||
android:title="@string/pump_unreachable_threshold">
|
||||
</com.andreabaccega.widget.ValidatingEditTextPreference>
|
||||
</PreferenceScreen>
|
||||
<SwitchPreference
|
||||
android:defaultValue="false"
|
||||
|
|
|
@ -10,12 +10,17 @@ buildscript {
|
|||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
|
||||
classpath 'com.jakewharton:butterknife-gradle-plugin:8.4.0'
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
jcenter()
|
||||
maven {
|
||||
url "https://maven.google.com"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue