Merge pull request #67 from MilosKozak/dev

Dev
This commit is contained in:
AdrianLxM 2017-04-30 10:58:50 +02:00 committed by GitHub
commit 334fbe0fd0
338 changed files with 9739 additions and 58715 deletions

View file

@ -43,8 +43,9 @@ android {
applicationId "info.nightscout.androidaps"
minSdkVersion 21
targetSdkVersion 23
versionCode 1100
versionName "1.1g"
versionCode 1400
version "1.41"
buildConfigField "String", "VERSION", '"' + version + '"'
buildConfigField "String", "BUILDVERSION", generateGitBuild()
}
lintOptions {
@ -57,41 +58,53 @@ android {
}
}
productFlavors {
flavorDimensions "standard", "limits", "wear"
adult {
dimension "limits"
buildConfigField "int", "MAXBOLUS", "17"
}
teenage {
dimension "limits"
buildConfigField "int", "MAXBOLUS", "10"
}
child {
dimension "limits"
buildConfigField "int", "MAXBOLUS", "5"
}
flavorDimensions "standard", "wear"
full {
dimension "standard"
resValue "string", "app_name", "AndroidAPS"
versionName version
manifestPlaceholders = [
appIcon: "@mipmap/blueowl"
]
buildConfigField "boolean", "APS", "true"
buildConfigField "boolean", "PUMPDRIVERS", "true"
buildConfigField "boolean", "NSCLIENTOLNY", "false"
buildConfigField "boolean", "CLOSEDLOOP", "true"
}
pumpcontrol {
dimension "standard"
buildConfigField "boolean", "APS", "false"
buildConfigField "boolean", "PUMPDRIVERS", "true"
buildConfigField "boolean", "CLOSEDLOOP", "false"
}
careportal {
dimension "standard"
buildConfigField "boolean", "APS", "false"
buildConfigField "boolean", "PUMPDRIVERS", "false"
buildConfigField "boolean", "CLOSEDLOOP", "false"
}
openloop {
dimension "standard"
resValue "string", "app_name", "AndroidAPS"
versionName version
manifestPlaceholders = [
appIcon: "@mipmap/blueowl"
]
buildConfigField "boolean", "APS", "true"
buildConfigField "boolean", "PUMPDRIVERS", "true"
buildConfigField "boolean", "NSCLIENTOLNY", "false"
buildConfigField "boolean", "CLOSEDLOOP", "false"
}
pumpcontrol {
dimension "standard"
resValue "string", "app_name", "AndroidAPS"
versionName version
manifestPlaceholders = [
appIcon: "@mipmap/blueowl"
]
buildConfigField "boolean", "APS", "false"
buildConfigField "boolean", "PUMPDRIVERS", "true"
buildConfigField "boolean", "NSCLIENTOLNY", "false"
buildConfigField "boolean", "CLOSEDLOOP", "false"
}
nsclient {
dimension "standard"
resValue "string", "app_name", "NSClient"
versionName version + "-nsclient"
manifestPlaceholders = [
appIcon: "@mipmap/yellowowl"
]
buildConfigField "boolean", "APS", "false"
buildConfigField "boolean", "PUMPDRIVERS", "false"
buildConfigField "boolean", "NSCLIENTOLNY", "true"
buildConfigField "boolean", "CLOSEDLOOP", "false"
}
wear {
@ -127,7 +140,10 @@ dependencies {
wearcontrolWearApp project(path: ':wear', configuration: 'fullRelease')
compile fileTree(include: ['*.jar'], dir: 'libs')
compile('com.crashlytics.sdk.android:crashlytics:2.5.7@aar') {
compile('com.crashlytics.sdk.android:crashlytics:2.6.7@aar') {
transitive = true;
}
compile('com.crashlytics.sdk.android:answers:1.3.12@aar') {
transitive = true;
}
@ -152,10 +168,16 @@ dependencies {
compile 'com.google.android.gms:play-services-wearable:7.5.0'
compile 'junit:junit:4.12'
testCompile 'org.json:json:20140107'
testCompile 'org.mockito:mockito-core:2.+'
androidTestCompile 'org.mockito:mockito-core:2.+'
androidTestCompile "com.google.dexmaker:dexmaker:1.2"
androidTestCompile "com.google.dexmaker:dexmaker-mockito:1.2"
compile(name:'android-edittext-validator-v1.3.4-mod', ext:'aar')
testCompile 'org.mockito:mockito-core:2.7.22'
androidTestCompile 'org.mockito:mockito-core:2.7.22'
androidTestCompile 'com.google.dexmaker:dexmaker:1.2'
androidTestCompile 'com.google.dexmaker:dexmaker-mockito:1.2'
compile(name: 'android-edittext-validator-v1.3.4-mod', ext: 'aar')
compile('io.socket:socket.io-client:0.8.3') {
// excluding org.json which is provided by Android
exclude group: 'org.json', module: 'json'
}
compile 'com.google.code.gson:gson:2.7'
compile 'com.google.guava:guava:20.0'
}

View file

@ -14,7 +14,10 @@
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.SEND_MMS" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="com.google.android.permission.PROVIDE_BACKGROUND" />
<uses-permission-sdk-23 android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<!-- To receive data from xdrip. -->
<uses-permission android:name="com.eveningoutpost.dexdrip.permissions.RECEIVE_BG_ESTIMATE" />
@ -22,26 +25,30 @@
<application
android:name=".MainApp"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:icon="${appIcon}"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".PreferencesActivity" />
<activity android:name=".plugins.Overview.Dialogs.BolusProgressHelperActivity" android:theme="@style/Theme.AppCompat.Translucent" />
<activity
android:name=".plugins.Overview.Dialogs.BolusProgressHelperActivity"
android:theme="@style/Theme.AppCompat.Translucent" />
<activity android:name=".AgreementActivity" />
<activity android:name=".plugins.DanaR.History.DanaRHistoryActivity" />
<activity android:name=".plugins.DanaRKorean.History.DanaRHistoryActivity" />
<activity android:name=".plugins.DanaR.History.DanaRStatsActivity" />
<activity android:name=".plugins.DanaRKorean.History.DanaRStatsActivity" />
<activity android:name=".plugins.PumpDanaR.History.DanaRHistoryActivity" />
<activity android:name=".plugins.PumpDanaRKorean.History.DanaRHistoryActivity" />
<activity android:name=".plugins.PumpDanaR.History.DanaRStatsActivity" />
<activity android:name=".plugins.PumpDanaRKorean.History.DanaRStatsActivity" />
<activity android:name=".plugins.Overview.activities.QuickWizardListActivity">
<intent-filter>
<action android:name="info.nightscout.androidaps.plugins.Overview.activities.QuickWizardListActivity" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
@ -68,37 +75,71 @@
<action android:name="com.eveningoutpost.dexdrip.BgEstimate" />
<!-- Receiver from 640g uploader -->
<action android:name="com.eveningoutpost.dexdrip.NS_EMULATOR" />
<!-- Auto start -->
<action android:name="android.intent.action.BOOT_COMPLETED" />
<!-- Receiver from glimp -->
<action android:name="it.ct.glicemia.ACTION_GLUCOSE_MEASURED" />
</intent-filter>
</receiver>
<!-- Receiver keepalive, scheduled every 30 min -->
<receiver android:name=".receivers.KeepAliveReceiver" />
<!-- Auto start -->
<receiver
android:name=".plugins.NSClientInternal.receivers.AutoStartReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<!-- NSClient -->
<receiver
android:name=".plugins.NSClientInternal.receivers.RestartReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="info.nightscout.client.RESTART" />
</intent-filter>
</receiver>
<receiver
android:name=".plugins.NSClientInternal.receivers.DBAccessReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="info.nightscout.client.DBACCESS" />
</intent-filter>
</receiver>
<!-- Service processing incomming data -->
<service
android:name=".Services.DataService"
android:exported="false" />
<!-- Service showing alert on screen -->
<service
android:name=".plugins.DanaR.Services.ExecutionService"
android:name=".plugins.PumpDanaR.Services.ExecutionService"
android:enabled="true"
android:exported="false" />
<service
android:name=".plugins.DanaRKorean.Services.ExecutionService"
android:name=".plugins.PumpDanaRKorean.Services.ExecutionService"
android:enabled="true"
android:exported="false" />
<service android:name=".plugins.Wear.wearintegration.WatchUpdaterService" android:exported="true" >
<intent-filter> <action android:name="com.google.android.gms.wearable.BIND_LISTENER" /> </intent-filter>
<service
android:name=".plugins.Wear.wearintegration.WatchUpdaterService"
android:exported="true">
<intent-filter>
<action android:name="com.google.android.gms.wearable.BIND_LISTENER" />
</intent-filter>
</service>
<meta-data
android:name="io.fabric.ApiKey"
android:value="59d462666c664c57b29e1d79ea123e01f8057cfa" />
<service
android:name=".plugins.NSClientInternal.services.NSClientService"
android:enabled="true"
android:exported="true" />
</application>
</manifest>
</manifest>

View file

@ -9,18 +9,18 @@ import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import info.nightscout.utils.SP;
public class AgreementActivity extends Activity {
boolean IUnderstand;
CheckBox agreeCheckBox;
Button saveButton;
SharedPreferences prefs;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_agreement);
prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
IUnderstand = prefs.getBoolean("I_understand", false);
IUnderstand = SP.getBoolean(R.string.key_i_understand, false);
setContentView(R.layout.activity_agreement);
agreeCheckBox = (CheckBox)findViewById(R.id.agreementCheckBox);
agreeCheckBox.setChecked(IUnderstand);
@ -32,7 +32,7 @@ public class AgreementActivity extends Activity {
saveButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
prefs.edit().putBoolean("I_understand", agreeCheckBox.isChecked()).apply();
SP.putBoolean(R.string.key_i_understand, agreeCheckBox.isChecked());
Intent intent = new Intent(getApplicationContext(), MainActivity.class);
startActivity(intent);

View file

@ -11,12 +11,22 @@ public class Config {
public static final boolean LOOPENABLED = APS;
public static final boolean WEAR = BuildConfig.WEAR;
public static final boolean CAREPORTALENABLED = true;
public static final boolean SMSCOMMUNICATORENABLED = true;
public static final boolean DANAR = true && BuildConfig.PUMPDRIVERS;
public static final boolean DANARKOREAN = true && BuildConfig.PUMPDRIVERS;
public static final boolean ACTION = !BuildConfig.NSCLIENTOLNY;
public static final boolean VIRTUALPUMP = !BuildConfig.NSCLIENTOLNY;
public static final boolean MDI = !BuildConfig.NSCLIENTOLNY;
public static final boolean OTHERPROFILES = !BuildConfig.NSCLIENTOLNY;
public static final boolean TEMPBASALS = !BuildConfig.NSCLIENTOLNY;
public static final boolean SAFETY = !BuildConfig.NSCLIENTOLNY;
public static final boolean SMSCOMMUNICATORENABLED = !BuildConfig.NSCLIENTOLNY;
public static final boolean ALLPREFERENCES = !BuildConfig.NSCLIENTOLNY;
public static final boolean detailedLog = true;
public static final boolean logFunctionCalls = true;
public static final boolean logIncommingBG = true;

View file

@ -12,6 +12,8 @@ public class Constants {
public static final double MMOLL_TO_MGDL = 18; // 18.0182;
public static final double MGDL_TO_MMOLL = 1 / MMOLL_TO_MGDL;
public static final double defaultDIA = 3d;
public static final double basalAbsoluteOnlyForCheckLimit = 10101010d;
public static final Integer basalPercentOnlyForCheckLimit = 10101010;
public static final double bolusOnlyForCheckLimit = 10101010d;
@ -32,12 +34,12 @@ public class Constants {
public static final int CPP_MAX_PERCENTAGE = 200;
// Defaults for settings
public static final String MAX_BG_DEFAULT_MGDL = "180";
public static final String MAX_BG_DEFAULT_MMOL = "10";
public static final String MIN_BG_DEFAULT_MGDL = "100";
public static final String MIN_BG_DEFAULT_MMOL = "5";
public static final String TARGET_BG_DEFAULT_MGDL = "150";
public static final String TARGET_BG_DEFAULT_MMOL = "7";
public static final Double MAX_BG_DEFAULT_MGDL = 180d;
public static final Double MAX_BG_DEFAULT_MMOL = 10d;
public static final Double MIN_BG_DEFAULT_MGDL = 100d;
public static final Double MIN_BG_DEFAULT_MMOL = 5d;
public static final Double TARGET_BG_DEFAULT_MGDL = 150d;
public static final Double TARGET_BG_DEFAULT_MMOL = 7d;
// Very Hard Limits Ranges
// First value is the Lowest and second value is the Highest a Limit can define
@ -52,4 +54,7 @@ public class Constants {
//DanaR
public static final double dailyLimitWarning = 0.95d;
//NSClientInternal
public static final int MAX_LOG_LINES = 100;
}

View file

@ -1,23 +1,21 @@
package info.nightscout.androidaps;
import android.Manifest;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.graphics.Rect;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.os.PowerManager;
import android.provider.Settings;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
@ -30,16 +28,15 @@ import com.squareup.otto.Subscribe;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.events.EventAppExit;
import info.nightscout.androidaps.events.EventPreferenceChange;
import info.nightscout.androidaps.events.EventRefreshGui;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.tabs.SlidingTabLayout;
import info.nightscout.androidaps.tabs.TabPageAdapter;
import info.nightscout.utils.LogDialog;
import info.nightscout.utils.ImportExportPrefs;
import info.nightscout.utils.LocaleHelper;
import info.nightscout.utils.PasswordProtection;
import info.nightscout.utils.OKDialog;
import info.nightscout.utils.SP;
import info.nightscout.utils.ToastUtils;
public class MainActivity extends AppCompatActivity {
private static Logger log = LoggerFactory.getLogger(MainActivity.class);
@ -60,33 +57,16 @@ public class MainActivity extends AppCompatActivity {
askForPermission(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE}, CASE_STORAGE);
}
askForBatteryOptimizationPermission();
if (Config.logFunctionCalls)
log.debug("onCreate");
// show version in toolbar
try {
setTitle(getString(R.string.app_name) + " " + getPackageManager().getPackageInfo(getPackageName(), 0).versionName);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
registerBus();
try {
getSupportActionBar().setDisplayShowHomeEnabled(true);
getSupportActionBar().setIcon(R.mipmap.ic_launcher);
} catch (NullPointerException e) {
// no action
}
setUpTabs(false);
}
@Subscribe
public void onStatusEvent(final EventRefreshGui ev) {
SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
String lang = SP.getString("language", "en");
LocaleHelper.setLocale(getApplicationContext(), lang);
runOnUiThread(new Runnable() {
@ -115,78 +95,6 @@ public class MainActivity extends AppCompatActivity {
mPager.setCurrentItem(pageAdapter.getCount() - 1, false);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
switch (id) {
case R.id.nav_preferences:
PasswordProtection.QueryPassword(this, R.string.settings_password, "settings_password", new Runnable() {
@Override
public void run() {
Intent i = new Intent(getApplicationContext(), PreferencesActivity.class);
startActivity(i);
}
}, null);
break;
case R.id.nav_resetdb:
new AlertDialog.Builder(this)
.setTitle(R.string.nav_resetdb)
.setMessage(R.string.reset_db_confirm)
.setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override public void onClick(DialogInterface dialog, int which) {
MainApp.getDbHelper().resetDatabases();
}
})
.create()
.show();
break;
case R.id.nav_export:
ImportExportPrefs.verifyStoragePermissions(this);
ImportExportPrefs.exportSharedPreferences(this);
break;
case R.id.nav_import:
ImportExportPrefs.verifyStoragePermissions(this);
ImportExportPrefs.importSharedPreferences(this);
break;
case R.id.nav_show_logcat:
LogDialog.showLogcat(this);
break;
// case R.id.nav_test_alarm:
// final int REQUEST_CODE_ASK_PERMISSIONS = 2355;
// int permission = ActivityCompat.checkSelfPermission(this, Manifest.permission.SYSTEM_ALERT_WINDOW);
// if (permission != PackageManager.PERMISSION_GRANTED) {
// // We don't have permission so prompt the user
// // On Android 6 give permission for alarming in Settings -> Apps -> Draw over other apps
// ActivityCompat.requestPermissions(
// this,
// new String[]{Manifest.permission.SYSTEM_ALERT_WINDOW},
// REQUEST_CODE_ASK_PERMISSIONS
// );
// }
// Intent alertServiceIntent = new Intent(getApplicationContext(), AlertService.class);
// alertServiceIntent.putExtra("alertText", getString(R.string.nav_test_alert));
// getApplicationContext().startService(alertServiceIntent);
// break;
case R.id.nav_exit:
log.debug("Exiting");
MainApp.instance().stopKeepAliveService();
MainApp.bus().post(new EventAppExit());
MainApp.closeDbHelper();
finish();
System.runFinalization();
System.exit(0);
break;
}
return super.onOptionsItemSelected(item);
}
private void registerBus() {
try {
MainApp.bus().unregister(this);
@ -197,7 +105,8 @@ public class MainActivity extends AppCompatActivity {
}
private void checkEula() {
boolean IUnderstand = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).getBoolean("I_understand", false);
//SP.removeBoolean(R.string.key_i_understand);
boolean IUnderstand = SP.getBoolean(R.string.key_i_understand, false);
if (!IUnderstand) {
Intent intent = new Intent(getApplicationContext(), AgreementActivity.class);
startActivity(intent);
@ -208,11 +117,12 @@ public class MainActivity extends AppCompatActivity {
//check for sms permission if enable in prefernces
@Subscribe
public void onStatusEvent(final EventPreferenceChange ev) {
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) {
SharedPreferences smssettings = PreferenceManager.getDefaultSharedPreferences(this);
synchronized (this){
if (smssettings.getBoolean("smscommunicator_remotecommandsallowed", false)) {
setAskForSMS();
if (ev.isChanged(R.string.key_smscommunicator_remotecommandsallowed)) {
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) {
synchronized (this) {
if (SP.getBoolean(R.string.key_smscommunicator_remotecommandsallowed, false)) {
setAskForSMS();
}
}
}
}
@ -223,16 +133,46 @@ public class MainActivity extends AppCompatActivity {
}
@Override
protected void onResume(){
protected void onResume() {
super.onResume();
askForSMSPermissions();
}
private synchronized void askForSMSPermissions(){
private void askForBatteryOptimizationPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
final String packageName = getPackageName();
final PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
if (!pm.isIgnoringBatteryOptimizations(packageName)) {
log.debug("Requesting ignore battery optimization");
OKDialog.show(this, getString(R.string.pleaseallowpermission), String.format(getString(R.string.needwhitelisting), getString(R.string.app_name)), new Runnable() {
@Override
public void run() {
try {
final Intent intent = new Intent();
// ignoring battery optimizations required for constant connection
intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
intent.setData(Uri.parse("package:" + packageName));
startActivity(intent);
} catch (ActivityNotFoundException e) {
final String msg = getString(R.string.batteryoptimalizationerror);
ToastUtils.showToastInUiThread(getApplicationContext(), msg);
log.error(msg);
}
}
});
}
}
}
private synchronized void askForSMSPermissions() {
if (askForSMS) { //only when settings were changed an MainActivity resumes.
askForSMS = false;
SharedPreferences smssettings = PreferenceManager.getDefaultSharedPreferences(this);
if (smssettings.getBoolean("smscommunicator_remotecommandsallowed", false)) {
if (SP.getBoolean(R.string.smscommunicator_remotecommandsallowed, false)) {
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) {
askForPermission(new String[]{Manifest.permission.RECEIVE_SMS,
Manifest.permission.SEND_SMS,
@ -244,7 +184,7 @@ public class MainActivity extends AppCompatActivity {
private void askForPermission(String[] permission, Integer requestCode) {
boolean test = false;
for (int i=0; i < permission.length; i++) {
for (int i = 0; i < permission.length; i++) {
test = test || (ContextCompat.checkSelfPermission(this, permission[i]) != PackageManager.PERMISSION_GRANTED);
}
if (test) {
@ -276,10 +216,10 @@ public class MainActivity extends AppCompatActivity {
public boolean dispatchTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
View v = getCurrentFocus();
if ( v instanceof EditText) {
if (v instanceof EditText) {
Rect outRect = new Rect();
v.getGlobalVisibleRect(outRect);
if (!outRect.contains((int)event.getRawX(), (int)event.getRawY())) {
if (!outRect.contains((int) event.getRawX(), (int) event.getRawY())) {
v.clearFocus();
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(v.getWindowToken(), 0);

View file

@ -6,6 +6,8 @@ import android.content.res.Resources;
import android.support.annotation.Nullable;
import com.crashlytics.android.Crashlytics;
import com.crashlytics.android.answers.Answers;
import com.crashlytics.android.answers.CustomEvent;
import com.j256.ormlite.android.apptools.OpenHelperManager;
import com.squareup.otto.Bus;
import com.squareup.otto.ThreadEnforcer;
@ -17,33 +19,39 @@ import java.util.ArrayList;
import info.nightscout.androidaps.db.DatabaseHelper;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.Actions.ActionsFragment;
import info.nightscout.androidaps.plugins.Careportal.CareportalFragment;
import info.nightscout.androidaps.plugins.CircadianPercentageProfile.CircadianPercentageProfileFragment;
import info.nightscout.androidaps.plugins.InsulinFastactingProlonged.InsulinFastactingProlongedFragment;
import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorFragment;
import info.nightscout.androidaps.plugins.ProfileCircadianPercentage.CircadianPercentageProfileFragment;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.DanaR.DanaRFragment;
import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanFragment;
import info.nightscout.androidaps.plugins.LocalProfile.LocalProfileFragment;
import info.nightscout.androidaps.plugins.PumpDanaR.DanaRFragment;
import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanFragment;
import info.nightscout.androidaps.plugins.InsulinFastacting.InsulinFastactingFragment;
import info.nightscout.androidaps.plugins.ProfileLocal.LocalProfileFragment;
import info.nightscout.androidaps.plugins.Loop.LoopFragment;
import info.nightscout.androidaps.plugins.MDI.MDIFragment;
import info.nightscout.androidaps.plugins.NSProfile.NSProfileFragment;
import info.nightscout.androidaps.plugins.Objectives.ObjectivesFragment;
import info.nightscout.androidaps.plugins.PumpMDI.MDIFragment;
import info.nightscout.androidaps.plugins.NSClientInternal.NSClientInternalFragment;
import info.nightscout.androidaps.plugins.ProfileNS.NSProfileFragment;
import info.nightscout.androidaps.plugins.ConstraintsObjectives.ObjectivesFragment;
import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAFragment;
import info.nightscout.androidaps.plugins.OpenAPSMA.OpenAPSMAFragment;
import info.nightscout.androidaps.plugins.Overview.OverviewFragment;
import info.nightscout.androidaps.plugins.SafetyFragment.SafetyFragment;
import info.nightscout.androidaps.plugins.SimpleProfile.SimpleProfileFragment;
import info.nightscout.androidaps.plugins.ConstraintsSafety.SafetyFragment;
import info.nightscout.androidaps.plugins.ProfileSimple.SimpleProfileFragment;
import info.nightscout.androidaps.plugins.SmsCommunicator.SmsCommunicatorFragment;
import info.nightscout.androidaps.plugins.SourceGlimp.SourceGlimpFragment;
import info.nightscout.androidaps.plugins.SourceMM640g.SourceMM640gFragment;
import info.nightscout.androidaps.plugins.SourceNSClient.SourceNSClientFragment;
import info.nightscout.androidaps.plugins.SourceXdrip.SourceXdripFragment;
import info.nightscout.androidaps.plugins.TempBasals.TempBasalsFragment;
import info.nightscout.androidaps.plugins.TempTargetRange.TempTargetRangeFragment;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsFragment;
import info.nightscout.androidaps.plugins.VirtualPump.VirtualPumpFragment;
import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpFragment;
import info.nightscout.androidaps.plugins.Wear.WearFragment;
import info.nightscout.androidaps.plugins.persistentnotification.PersistentNotificationPlugin;
import info.nightscout.androidaps.plugins.Persistentnotification.PersistentNotificationPlugin;
import info.nightscout.androidaps.receivers.KeepAliveReceiver;
import io.fabric.sdk.android.Fabric;
@ -65,10 +73,13 @@ public class MainApp extends Application {
public void onCreate() {
super.onCreate();
Fabric.with(this, new Crashlytics());
Fabric.with(this, new Answers());
Crashlytics.setString("BUILDVERSION", BuildConfig.BUILDVERSION);
log.info("Version: " + BuildConfig.VERSION_NAME);
log.info("BuildVersion: " + BuildConfig.BUILDVERSION);
Answers.getInstance().logCustom(new CustomEvent("AppStart"));
sBus = new Bus(ThreadEnforcer.ANY);
sInstance = this;
sResources = getResources();
@ -77,32 +88,37 @@ public class MainApp extends Application {
pluginsList = new ArrayList<>();
// Register all tabs in app here
pluginsList.add(OverviewFragment.getPlugin());
pluginsList.add(ActionsFragment.getPlugin());
pluginsList.add(IobCobCalculatorFragment.getPlugin());
if (Config.ACTION) pluginsList.add(ActionsFragment.getPlugin());
pluginsList.add(InsulinFastactingFragment.getPlugin());
pluginsList.add(InsulinFastactingProlongedFragment.getPlugin());
if (Config.DANAR) pluginsList.add(DanaRFragment.getPlugin());
if (Config.DANARKOREAN) pluginsList.add(DanaRKoreanFragment.getPlugin());
if (Config.CAREPORTALENABLED) pluginsList.add(CareportalFragment.getPlugin());
pluginsList.add(MDIFragment.getPlugin());
pluginsList.add(VirtualPumpFragment.getPlugin());
pluginsList.add(CareportalFragment.getPlugin());
if (Config.MDI) pluginsList.add(MDIFragment.getPlugin());
if (Config.VIRTUALPUMP) pluginsList.add(VirtualPumpFragment.getPlugin());
if (Config.LOOPENABLED) pluginsList.add(LoopFragment.getPlugin());
if (Config.OPENAPSENABLED) pluginsList.add(OpenAPSMAFragment.getPlugin());
if (Config.OPENAPSENABLED) pluginsList.add(OpenAPSAMAFragment.getPlugin());
pluginsList.add(NSProfileFragment.getPlugin());
pluginsList.add(SimpleProfileFragment.getPlugin());
pluginsList.add(LocalProfileFragment.getPlugin());
pluginsList.add(CircadianPercentageProfileFragment.getPlugin());
if (Config.OTHERPROFILES) pluginsList.add(SimpleProfileFragment.getPlugin());
if (Config.OTHERPROFILES) pluginsList.add(LocalProfileFragment.getPlugin());
if (Config.OTHERPROFILES)
pluginsList.add(CircadianPercentageProfileFragment.getPlugin());
if (Config.APS) pluginsList.add(TempTargetRangeFragment.getPlugin());
pluginsList.add(TreatmentsFragment.getPlugin());
pluginsList.add(TempBasalsFragment.getPlugin());
pluginsList.add(SafetyFragment.getPlugin());
if (Config.TEMPBASALS) pluginsList.add(TempBasalsFragment.getPlugin());
if (Config.SAFETY) pluginsList.add(SafetyFragment.getPlugin());
if (Config.APS) pluginsList.add(ObjectivesFragment.getPlugin());
pluginsList.add(SourceXdripFragment.getPlugin());
pluginsList.add(SourceNSClientFragment.getPlugin());
pluginsList.add(SourceMM640gFragment.getPlugin());
if (Config.SMSCOMMUNICATORENABLED)
pluginsList.add(SmsCommunicatorFragment.getPlugin());
pluginsList.add(SourceGlimpFragment.getPlugin());
if (Config.SMSCOMMUNICATORENABLED) pluginsList.add(SmsCommunicatorFragment.getPlugin());
if (Config.WEAR) pluginsList.add(WearFragment.getPlugin(this));
pluginsList.add(new PersistentNotificationPlugin(this));
pluginsList.add(NSClientInternalFragment.getPlugin());
pluginsList.add(sConfigBuilder = ConfigBuilderFragment.getPlugin());
@ -111,24 +127,37 @@ public class MainApp extends Application {
MainApp.getConfigBuilder().uploadAppStart();
startKeepAliveService();
Thread t = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
}
PumpInterface pump = MainApp.getConfigBuilder();
if (pump != null)
pump.refreshDataFromPump("Initialization");
}
});
t.start();
}
private void startKeepAliveService() {
if (keepAliveReceiver == null) {
keepAliveReceiver = new KeepAliveReceiver();
if (Config.DANAR) {
startService(new Intent(this, info.nightscout.androidaps.plugins.DanaR.Services.ExecutionService.class));
startService(new Intent(this, info.nightscout.androidaps.plugins.DanaRKorean.Services.ExecutionService.class));
startService(new Intent(this, info.nightscout.androidaps.plugins.PumpDanaR.Services.ExecutionService.class));
startService(new Intent(this, info.nightscout.androidaps.plugins.PumpDanaRKorean.Services.ExecutionService.class));
}
keepAliveReceiver.setAlarm(this);
}
}
public void stopKeepAliveService(){
if(keepAliveReceiver!=null)
keepAliveReceiver.cancelAlarm(this);
public void stopKeepAliveService() {
if (keepAliveReceiver != null)
keepAliveReceiver.cancelAlarm(this);
}
public static Bus bus() {
@ -175,6 +204,21 @@ public class MainApp extends Application {
return newList;
}
public static ArrayList<PluginBase> getSpecificPluginsVisibleInList(int type) {
ArrayList<PluginBase> newList = new ArrayList<>();
if (pluginsList != null) {
for (PluginBase p : pluginsList) {
if (p.getType() == type)
if (p.showInList(type))
newList.add(p);
}
} else {
log.error("pluginsList=null");
}
return newList;
}
public static ArrayList<PluginBase> getSpecificPluginsListByInterface(Class interfaceClass) {
ArrayList<PluginBase> newList = new ArrayList<>();
@ -189,6 +233,21 @@ public class MainApp extends Application {
return newList;
}
public static ArrayList<PluginBase> getSpecificPluginsVisibleInListByInterface(Class interfaceClass, int type) {
ArrayList<PluginBase> newList = new ArrayList<>();
if (pluginsList != null) {
for (PluginBase p : pluginsList) {
if (p.getClass() != ConfigBuilderPlugin.class && interfaceClass.isAssignableFrom(p.getClass()))
if (p.showInList(type))
newList.add(p);
}
} else {
log.error("pluginsList=null");
}
return newList;
}
@Nullable
public static PluginBase getSpecificPlugin(Class pluginClass) {
if (pluginsList != null) {

View file

@ -11,15 +11,16 @@ import android.preference.PreferenceFragment;
import android.preference.PreferenceGroup;
import android.preference.PreferenceManager;
import info.nightscout.androidaps.events.EventPreferenceChange;
import info.nightscout.androidaps.events.EventRefreshGui;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.plugins.DanaR.BluetoothDevicePreference;
import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin;
import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPlugin;
import info.nightscout.androidaps.plugins.PumpDanaR.BluetoothDevicePreference;
import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin;
import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin;
import info.nightscout.androidaps.plugins.NSClientInternal.NSClientInternalPlugin;
import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin;
import info.nightscout.androidaps.plugins.VirtualPump.VirtualPumpPlugin;
import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin;
import info.nightscout.androidaps.plugins.Wear.WearPlugin;
import info.nightscout.utils.LocaleHelper;
public class PreferencesActivity extends PreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener {
@ -35,7 +36,7 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
MainApp.bus().post(new EventPreferenceChange());
MainApp.bus().post(new EventPreferenceChange(key));
if (key.equals("language")) {
String lang = sharedPreferences.getString("language", "en");
LocaleHelper.setLocale(getApplicationContext(), lang);
@ -48,14 +49,14 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
updatePrefSummary(myPreferenceFragment.getPreference(key));
}
private static void updatePrefSummary(Preference pref) {
private static void updatePrefSummary(Preference pref) {
if (pref instanceof ListPreference || pref instanceof BluetoothDevicePreference) {
ListPreference listPref = (ListPreference) pref;
pref.setSummary(listPref.getEntry());
}
if (pref instanceof EditTextPreference) {
EditTextPreference editTextPref = (EditTextPreference) pref;
if (pref.getKey().contains("password")) {
if (pref.getKey().contains("password") || pref.getKey().contains("secret")) {
pref.setSummary("******");
} else if (editTextPref.getText() != null && !editTextPref.getText().equals("")) {
((EditTextPreference) pref).setDialogMessage(editTextPref.getDialogMessage());
@ -68,7 +69,7 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
}
}
private static void initSummary(Preference p) {
public static void initSummary(Preference p) {
if (p instanceof PreferenceGroup) {
PreferenceGroup pGrp = (PreferenceGroup) p;
for (int i = 0; i < pGrp.getPreferenceCount(); i++) {
@ -83,19 +84,28 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
@Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_password);
addPreferencesFromResource(R.xml.pref_quickwizard);
if (Config.ALLPREFERENCES) {
addPreferencesFromResource(R.xml.pref_password);
addPreferencesFromResource(R.xml.pref_age);
}
addPreferencesFromResource(R.xml.pref_language);
if (Config.CAREPORTALENABLED)
addPreferencesFromResource(R.xml.pref_careportal);
addPreferencesFromResource(R.xml.pref_treatments);
if (Config.ALLPREFERENCES) {
addPreferencesFromResource(R.xml.pref_quickwizard);
}
addPreferencesFromResource(R.xml.pref_careportal);
if (Config.ALLPREFERENCES) {
addPreferencesFromResource(R.xml.pref_treatments);
}
if (Config.APS)
addPreferencesFromResource(R.xml.pref_closedmode);
if (Config.OPENAPSENABLED)
if (Config.OPENAPSENABLED) {
addPreferencesFromResource(R.xml.pref_openapsma);
if (MainApp.getSpecificPlugin(OpenAPSAMAPlugin.class) != null && MainApp.getSpecificPlugin(OpenAPSAMAPlugin.class).isEnabled(PluginBase.APS))
addPreferencesFromResource(R.xml.pref_openapsama);
addPreferencesFromResource(R.xml.pref_profile);
if (MainApp.getSpecificPlugin(OpenAPSAMAPlugin.class) != null && MainApp.getSpecificPlugin(OpenAPSAMAPlugin.class).isEnabled(PluginBase.APS))
addPreferencesFromResource(R.xml.pref_openapsama);
}
if (Config.ALLPREFERENCES) {
addPreferencesFromResource(R.xml.pref_profile);
}
if (Config.DANAR) {
DanaRPlugin danaRPlugin = (DanaRPlugin) MainApp.getSpecificPlugin(DanaRPlugin.class);
DanaRKoreanPlugin danaRKoreanPlugin = (DanaRKoreanPlugin) MainApp.getSpecificPlugin(DanaRKoreanPlugin.class);
@ -108,16 +118,30 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
}
VirtualPumpPlugin virtualPumpPlugin = (VirtualPumpPlugin) MainApp.getSpecificPlugin(VirtualPumpPlugin.class);
if (virtualPumpPlugin != null && virtualPumpPlugin.isEnabled(PluginBase.PUMP)) {
addPreferencesFromResource(R.xml.pref_virtualpump);
addPreferencesFromResource(R.xml.pref_virtualpump);
}
NSClientInternalPlugin nsClientInternalPlugin = (NSClientInternalPlugin) MainApp.getSpecificPlugin(NSClientInternalPlugin.class);
if (nsClientInternalPlugin != null && nsClientInternalPlugin.isEnabled(PluginBase.GENERAL)) {
addPreferencesFromResource(R.xml.pref_nsclientinternal);
}
if (Config.SMSCOMMUNICATORENABLED)
addPreferencesFromResource(R.xml.pref_smscommunicator);
addPreferencesFromResource(R.xml.pref_others);
addPreferencesFromResource(R.xml.pref_advanced);
if (Config.ALLPREFERENCES) {
addPreferencesFromResource(R.xml.pref_others);
addPreferencesFromResource(R.xml.pref_advanced);
}
if (Config.WEAR) {
WearPlugin wearPlugin = (WearPlugin) MainApp.getSpecificPlugin(WearPlugin.class);
if (wearPlugin != null && wearPlugin.isEnabled(PluginBase.GENERAL)) {
addPreferencesFromResource(R.xml.pref_wear);
}
}
initSummary(getPreferenceScreen());
}
public Preference getPreference (String key) {
public Preference getPreference(String key) {
return findPreference(key);
}
}

View file

@ -32,25 +32,28 @@ import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.events.EventNewBG;
import info.nightscout.androidaps.events.EventNewBasalProfile;
import info.nightscout.androidaps.interfaces.InsulinInterface;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.DanaR.History.DanaRNSHistorySync;
import info.nightscout.androidaps.plugins.NSProfile.NSProfilePlugin;
import info.nightscout.androidaps.plugins.Objectives.ObjectivesPlugin;
import info.nightscout.androidaps.plugins.PumpDanaR.History.DanaRNSHistorySync;
import info.nightscout.androidaps.plugins.InsulinFastacting.InsulinFastactingFragment;
import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin;
import info.nightscout.androidaps.plugins.ConstraintsObjectives.ObjectivesPlugin;
import info.nightscout.androidaps.plugins.Overview.Notification;
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.SmsCommunicator.SmsCommunicatorPlugin;
import info.nightscout.androidaps.plugins.SmsCommunicator.events.EventNewSMS;
import info.nightscout.androidaps.plugins.SourceGlimp.SourceGlimpPlugin;
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.plugins.TempTargetRange.events.EventTempTargetRangeChange;
import info.nightscout.androidaps.receivers.DataReceiver;
import info.nightscout.client.data.NSProfile;
import info.nightscout.client.data.NSSgv;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSgv;
public class DataService extends IntentService {
@ -59,6 +62,7 @@ public class DataService extends IntentService {
boolean xDripEnabled = false;
boolean nsClientEnabled = true;
boolean mm640gEnabled = false;
boolean glimpEnabled = false;
public DataService() {
super("DataService");
@ -74,14 +78,22 @@ public class DataService extends IntentService {
xDripEnabled = true;
nsClientEnabled = false;
mm640gEnabled = false;
glimpEnabled = false;
} else if (ConfigBuilderPlugin.getActiveBgSource().getClass().equals(SourceNSClientPlugin.class)) {
xDripEnabled = false;
nsClientEnabled = true;
mm640gEnabled = false;
glimpEnabled = false;
} else if (ConfigBuilderPlugin.getActiveBgSource().getClass().equals(SourceMM640gPlugin.class)) {
xDripEnabled = false;
nsClientEnabled = false;
mm640gEnabled = true;
glimpEnabled = false;
} else if (ConfigBuilderPlugin.getActiveBgSource().getClass().equals(SourceGlimpPlugin.class)) {
xDripEnabled = false;
nsClientEnabled = false;
mm640gEnabled = false;
glimpEnabled = true;
}
boolean isNSProfile = ConfigBuilderPlugin.getActiveProfile().getClass().equals(NSProfilePlugin.class);
@ -99,6 +111,10 @@ public class DataService extends IntentService {
if (mm640gEnabled) {
handleNewDataFromMM640g(intent);
}
} else if (Intents.GLIMP_BG.equals(action)) {
if (glimpEnabled) {
handleNewDataFromGlimp(intent);
}
} else if (Intents.ACTION_NEW_SGV.equals(action)) {
// always handle SGV if NS-Client is the source
if (nsClientEnabled) {
@ -185,6 +201,30 @@ public class DataService extends IntentService {
MainApp.bus().post(new EventNewBG());
}
private void handleNewDataFromGlimp(Intent intent) {
Bundle bundle = intent.getExtras();
if (bundle == null) return;
BgReading bgReading = new BgReading();
bgReading.value = bundle.getDouble("mySGV");
bgReading.direction = bundle.getString("myTrend");
bgReading.battery_level = bundle.getInt("myBatLvl");
bgReading.timeIndex = bundle.getLong("myTimestamp");
bgReading.raw = 0;
if (Config.logIncommingBG)
log.debug(bundle.toString());
log.debug("GLIMP BG " + bgReading.toString());
try {
MainApp.getDbHelper().getDaoBgReadings().createIfNotExists(bgReading);
} catch (SQLException e) {
e.printStackTrace();
}
MainApp.bus().post(new EventNewBG());
}
private void handleNewDataFromMM640g(Intent intent) {
Bundle bundle = intent.getExtras();
if (bundle == null) return;
@ -482,7 +522,9 @@ public class DataService extends IntentService {
} else {
if (Config.logIncommingData)
log.debug("ADD: New treatment: " + trstring);
Treatment treatment = new Treatment();
InsulinInterface insulinInterface = MainApp.getConfigBuilder().getActiveInsulin();
if (insulinInterface == null) insulinInterface = InsulinFastactingFragment.getPlugin();
Treatment treatment = new Treatment(insulinInterface);
treatment._id = _id;
treatment.carbs = trJson.has("carbs") ? trJson.getDouble("carbs") : 0;
treatment.insulin = trJson.has("insulin") ? trJson.getDouble("insulin") : 0d;
@ -537,7 +579,9 @@ public class DataService extends IntentService {
if (Config.logIncommingData)
log.debug("CHANGE: Adding new treatment: " + trstring);
Treatment treatment = new Treatment();
InsulinInterface insulinInterface = MainApp.getConfigBuilder().getActiveInsulin();
if (insulinInterface == null) insulinInterface = InsulinFastactingFragment.getPlugin();
Treatment treatment = new Treatment(insulinInterface);
treatment._id = _id;
treatment.carbs = trJson.has("carbs") ? trJson.getDouble("carbs") : 0;
treatment.insulin = trJson.has("insulin") ? trJson.getDouble("insulin") : 0d;

View file

@ -11,11 +11,13 @@ public interface Intents {
String ACTION_NEW_MBG = "info.nightscout.client.NEW_MBG";
String ACTION_NEW_CAL = "info.nightscout.client.NEW_CAL";
String ACTION_NEW_STATUS = "info.nightscout.client.NEW_STATUS";
String ACTION_QUEUE_STATUS = "info.nightscout.client.QUEUE_STATUS";
// App -> NSClient
String ACTION_DATABASE = "info.nightscout.client.DBACCESS";
String ACTION_RESTART = "info.nightscout.client.RESTART";
String ACTION_RESEND = "info.nightscout.client.RESEND";
// xDrip -> App
String RECEIVER_PERMISSION = "com.eveningoutpost.dexdrip.permissions.RECEIVE_BG_ESTIMATE";
@ -33,4 +35,6 @@ public interface Intents {
String NS_EMULATOR = "com.eveningoutpost.dexdrip.NS_EMULATOR";
String ACTION_REMOTE_CALIBRATION = "com.eveningoutpost.dexdrip.NewCalibration";
String GLIMP_BG = "it.ct.glicemia.ACTION_GLUCOSE_MEASURED";
}

View file

@ -73,7 +73,7 @@ public class GlucoseStatus {
List<BgReading> data = MainApp.getDbHelper().getBgreadingsDataFromTime(fromtime, false);
int sizeRecords = data.size();
if (sizeRecords < 4 || data.get(0).timeIndex < new Date().getTime() - 7 * 60 * 1000L) {
if (sizeRecords < 1 || data.get(0).timeIndex < new Date().getTime() - 7 * 60 * 1000L) {
return null;
}
@ -81,6 +81,16 @@ public class GlucoseStatus {
long now_date = now.timeIndex;
double change;
if (sizeRecords < 2) {
GlucoseStatus status = new GlucoseStatus();
status.glucose = now.value;
status.short_avgdelta = 0d;
status.delta = 0d;
status.long_avgdelta = 0d;
status.avgdelta = 0d; // for OpenAPS MA
return status.round();
}
ArrayList<Double> last_deltas = new ArrayList<Double>();
ArrayList<Double> short_deltas = new ArrayList<Double>();
ArrayList<Double> long_deltas = new ArrayList<Double>();
@ -121,7 +131,7 @@ public class GlucoseStatus {
status.short_avgdelta = average(short_deltas);
if(prefs.getBoolean("always_use_shortavg",false) || last_deltas.isEmpty()){
if (prefs.getBoolean("always_use_shortavg", false) || last_deltas.isEmpty()) {
status.delta = status.short_avgdelta;
} else {
status.delta = average(last_deltas);

View file

@ -6,9 +6,8 @@ import org.json.JSONObject;
import java.util.Date;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.client.data.NSProfile;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.Round;
@ -21,7 +20,7 @@ public class IobTotal {
public Double hightempinsulin;
public Double netInsulin = 0d; // for calculations from temp basals only
public Double netRatio = 0d; // for calculations from temp basals only
public Double netRatio = 0d; // net ratio at start of temp basal
long time;
@ -95,43 +94,4 @@ public class IobTotal {
return json;
}
public static IobTotal calulateFromTreatmentsAndTemps() {
ConfigBuilderPlugin.getActiveTreatments().updateTotalIOB();
IobTotal bolusIob = ConfigBuilderPlugin.getActiveTreatments().getLastCalculation().round();
ConfigBuilderPlugin.getActiveTempBasals().updateTotalIOB();
IobTotal basalIob = ConfigBuilderPlugin.getActiveTempBasals().getLastCalculation().round();
IobTotal iobTotal = IobTotal.combine(bolusIob, basalIob).round();
return iobTotal;
}
public static IobTotal calulateFromTreatmentsAndTemps(long time) {
IobTotal bolusIob = ConfigBuilderPlugin.getActiveTreatments().getCalculationToTime(time).round();
IobTotal basalIob = ConfigBuilderPlugin.getActiveTempBasals().getCalculationToTime(time).round();
IobTotal iobTotal = IobTotal.combine(bolusIob, basalIob).round();
return iobTotal;
}
public static IobTotal[] calculateIobArrayInDia() {
NSProfile profile = ConfigBuilderPlugin.getActiveProfile().getProfile();
// predict IOB out to DIA plus 30m
long time = new Date().getTime();
int len = (int) ((profile.getDia() *60 + 30) / 5);
IobTotal[] array = new IobTotal[len];
int pos = 0;
for (int i = 0; i < len; i++){
long t = time + i * 5 * 60000;
IobTotal iob = calulateFromTreatmentsAndTemps(t);
array[pos] = iob;
pos++;
}
return array;
}
public static JSONArray convertToJSONArray(IobTotal[] iobArray) {
JSONArray array = new JSONArray();
for (int i = 0; i < iobArray.length; i ++) {
array.put(iobArray[i].determineBasalJson());
}
return array;
}
}

View file

@ -1,17 +1,5 @@
package info.nightscout.androidaps.data;
import java.util.Date;
import java.util.List;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.plugins.OpenAPSAMA.Autosens;
import info.nightscout.androidaps.plugins.OpenAPSAMA.AutosensResult;
import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin;
import info.nightscout.client.data.NSProfile;
/**
* Created by mike on 04.01.2017.
*/
@ -19,30 +7,4 @@ public class MealData {
public double boluses = 0d;
public double carbs = 0d;
public double mealCOB = 0.0d;
public void addTreatment(Treatment treatment) {
NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile();
if (profile == null) return;
List<BgReading> bgReadings = MainApp.getDbHelper().getBgreadingsDataFromTime((long) (new Date().getTime() - 60 * 60 * 1000L * profile.getDia() * 2), false);
long now = new Date().getTime();
long dia_ago = now - (new Double(1.5d * profile.getDia() * 60 * 60 * 1000l)).longValue();
long t = treatment.created_at.getTime();
if (t > dia_ago && t <= now) {
if (treatment.carbs >= 1) {
carbs += treatment.carbs;
if (MainApp.getSpecificPlugin(OpenAPSAMAPlugin.class).isEnabled(PluginBase.APS)) {
AutosensResult result = Autosens.detectSensitivityandCarbAbsorption(bgReadings, t);
double myCarbsAbsorbed = result.carbsAbsorbed;
double myMealCOB = Math.max(0, carbs - myCarbsAbsorbed);
mealCOB = Math.max(mealCOB, myMealCOB);
}
}
if (treatment.insulin > 0 && treatment.mealBolus) {
boluses += treatment.insulin;
}
}
}
}

View file

@ -1,7 +1,5 @@
package info.nightscout.androidaps.data;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.Html;
import android.text.Spanned;
@ -10,7 +8,7 @@ import org.json.JSONObject;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.client.data.NSProfile;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile;
import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.Round;

View file

@ -10,7 +10,7 @@ import org.slf4j.LoggerFactory;
import java.util.Date;
import info.nightscout.androidaps.Constants;
import info.nightscout.client.data.NSSgv;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSgv;
import info.nightscout.utils.DecimalFormatter;
@DatabaseTable(tableName = DatabaseHelper.DATABASE_BGREADINGS)
@ -47,7 +47,7 @@ public class BgReading implements DataPointInterface {
public BgReading(NSSgv sgv) {
timeIndex = sgv.getMills();
value = sgv.getMgdl();
raw = sgv.getFiltered();
raw = sgv.getFiltered() != null ? sgv.getFiltered() : value;
direction = sgv.getDirection();
}

View file

@ -29,6 +29,7 @@ import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.events.EventTreatmentChange;
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventNewHistoryData;
public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
private static Logger log = LoggerFactory.getLogger(DatabaseHelper.class);
@ -39,10 +40,11 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
public static final String DATABASE_TEMPTARGETS = "TempTargets";
public static final String DATABASE_TREATMENTS = "Treatments";
public static final String DATABASE_DANARHISTORY = "DanaRHistory";
public static final String DATABASE_DBREQUESTS = "DBRequests";
private static final int DATABASE_VERSION = 5;
private static final int DATABASE_VERSION = 6;
private long latestTreatmentChange = 0;
private static Long latestTreatmentChange = null;
private static final ScheduledExecutorService worker = Executors.newSingleThreadScheduledExecutor();
private static ScheduledFuture<?> scheduledPost = null;
@ -62,6 +64,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
TableUtils.createTableIfNotExists(connectionSource, Treatment.class);
TableUtils.createTableIfNotExists(connectionSource, BgReading.class);
TableUtils.createTableIfNotExists(connectionSource, DanaRHistoryRecord.class);
TableUtils.createTableIfNotExists(connectionSource, DbRequest.class);
} catch (SQLException e) {
log.error("Can't create database", e);
throw new RuntimeException(e);
@ -77,6 +80,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
TableUtils.dropTable(connectionSource, Treatment.class, true);
TableUtils.dropTable(connectionSource, BgReading.class, true);
TableUtils.dropTable(connectionSource, DanaRHistoryRecord.class, true);
TableUtils.dropTable(connectionSource, DbRequest.class, true);
onCreate(database, connectionSource);
} catch (SQLException e) {
log.error("Can't drop databases", e);
@ -122,12 +126,13 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
TableUtils.dropTable(connectionSource, Treatment.class, true);
TableUtils.dropTable(connectionSource, BgReading.class, true);
TableUtils.dropTable(connectionSource, DanaRHistoryRecord.class, true);
//DbRequests can be cleared from NSClient fragment
TableUtils.createTableIfNotExists(connectionSource, TempBasal.class);
TableUtils.createTableIfNotExists(connectionSource, TempTarget.class);
TableUtils.createTableIfNotExists(connectionSource, Treatment.class);
TableUtils.createTableIfNotExists(connectionSource, BgReading.class);
TableUtils.createTableIfNotExists(connectionSource, DanaRHistoryRecord.class);
latestTreatmentChange = 0;
latestTreatmentChange = 0L;
} catch (SQLException e) {
e.printStackTrace();
}
@ -137,7 +142,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
try {
TableUtils.dropTable(connectionSource, Treatment.class, true);
TableUtils.createTableIfNotExists(connectionSource, Treatment.class);
latestTreatmentChange = 0;
latestTreatmentChange = 0L;
} catch (SQLException e) {
e.printStackTrace();
}
@ -172,6 +177,14 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
return getDao(DanaRHistoryRecord.class);
}
public Dao<DbRequest, String> getDaoDbRequest() throws SQLException {
return getDao(DbRequest.class);
}
public long size(String database) {
return DatabaseUtils.queryNumEntries(getReadableDatabase(), database);
}
public List<BgReading> getBgreadingsDataFromTime(long mills, boolean ascending) {
try {
Dao<BgReading, Long> daoBgreadings = getDaoBgReadings();
@ -189,18 +202,80 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
return new ArrayList<BgReading>();
}
// DbRequests handling
public void create(DbRequest dbr) {
try {
getDaoDbRequest().create(dbr);
} catch (SQLException e) {
e.printStackTrace();
}
}
public int delete(DbRequest dbr) {
try {
return getDaoDbRequest().delete(dbr);
} catch (SQLException e) {
e.printStackTrace();
}
return 0;
}
public int deleteDbRequest(String nsClientId) {
try {
return getDaoDbRequest().deleteById(nsClientId);
} catch (SQLException e) {
e.printStackTrace();
}
return 0;
}
public int deleteDbRequestbyMongoId(String action, String id) {
try {
QueryBuilder<DbRequest, String> queryBuilder = getDaoDbRequest().queryBuilder();
Where where = queryBuilder.where();
where.eq("_id", id).and().eq("action", action);
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));
}
} catch (SQLException e) {
e.printStackTrace();
}
return 0;
}
public void deleteAllDbRequests() {
try {
TableUtils.clearTable(connectionSource, DbRequest.class);
} catch (SQLException e) {
e.printStackTrace();
}
}
// TREATMENT HANDLING
public boolean isDataUnchanged(long time) {
if (time >= latestTreatmentChange) return true;
else return false;
public boolean affectingIobCob(Treatment t) {
Treatment existing = findTreatmentByTimeIndex(t.timeIndex);
if (existing == null)
return true;
if (existing.insulin == t.insulin && existing.carbs == t.carbs)
return false;
return true;
}
public int update(Treatment treatment) {
int updated = 0;
try {
boolean historyChange = affectingIobCob(treatment);
updated = getDaoTreatments().update(treatment);
latestTreatmentChange = treatment.getTimeIndex();
if (historyChange)
latestTreatmentChange = treatment.getTimeIndex();
} catch (SQLException e) {
e.printStackTrace();
}
@ -211,8 +286,10 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
public Dao.CreateOrUpdateStatus createOrUpdate(Treatment treatment) {
Dao.CreateOrUpdateStatus status = null;
try {
boolean historyChange = affectingIobCob(treatment);
status = getDaoTreatments().createOrUpdate(treatment);
latestTreatmentChange = treatment.getTimeIndex();
if (historyChange)
latestTreatmentChange = treatment.getTimeIndex();
} catch (SQLException e) {
e.printStackTrace();
}
@ -311,6 +388,9 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
class PostRunnable implements Runnable {
public void run() {
MainApp.bus().post(new EventTreatmentChange());
if (latestTreatmentChange != null)
MainApp.bus().post(new EventNewHistoryData(latestTreatmentChange));
latestTreatmentChange = null;
scheduledPost = null;
}
}

View file

@ -0,0 +1,111 @@
package info.nightscout.androidaps.db;
import com.google.common.base.Charsets;
import com.google.common.hash.Hashing;
import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Created by mike on 27.02.2016.
* <p>
* Allowed actions "dbAdd" || "dbUpdate" || "dbUpdateUnset" || "dbRemove"
*/
@DatabaseTable(tableName = DatabaseHelper.DATABASE_DBREQUESTS)
public class DbRequest {
private static Logger log = LoggerFactory.getLogger(DbRequest.class);
public String getNsClientID() {
return nsClientID;
}
public void setNsClientID(String nsClientID) {
this.nsClientID = nsClientID;
}
@DatabaseField(id = true, useGetSet = true)
public String nsClientID = null;
@DatabaseField
public String action = null;
@DatabaseField
public String collection = null;
@DatabaseField
public String data = null;
@DatabaseField
public String _id = null;
public DbRequest() {
}
// dbAdd
public DbRequest(String action, String collection, String nsClientID, JSONObject data) {
this.action = action;
this.collection = collection;
this.data = data.toString();
this.nsClientID = nsClientID;
this._id = "";
}
// dbUpdate, dbUpdateUnset
public DbRequest(String action, String collection, String nsClientID, String _id, JSONObject data) {
this.action = action;
this.collection = collection;
this.data = data.toString();
this.nsClientID = nsClientID;
this._id = _id;
}
// dbRemove
public DbRequest(String action, String collection, String nsClientID, String _id) {
this.action = action;
this.collection = collection;
this.data = new JSONObject().toString();
this.nsClientID = nsClientID;
this._id = _id;
}
public String hash() {
return Hashing.sha1().hashString(action + collection + _id + data.toString(), Charsets.UTF_8).toString();
}
public JSONObject toJSON() {
JSONObject object = new JSONObject();
try {
object.put("action", action);
object.put("collection", collection);
object.put("data", new JSONObject(data));
if (_id != null) object.put("_id", _id);
if (nsClientID != null) object.put("nsClientID", nsClientID);
} catch (JSONException e) {
e.printStackTrace();
}
return object;
}
public static DbRequest fromJSON(JSONObject jsonObject) {
DbRequest result = new DbRequest();
try {
if (jsonObject.has("action"))
result.action = jsonObject.getString("action");
if (jsonObject.has("collection"))
result.collection = jsonObject.getString("collection");
if (jsonObject.has("data"))
result.data = jsonObject.getJSONObject("data").toString();
if (jsonObject.has("_id"))
result._id = jsonObject.getString("_id");
if (jsonObject.has("nsClientID"))
result.nsClientID = jsonObject.getString("nsClientID");
} catch (JSONException e) {
e.printStackTrace();
}
return result;
}
}

View file

@ -11,7 +11,9 @@ import java.util.Date;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.data.Iob;
import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.client.data.NSProfile;
import info.nightscout.androidaps.interfaces.InsulinInterface;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.DecimalFormatter;
@ -52,18 +54,81 @@ public class TempBasal {
public boolean isAbsolute = false; // true if if set as absolute value in U
public IobTotal iobCalc(Date time) {
IobTotal result = new IobTotal(time.getTime());
NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile();
public IobTotal iobCalc(long time) {
IobTotal result = new IobTotal(time);
NSProfile profile = ConfigBuilderPlugin.getActiveProfile().getProfile();
InsulinInterface insulinInterface = ConfigBuilderPlugin.getActiveInsulin();
if (profile == null)
return result;
int realDuration = getRealDuration();
int realDuration = getDurationToTime(time);
Double netBasalAmount = 0d;
if (realDuration > 0) {
Double netBasalRate = 0d;
int aboutFiveMinIntervals = (int) Math.ceil(realDuration / 5d);
result.netRatio = netBasalRate;
double tempBolusSpacing = realDuration / aboutFiveMinIntervals;
for (Long j = 0L; j < aboutFiveMinIntervals; j++) {
// find middle of the interval
Long date = (long) (timeStart.getTime() + j * tempBolusSpacing * 60 * 1000 + 0.5d * tempBolusSpacing * 60 * 1000);
Double basalRate = profile.getBasal(NSProfile.secondsFromMidnight(date));
if (isExtended) {
netBasalRate = this.absolute;
} else {
if (this.isAbsolute) {
netBasalRate = this.absolute - basalRate;
} else {
netBasalRate = (this.percent - 100) / 100d * basalRate;
}
}
double tempBolusSize = netBasalRate * tempBolusSpacing / 60d;
netBasalAmount += tempBolusSize;
Treatment tempBolusPart = new Treatment(insulinInterface);
tempBolusPart.insulin = tempBolusSize;
tempBolusPart.created_at = new Date(date);
Iob aIOB = insulinInterface.iobCalc(tempBolusPart, time, profile.getDia());
result.basaliob += aIOB.iobContrib;
result.activity += aIOB.activityContrib;
Double dia_ago = time - profile.getDia() * 60 * 60 * 1000;
if (date > dia_ago && date <= time) {
result.netbasalinsulin += tempBolusPart.insulin;
if (tempBolusPart.insulin > 0) {
result.hightempinsulin += tempBolusPart.insulin;
}
}
}
}
result.netInsulin = netBasalAmount;
return result;
}
/*
public IobTotal old_iobCalc(long time) {
IobTotal result = new IobTotal(time);
NSProfile profile = ConfigBuilderPlugin.getActiveProfile().getProfile();
InsulinInterface insulinInterface = ConfigBuilderPlugin.getActiveInsulin();
if (profile == null)
return result;
Double basalRate = profile.getBasal(NSProfile.secondsFromMidnight(time));
if (basalRate == null)
return result;
int realDuration = getDurationToTime(time);
if (realDuration > 0) {
Double netBasalRate = 0d;
Double basalRate = profile.getBasal(profile.secondsFromMidnight(time));
Double tempBolusSize = 0.05;
if (isExtended) {
@ -88,17 +153,17 @@ public class TempBasal {
Long tempBolusCount = Math.round(netBasalAmount / tempBolusSize);
if (tempBolusCount > 0) {
Long tempBolusSpacing = realDuration / tempBolusCount;
for (Long j = 0l; j < tempBolusCount; j++) {
Treatment tempBolusPart = new Treatment();
for (Long j = 0L; j < tempBolusCount; j++) {
Treatment tempBolusPart = new Treatment(insulinInterface);
tempBolusPart.insulin = tempBolusSize;
Long date = this.timeStart.getTime() + j * tempBolusSpacing * 60 * 1000;
tempBolusPart.created_at = new Date(date);
Iob aIOB = tempBolusPart.iobCalc(time, profile.getDia());
Iob aIOB = insulinInterface.iobCalc(tempBolusPart, time, profile.getDia());
result.basaliob += aIOB.iobContrib;
result.activity += aIOB.activityContrib;
Double dia_ago = time.getTime() - profile.getDia() * 60 * 60 * 1000;
if (date > dia_ago && date <= time.getTime()) {
Double dia_ago = time - profile.getDia() * 60 * 60 * 1000;
if (date > dia_ago && date <= time) {
result.netbasalinsulin += tempBolusPart.insulin;
if (tempBolusPart.insulin > 0) {
result.hightempinsulin += tempBolusPart.insulin;
@ -109,28 +174,35 @@ public class TempBasal {
}
return result;
}
*/
// Determine end of basal
public Date getTimeEnd() {
Date tempBasalTimePlannedEnd = getPlannedTimeEnd();
Date now = new Date();
public long getTimeEnd() {
long tempBasalTimePlannedEnd = getPlannedTimeEnd();
long now = new Date().getTime();
if (timeEnd != null && timeEnd.getTime() < tempBasalTimePlannedEnd.getTime()) {
tempBasalTimePlannedEnd = timeEnd;
if (timeEnd != null && timeEnd.getTime() < tempBasalTimePlannedEnd) {
tempBasalTimePlannedEnd = timeEnd.getTime();
}
if (now.getTime() < tempBasalTimePlannedEnd.getTime())
if (now < tempBasalTimePlannedEnd)
tempBasalTimePlannedEnd = now;
return tempBasalTimePlannedEnd;
}
public Date getPlannedTimeEnd() {
return new Date(timeStart.getTime() + 60 * 1_000 * duration);
public long getPlannedTimeEnd() {
return timeStart.getTime() + 60 * 1_000 * duration;
}
public int getRealDuration() {
Long msecs = getTimeEnd().getTime() - timeStart.getTime();
long msecs = getTimeEnd() - timeStart.getTime();
return Math.round(msecs / 60f / 1000);
}
public int getDurationToTime(long time) {
long endTime = Math.min(time, getTimeEnd());
long msecs = endTime - timeStart.getTime();
return Math.round(msecs / 60f / 1000);
}
@ -140,7 +212,7 @@ public class TempBasal {
public int getPlannedRemainingMinutes() {
if (timeEnd != null) return 0;
float remainingMin = (getPlannedTimeEnd().getTime() - new Date().getTime()) / 1000f / 60;
float remainingMin = (getPlannedTimeEnd() - new Date().getTime()) / 1000f / 60;
return (remainingMin < 0) ? 0 : Math.round(remainingMin);
}
@ -166,12 +238,13 @@ public class TempBasal {
public boolean isInProgress(Date time) {
if (timeStart.getTime() > time.getTime()) return false; // in the future
if (timeEnd == null) { // open end
if (timeStart.getTime() < time.getTime() && getPlannedTimeEnd().getTime() > time.getTime())
if (timeStart.getTime() < time.getTime() && getPlannedTimeEnd() > time.getTime())
return true; // in interval
return false;
}
// closed end
if (timeStart.getTime() < time.getTime() && timeEnd.getTime() > time.getTime()) return true; // in interval
if (timeStart.getTime() < time.getTime() && timeEnd.getTime() > time.getTime())
return true; // in interval
return false;
}

View file

@ -11,11 +11,13 @@ import org.slf4j.LoggerFactory;
import java.util.Date;
import java.util.List;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.data.Iob;
import info.nightscout.androidaps.interfaces.InsulinInterface;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Overview.graphExtensions.DataPointWithLabelInterface;
import info.nightscout.client.data.NSProfile;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.DecimalFormatter;
@ -43,12 +45,34 @@ public class Treatment implements DataPointWithLabelInterface {
@DatabaseField
public Double insulin = 0d;
@DatabaseField
public int insulinType = InsulinInterface.FASTACTINGINSULIN;
@DatabaseField
public double dia = Constants.defaultDIA;
@DatabaseField
public Double carbs = 0d;
@DatabaseField
public boolean mealBolus = true; // true for meal bolus , false for correction bolus
public Treatment() {
InsulinInterface insulin = MainApp.getConfigBuilder().getActiveInsulin();
if (insulin != null) {
insulinType = insulin.getId();
dia = insulin.getDia();
} else {
insulinType = InsulinInterface.FASTACTINGINSULIN;
dia = Constants.defaultDIA;
}
}
public Treatment(InsulinInterface insulin) {
insulinType = insulin.getId();
dia = insulin.getDia();
}
public void copyFrom(Treatment t) {
this._id = t._id;
this.created_at = t.created_at;
@ -57,32 +81,6 @@ public class Treatment implements DataPointWithLabelInterface {
this.mealBolus = t.mealBolus;
}
public Iob iobCalc(Date time, Double dia) {
Iob result = new Iob();
Double scaleFactor = 3.0 / dia;
Double peak = 75d;
Double end = 180d;
if (this.insulin != 0d) {
Long bolusTime = this.created_at.getTime();
Double minAgo = scaleFactor * (time.getTime() - bolusTime) / 1000d / 60d;
if (minAgo < peak) {
Double x1 = minAgo / 5d + 1;
result.iobContrib = this.insulin * (1 - 0.001852 * x1 * x1 + 0.001852 * x1);
// units: BG (mg/dL) = (BG/U) * U insulin * scalar
result.activityContrib = this.insulin * (2 / dia / 60 / peak) * minAgo;
} else if (minAgo < end) {
Double x2 = (minAgo - 75) / 5;
result.iobContrib = this.insulin * (0.001323 * x2 * x2 - 0.054233 * x2 + 0.55556);
result.activityContrib = this.insulin * (2 / dia / 60 - (minAgo - peak) * 2 / dia / 60 / (60 * 3 - peak));
}
}
return result;
}
public long getMillisecondsFromStart() {
return new Date().getTime() - created_at.getTime();
}

View file

@ -0,0 +1,8 @@
package info.nightscout.androidaps.events;
/**
* Created by mike on 17.02.2017.
*/
public class EventConfigBuilderChange {
}

View file

@ -1,6 +1,6 @@
package info.nightscout.androidaps.events;
import info.nightscout.client.data.NSProfile;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile;
/**
* Created by mike on 04.06.2016.

View file

@ -1,7 +1,25 @@
package info.nightscout.androidaps.events;
import info.nightscout.androidaps.MainApp;
/**
* Created by mike on 19.06.2016.
*/
public class EventPreferenceChange {
public String changedKey;
public EventPreferenceChange(String key) {
changedKey = key;
}
public EventPreferenceChange(int resourceID) {
changedKey = MainApp.sResources.getString(resourceID);
}
public boolean isChanged(int id) {
return changedKey.equals(MainApp.sResources.getString(id));
}
public boolean isChanged(String id) {
return changedKey.equals(id);
}
}

View file

@ -0,0 +1,50 @@
package info.nightscout.androidaps.events;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
/**
* Created by mike on 19.02.2017.
*/
public class EventPumpStatusChanged {
public static final int CONNECTING = 0;
public static final int CONNECTED = 1;
public static final int PERFORMING = 2;
public static final int DISCONNECTING = 3;
public static final int DISCONNECTED = 4;
public int sStatus = DISCONNECTED;
public int sSecondsElapsed = 0;
public String sPerfomingAction = "";
public EventPumpStatusChanged(int status) {
sStatus = status;
sSecondsElapsed = 0;
}
public EventPumpStatusChanged(int status, int secondsElapsed) {
sStatus = status;
sSecondsElapsed = secondsElapsed;
}
public EventPumpStatusChanged(String action) {
sStatus = PERFORMING;
sSecondsElapsed = 0;
sPerfomingAction = action;
}
public String textStatus() {
if (sStatus == CONNECTING)
return String.format(MainApp.sResources.getString(R.string.danar_history_connectingfor), sSecondsElapsed);
else if (sStatus == CONNECTED)
return MainApp.sResources.getString(R.string.connected);
else if (sStatus == PERFORMING)
return sPerfomingAction;
else if (sStatus == DISCONNECTING)
return MainApp.sResources.getString(R.string.disconnecting);
else if (sStatus == DISCONNECTED)
return "";
return "";
}
}

View file

@ -1,7 +0,0 @@
package info.nightscout.androidaps.interfaces;
/**
* Created by mike on 05.08.2016.
*/
public interface FragmentBase {
}

View file

@ -0,0 +1,21 @@
package info.nightscout.androidaps.interfaces;
import java.util.Date;
import info.nightscout.androidaps.data.Iob;
import info.nightscout.androidaps.db.Treatment;
/**
* Created by mike on 17.04.2017.
*/
public interface InsulinInterface {
final int FASTACTINGINSULIN = 0;
final int FASTACTINGINSULINPROLONGED = 1;
int getId();
String getFriendlyName();
String getComment();
double getDia();
public Iob iobCalc(Treatment treatment, long time, Double dia);
}

View file

@ -15,7 +15,8 @@ public interface PluginBase {
int CONSTRAINTS = 7;
int LOOP = 8;
int BGSOURCE = 9;
int LAST = 10; // keep always highest number
int INSULIN = 10;
int LAST = 11; // keep always highest number
int getType();
String getFragmentClass();
@ -25,6 +26,8 @@ public interface PluginBase {
boolean isEnabled(int type);
boolean isVisibleInTabs(int type);
boolean canBeHidden(int type);
boolean hasFragment();
boolean showInList(int type);
void setFragmentEnabled(int type, boolean fragmentEnabled);
void setFragmentVisible(int type, boolean fragmentVisible);
}

View file

@ -2,7 +2,7 @@ package info.nightscout.androidaps.interfaces;
import android.support.annotation.Nullable;
import info.nightscout.client.data.NSProfile;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile;
/**
* Created by mike on 14.06.2016.

View file

@ -8,8 +8,7 @@ import java.util.Date;
import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.db.TempBasal;
import info.nightscout.androidaps.plugins.Loop.APSResult;
import info.nightscout.client.data.NSProfile;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile;
/**
* Created by mike on 04.06.2016.
@ -30,8 +29,8 @@ public interface PumpInterface {
int setNewBasalProfile(NSProfile profile);
boolean isThisProfileSet(NSProfile profile);
Date lastStatusTime();
void updateStatus(String reason);
Date lastDataTime();
void refreshDataFromPump(String reason);
double getBaseBasalRate(); // base basal rate, not temp basal
double getTempBasalAbsoluteRate();
@ -40,7 +39,7 @@ public interface PumpInterface {
TempBasal getTempBasal();
TempBasal getExtendedBolus();
PumpEnactResult deliverTreatment(Double insulin, Integer carbs, Context context);
PumpEnactResult deliverTreatment(InsulinInterface insulinType, Double insulin, Integer carbs, Context context);
void stopBolusDelivering();
PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes);
PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes);
@ -52,7 +51,9 @@ public interface PumpInterface {
JSONObject getJSONStatus();
String deviceID();
// Pump capabilities
PumpDescription getPumpDescription();
public String shortStatus(boolean veryShort);
// Short info for SMS, Wear etc
String shortStatus(boolean veryShort);
}

View file

@ -16,4 +16,5 @@ public interface TreatmentsInterface {
IobTotal getCalculationToTime(long time);
MealData getMealData();
List<Treatment> getTreatments();
List<Treatment> getTreatments5MinBack(long time);
}

View file

@ -17,17 +17,16 @@ import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.events.EventInitializationChanged;
import info.nightscout.androidaps.events.EventRefreshGui;
import info.nightscout.androidaps.interfaces.FragmentBase;
import info.nightscout.androidaps.plugins.Actions.dialogs.FillDialog;
import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog;
import info.nightscout.androidaps.plugins.Careportal.OptionsToShow;
import info.nightscout.androidaps.plugins.Actions.dialogs.NewExtendedBolusDialog;
import info.nightscout.androidaps.plugins.Actions.dialogs.NewTempBasalDialog;
import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog;
import info.nightscout.androidaps.plugins.Careportal.OptionsToShow;
/**
* A simple {@link Fragment} subclass.
*/
public class ActionsFragment extends Fragment implements FragmentBase, View.OnClickListener {
public class ActionsFragment extends Fragment implements View.OnClickListener {
static ActionsPlugin actionsPlugin = new ActionsPlugin();

View file

@ -54,6 +54,16 @@ public class ActionsPlugin implements PluginBase {
return true;
}
@Override
public boolean hasFragment() {
return true;
}
@Override
public boolean showInList(int type) {
return true;
}
@Override
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
if (type == GENERAL) this.fragmentEnabled = fragmentEnabled;

View file

@ -18,6 +18,9 @@ import android.view.WindowManager;
import android.widget.Button;
import android.widget.TextView;
import com.crashlytics.android.answers.Answers;
import com.crashlytics.android.answers.CustomEvent;
import java.text.DecimalFormat;
import info.nightscout.androidaps.Constants;
@ -28,6 +31,7 @@ import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.PlusMinusEditText;
import info.nightscout.utils.SP;
import info.nightscout.utils.SafeParse;
public class FillDialog extends DialogFragment implements OnClickListener {
@ -72,10 +76,9 @@ public class FillDialog extends DialogFragment implements OnClickListener {
Button button3 = (Button) view.findViewById(R.id.fill_preset_button3);
View divider = view.findViewById(R.id.fill_preset_divider);
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
amount1 = SafeParse.stringToDouble(DecimalFormatter.to2Decimal(SafeParse.stringToDouble(sp.getString("fill_button1", "0.3"))));
amount2 = SafeParse.stringToDouble(DecimalFormatter.to2Decimal(SafeParse.stringToDouble(sp.getString("fill_button2", "0"))));
amount3 = SafeParse.stringToDouble(DecimalFormatter.to2Decimal(SafeParse.stringToDouble(sp.getString("fill_button3", "0"))));
amount1 = SP.getDouble("fill_button1", 0.3);
amount2 = SP.getDouble("fill_button2", 0d);
amount3 = SP.getDouble("fill_button3", 0d);
if(amount1 >0) {
button1.setVisibility(View.VISIBLE);
@ -156,7 +159,7 @@ public class FillDialog extends DialogFragment implements OnClickListener {
mHandler.post(new Runnable() {
@Override
public void run() {
PumpEnactResult result = pump.deliverTreatment(finalInsulinAfterConstraints, 0, context, false);
PumpEnactResult result = pump.deliverTreatment(MainApp.getConfigBuilder().getActiveInsulin(), finalInsulinAfterConstraints, 0, context, false);
if (!result.success) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(MainApp.sResources.getString(R.string.treatmentdeliveryerror));
@ -166,6 +169,7 @@ public class FillDialog extends DialogFragment implements OnClickListener {
}
}
});
Answers.getInstance().logCustom(new CustomEvent("Fill"));
}
}
});

View file

@ -14,6 +14,9 @@ import android.widget.Button;
import android.widget.EditText;
import android.widget.RadioButton;
import com.crashlytics.android.answers.Answers;
import com.crashlytics.android.answers.CustomEvent;
import java.text.DecimalFormat;
import info.nightscout.androidaps.Constants;
@ -117,6 +120,7 @@ public class NewExtendedBolusDialog extends DialogFragment implements View.OnCli
}
}
});
Answers.getInstance().logCustom(new CustomEvent("ExtendedBolus"));
}
});
builder.setNegativeButton(getString(R.string.cancel), null);

View file

@ -16,6 +16,9 @@ import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import com.crashlytics.android.answers.Answers;
import com.crashlytics.android.answers.CustomEvent;
import java.text.DecimalFormat;
import info.nightscout.androidaps.Constants;
@ -23,7 +26,7 @@ import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.client.data.NSProfile;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile;
import info.nightscout.utils.PlusMinusEditText;
import info.nightscout.utils.SafeParse;
@ -51,7 +54,7 @@ public class NewTempBasalDialog extends DialogFragment implements View.OnClickLi
public static HandlerThread mHandlerThread;
public NewTempBasalDialog() {
mHandlerThread = new HandlerThread(NewExtendedBolusDialog.class.getSimpleName());
mHandlerThread = new HandlerThread(NewTempBasalDialog.class.getSimpleName());
mHandlerThread.start();
this.mHandler = new Handler(mHandlerThread.getLooper());
}
@ -158,7 +161,7 @@ public class NewTempBasalDialog extends DialogFragment implements View.OnClickLi
}
}
});
Answers.getInstance().logCustom(new CustomEvent("TempBasal"));
}
});
builder.setNegativeButton(getString(R.string.cancel), null);

View file

@ -9,10 +9,9 @@ import android.view.View;
import android.view.ViewGroup;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.interfaces.FragmentBase;
import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog;
public class CareportalFragment extends Fragment implements FragmentBase, View.OnClickListener {
public class CareportalFragment extends Fragment implements View.OnClickListener {
static CareportalPlugin careportalPlugin;

View file

@ -50,6 +50,16 @@ public class CareportalPlugin implements PluginBase {
return true;
}
@Override
public boolean hasFragment() {
return true;
}
@Override
public boolean showInList(int type) {
return true;
}
@Override
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
if (type == GENERAL) this.fragmentEnabled = fragmentEnabled;

View file

@ -3,11 +3,9 @@ package info.nightscout.androidaps.plugins.Careportal.Dialogs;
import android.app.Activity;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.preference.PreferenceManager;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentActivity;
import android.support.v7.app.AlertDialog;
@ -26,6 +24,8 @@ import android.widget.RadioButton;
import android.widget.Spinner;
import android.widget.TextView;
import com.crashlytics.android.answers.Answers;
import com.crashlytics.android.answers.CustomEvent;
import com.j256.ormlite.dao.Dao;
import com.wdullaer.materialdatetimepicker.date.DatePickerDialog;
import com.wdullaer.materialdatetimepicker.time.RadialPickerLayout;
@ -42,7 +42,6 @@ import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
@ -51,12 +50,13 @@ import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.events.EventNewBasalProfile;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.Careportal.OptionsToShow;
import info.nightscout.androidaps.plugins.CircadianPercentageProfile.CircadianPercentageProfilePlugin;
import info.nightscout.androidaps.plugins.ProfileCircadianPercentage.CircadianPercentageProfilePlugin;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile;
import info.nightscout.androidaps.plugins.TempTargetRange.events.EventTempTargetRangeChange;
import info.nightscout.client.data.NSProfile;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.PlusMinusEditText;
import info.nightscout.utils.SP;
import info.nightscout.utils.SafeParse;
import info.nightscout.utils.ToastUtils;
import info.nightscout.utils.Translator;
@ -391,7 +391,6 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
JSONObject gatherData() {
SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
String enteredBy = SP.getString("careportal_enteredby", "");
JSONObject data = new JSONObject();
try {
@ -630,6 +629,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
data.put("percentage", cpp.percentage);
}
ConfigBuilderPlugin.uploadCareportalEntryToNS(data);
Answers.getInstance().logCustom(new CustomEvent("ProfileSwitch"));
} catch (JSONException e) {
e.printStackTrace();
}
@ -660,6 +660,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
dao.createIfNotExists(tempTarget);
MainApp.bus().post(new EventTempTargetRangeChange());
ConfigBuilderPlugin.uploadCareportalEntryToNS(data);
Answers.getInstance().logCustom(new CustomEvent("TempTarget"));
} catch (JSONException | SQLException e) {
e.printStackTrace();
}
@ -671,6 +672,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
}
} else {
ConfigBuilderPlugin.uploadCareportalEntryToNS(data);
Answers.getInstance().logCustom(new CustomEvent("NSTreatment"));
}
}
});

View file

@ -16,24 +16,29 @@ import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView;
import com.crashlytics.android.answers.Answers;
import com.crashlytics.android.answers.CustomEvent;
import java.util.ArrayList;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.events.EventConfigBuilderChange;
import info.nightscout.androidaps.events.EventRefreshGui;
import info.nightscout.androidaps.interfaces.APSInterface;
import info.nightscout.androidaps.interfaces.BgSourceInterface;
import info.nightscout.androidaps.interfaces.ConstraintsInterface;
import info.nightscout.androidaps.interfaces.FragmentBase;
import info.nightscout.androidaps.interfaces.InsulinInterface;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.ProfileInterface;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.NSProfile.NSProfilePlugin;
import info.nightscout.androidaps.plugins.VirtualPump.VirtualPumpPlugin;
import info.nightscout.androidaps.plugins.InsulinFastacting.InsulinFastactingPlugin;
import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin;
import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin;
import info.nightscout.utils.PasswordProtection;
public class ConfigBuilderFragment extends Fragment implements FragmentBase {
public class ConfigBuilderFragment extends Fragment {
static ConfigBuilderPlugin configBuilderPlugin = new ConfigBuilderPlugin();
@ -41,20 +46,28 @@ public class ConfigBuilderFragment extends Fragment implements FragmentBase {
return configBuilderPlugin;
}
ListView insulinListView;
ListView bgsourceListView;
ListView pumpListView;
TextView pumpLabel;
ListView loopListView;
TextView loopLabel;
ListView treatmentsListView;
ListView tempsListView;
TextView tempsLabel;
ListView profileListView;
ListView apsListView;
TextView apsLabel;
ListView constraintsListView;
TextView constraintsLabel;
ListView generalListView;
TextView nsclientVerView;
TextView nightscoutVerView;
LinearLayout mainLayout;
Button unlock;
PluginCustomAdapter insulinDataAdapter = null;
PluginCustomAdapter bgsourceDataAdapter = null;
PluginCustomAdapter pumpDataAdapter = null;
PluginCustomAdapter loopDataAdapter = null;
@ -65,29 +78,34 @@ public class ConfigBuilderFragment extends Fragment implements FragmentBase {
PluginCustomAdapter constraintsDataAdapter = null;
PluginCustomAdapter generalDataAdapter = null;
LinearLayout mainLayout;
Button unlock;
// TODO: sorting
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.configbuilder_fragment, container, false);
insulinListView = (ListView) view.findViewById(R.id.configbuilder_insulinlistview);
bgsourceListView = (ListView) view.findViewById(R.id.configbuilder_bgsourcelistview);
pumpListView = (ListView) view.findViewById(R.id.configbuilder_pumplistview);
pumpLabel = (TextView) view.findViewById(R.id.configbuilder_pumplabel);
loopListView = (ListView) view.findViewById(R.id.configbuilder_looplistview);
loopLabel = (TextView) view.findViewById(R.id.configbuilder_looplabel);
treatmentsListView = (ListView) view.findViewById(R.id.configbuilder_treatmentslistview);
tempsListView = (ListView) view.findViewById(R.id.configbuilder_tempslistview);
tempsLabel = (TextView) view.findViewById(R.id.configbuilder_tempslabel);
profileListView = (ListView) view.findViewById(R.id.configbuilder_profilelistview);
apsListView = (ListView) view.findViewById(R.id.configbuilder_apslistview);
apsLabel = (TextView) view.findViewById(R.id.configbuilder_apslabel);
constraintsListView = (ListView) view.findViewById(R.id.configbuilder_constraintslistview);
constraintsLabel = (TextView) view.findViewById(R.id.configbuilder_constraintslabel);
generalListView = (ListView) view.findViewById(R.id.configbuilder_generallistview);
nsclientVerView = (TextView) view.findViewById(R.id.configbuilder_nsclientversion);
nightscoutVerView = (TextView) view.findViewById(R.id.configbuilder_nightscoutversion);
mainLayout = (LinearLayout) view.findViewById(R.id.configbuilder_mainlayout);
unlock = (Button) view.findViewById(R.id.configbuilder_unlock);
nsclientVerView.setText(ConfigBuilderPlugin.nsClientVersionName);
nightscoutVerView.setText(ConfigBuilderPlugin.nightscoutVersionName);
if (ConfigBuilderPlugin.nsClientVersionCode < 117) nsclientVerView.setTextColor(Color.RED);
@ -95,9 +113,6 @@ public class ConfigBuilderFragment extends Fragment implements FragmentBase {
nightscoutVerView.setTextColor(Color.RED);
setViews();
unlock = (Button) view.findViewById(R.id.configbuilder_unlock);
mainLayout = (LinearLayout) view.findViewById(R.id.configbuilder_mainlayout);
if (PasswordProtection.isLocked("settings_password")) {
mainLayout.setVisibility(View.GONE);
unlock.setOnClickListener(new View.OnClickListener() {
@ -112,40 +127,51 @@ public class ConfigBuilderFragment extends Fragment implements FragmentBase {
}, null);
}
});
} else {
unlock.setVisibility(View.GONE);
}
return view;
}
void setViews() {
bgsourceDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsListByInterface(BgSourceInterface.class), PluginBase.BGSOURCE);
insulinDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInListByInterface(InsulinInterface.class, PluginBase.INSULIN), PluginBase.INSULIN);
insulinListView.setAdapter(insulinDataAdapter);
setListViewHeightBasedOnChildren(insulinListView);
bgsourceDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInListByInterface(BgSourceInterface.class, PluginBase.BGSOURCE), PluginBase.BGSOURCE);
bgsourceListView.setAdapter(bgsourceDataAdapter);
setListViewHeightBasedOnChildren(bgsourceListView);
pumpDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsList(PluginBase.PUMP), PluginBase.PUMP);
pumpDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInList(PluginBase.PUMP), PluginBase.PUMP);
pumpListView.setAdapter(pumpDataAdapter);
if (MainApp.getSpecificPluginsVisibleInList(PluginBase.PUMP).size() == 0)
pumpLabel.setVisibility(View.GONE);
setListViewHeightBasedOnChildren(pumpListView);
loopDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsList(PluginBase.LOOP), PluginBase.LOOP);
loopDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInList(PluginBase.LOOP), PluginBase.LOOP);
loopListView.setAdapter(loopDataAdapter);
setListViewHeightBasedOnChildren(loopListView);
if (MainApp.getSpecificPluginsList(PluginBase.LOOP).size() == 0)
if (MainApp.getSpecificPluginsVisibleInList(PluginBase.LOOP).size() == 0)
loopLabel.setVisibility(View.GONE);
treatmentsDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsList(PluginBase.TREATMENT), PluginBase.TREATMENT);
treatmentsDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInList(PluginBase.TREATMENT), PluginBase.TREATMENT);
treatmentsListView.setAdapter(treatmentsDataAdapter);
setListViewHeightBasedOnChildren(treatmentsListView);
tempsDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsList(PluginBase.TEMPBASAL), PluginBase.TEMPBASAL);
tempsDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInList(PluginBase.TEMPBASAL), PluginBase.TEMPBASAL);
tempsListView.setAdapter(tempsDataAdapter);
setListViewHeightBasedOnChildren(tempsListView);
profileDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsListByInterface(ProfileInterface.class), PluginBase.PROFILE);
if (MainApp.getSpecificPluginsVisibleInList(PluginBase.TEMPBASAL).size() == 0)
tempsLabel.setVisibility(View.GONE);
profileDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInListByInterface(ProfileInterface.class, PluginBase.BGSOURCE), PluginBase.PROFILE);
profileListView.setAdapter(profileDataAdapter);
setListViewHeightBasedOnChildren(profileListView);
apsDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsList(PluginBase.APS), PluginBase.APS);
apsDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInList(PluginBase.APS), PluginBase.APS);
apsListView.setAdapter(apsDataAdapter);
setListViewHeightBasedOnChildren(apsListView);
if (MainApp.getSpecificPluginsList(PluginBase.APS).size() == 0)
if (MainApp.getSpecificPluginsVisibleInList(PluginBase.APS).size() == 0)
apsLabel.setVisibility(View.GONE);
constraintsDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class), PluginBase.CONSTRAINTS);
constraintsDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInListByInterface(ConstraintsInterface.class, PluginBase.BGSOURCE), PluginBase.CONSTRAINTS);
constraintsListView.setAdapter(constraintsDataAdapter);
setListViewHeightBasedOnChildren(constraintsListView);
generalDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsList(PluginBase.GENERAL), PluginBase.GENERAL);
if (MainApp.getSpecificPluginsVisibleInList(PluginBase.CONSTRAINTS).size() == 0)
constraintsLabel.setVisibility(View.GONE);
generalDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInList(PluginBase.GENERAL), PluginBase.GENERAL);
generalListView.setAdapter(generalDataAdapter);
setListViewHeightBasedOnChildren(generalListView);
@ -175,18 +201,18 @@ public class ConfigBuilderFragment extends Fragment implements FragmentBase {
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
public View getView(int position, View view, ViewGroup parent) {
PluginViewHolder holder = null;
if (convertView == null) {
convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.configbuilder_simpleitem, null);
if (view == null) {
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.configbuilder_simpleitem, null);
holder = new PluginViewHolder();
holder.name = (TextView) convertView.findViewById(R.id.configbuilder_simpleitem_name);
holder.checkboxEnabled = (CheckBox) convertView.findViewById(R.id.configbuilder_simpleitem_checkboxenabled);
holder.checkboxVisible = (CheckBox) convertView.findViewById(R.id.configbuilder_simpleitem_checkboxvisible);
convertView.setTag(holder);
holder.name = (TextView) view.findViewById(R.id.configbuilder_simpleitem_name);
holder.checkboxEnabled = (CheckBox) view.findViewById(R.id.configbuilder_simpleitem_checkboxenabled);
holder.checkboxVisible = (CheckBox) view.findViewById(R.id.configbuilder_simpleitem_checkboxvisible);
view.setTag(holder);
holder.checkboxEnabled.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
@ -197,7 +223,9 @@ public class ConfigBuilderFragment extends Fragment implements FragmentBase {
onEnabledCategoryChanged(plugin, type);
configBuilderPlugin.storeSettings();
MainApp.bus().post(new EventRefreshGui(true));
MainApp.bus().post(new EventConfigBuilderChange());
getPlugin().logPluginStatus();
Answers.getInstance().logCustom(new CustomEvent("ConfigurationChange"));
}
});
@ -212,7 +240,7 @@ public class ConfigBuilderFragment extends Fragment implements FragmentBase {
}
});
} else {
holder = (PluginViewHolder) convertView.getTag();
holder = (PluginViewHolder) view.getTag();
}
PluginBase plugin = pluginList.get(position);
@ -232,8 +260,12 @@ public class ConfigBuilderFragment extends Fragment implements FragmentBase {
holder.checkboxVisible.setEnabled(false);
}
if (!plugin.hasFragment()) {
holder.checkboxVisible.setVisibility(View.INVISIBLE);
}
// Hide enabled control and force enabled plugin if there is only one plugin available
if (type == PluginBase.PUMP || type == PluginBase.TREATMENT || type == PluginBase.TEMPBASAL || type == PluginBase.PROFILE)
if (type == PluginBase.INSULIN || type == PluginBase.PUMP || type == PluginBase.TREATMENT || type == PluginBase.TEMPBASAL || type == PluginBase.PROFILE)
if (pluginList.size() < 2) {
holder.checkboxEnabled.setEnabled(false);
plugin.setFragmentEnabled(type, true);
@ -264,7 +296,7 @@ public class ConfigBuilderFragment extends Fragment implements FragmentBase {
}
}
return convertView;
return view;
}
@ -279,6 +311,9 @@ public class ConfigBuilderFragment extends Fragment implements FragmentBase {
case PluginBase.LOOP:
break;
// Single selection allowed
case PluginBase.INSULIN:
pluginsInCategory = MainApp.getSpecificPluginsListByInterface(InsulinInterface.class);
break;
case PluginBase.APS:
pluginsInCategory = MainApp.getSpecificPluginsListByInterface(APSInterface.class);
break;
@ -308,6 +343,8 @@ public class ConfigBuilderFragment extends Fragment implements FragmentBase {
} else { // enable first plugin in list
if (type == PluginBase.PUMP)
MainApp.getSpecificPlugin(VirtualPumpPlugin.class).setFragmentEnabled(type, true);
else if (type == PluginBase.INSULIN)
MainApp.getSpecificPlugin(InsulinFastactingPlugin.class).setFragmentEnabled(type, true);
else if (type == PluginBase.PROFILE)
MainApp.getSpecificPlugin(NSProfilePlugin.class).setFragmentEnabled(type, true);
else

View file

@ -9,8 +9,6 @@ import android.preference.PreferenceManager;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import com.squareup.otto.Subscribe;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
@ -18,10 +16,6 @@ import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.MainApp;
@ -31,19 +25,19 @@ import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.db.TempBasal;
import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.events.EventBolusRequested;
import info.nightscout.androidaps.events.EventNewBG;
import info.nightscout.androidaps.events.EventTempBasalChange;
import info.nightscout.androidaps.events.EventTreatmentChange;
import info.nightscout.androidaps.interfaces.APSInterface;
import info.nightscout.androidaps.interfaces.BgSourceInterface;
import info.nightscout.androidaps.interfaces.ConstraintsInterface;
import info.nightscout.androidaps.interfaces.InsulinInterface;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.ProfileInterface;
import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.interfaces.TempBasalsInterface;
import info.nightscout.androidaps.interfaces.TreatmentsInterface;
import info.nightscout.androidaps.plugins.DanaR.comm.MsgError;
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgError;
import info.nightscout.androidaps.plugins.Loop.APSResult;
import info.nightscout.androidaps.plugins.Loop.DeviceStatus;
import info.nightscout.androidaps.plugins.Loop.LoopPlugin;
@ -52,11 +46,14 @@ import info.nightscout.androidaps.plugins.OpenAPSMA.DetermineBasalResultMA;
import info.nightscout.androidaps.plugins.Overview.Dialogs.BolusProgressDialog;
import info.nightscout.androidaps.plugins.Overview.Dialogs.BolusProgressHelperActivity;
import info.nightscout.androidaps.plugins.Overview.Notification;
import info.nightscout.androidaps.plugins.Overview.events.EventDismissBolusprogressIfRunning;
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
import info.nightscout.client.data.DbLogger;
import info.nightscout.client.data.NSProfile;
import info.nightscout.androidaps.plugins.NSClientInternal.data.DbLogger;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile;
import info.nightscout.utils.BatteryLevel;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.SP;
/**
* Created by mike on 05.08.2016.
@ -71,6 +68,7 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
static TempBasalsInterface activeTempBasals;
static APSInterface activeAPS;
static LoopPlugin activeLoop;
static InsulinInterface activeInsulin;
static public String nightscoutVersionName = "";
static public Integer nightscoutVersionCode = 0;
@ -79,9 +77,6 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
static ArrayList<PluginBase> pluginList;
private static final ScheduledExecutorService worker = Executors.newSingleThreadScheduledExecutor();
private static ScheduledFuture<?> scheduledPost = null;
PowerManager.WakeLock mWakeLock;
public ConfigBuilderPlugin() {
@ -132,6 +127,16 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
return false;
}
@Override
public boolean hasFragment() {
return true;
}
@Override
public boolean showInList(int type) {
return false;
}
@Override
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
// Always enabled
@ -179,7 +184,7 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
if (SP.contains(settingEnabled))
p.setFragmentEnabled(type, SP.getBoolean(settingEnabled, true));
if (SP.contains(settingVisible))
p.setFragmentVisible(type, SP.getBoolean(settingVisible, true));
p.setFragmentVisible(type, SP.getBoolean(settingVisible, true) && SP.getBoolean(settingEnabled, true));
} catch (Exception e) {
e.printStackTrace();
}
@ -205,6 +210,10 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
return activeTempBasals;
}
public static InsulinInterface getActiveInsulin() {
return activeInsulin;
}
public static APSInterface getActiveAPS() {
return activeAPS;
}
@ -224,7 +233,8 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
(p.isEnabled(6) ? " PUMP" : "") +
(p.isEnabled(7) ? " CONSTRAINTS" : "") +
(p.isEnabled(8) ? " LOOP" : "") +
(p.isEnabled(9) ? " BGSOURCE" : "")
(p.isEnabled(9) ? " BGSOURCE" : "") +
(p.isEnabled(10) ? " INSULIN" : "")
);
}
}
@ -245,7 +255,18 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
}
}
// PluginBase.PROFILE
// PluginBase.INSULIN
pluginsInCategory = MainApp.getSpecificPluginsListByInterface(InsulinInterface.class);
activeInsulin = (InsulinInterface) getTheOneEnabledInArray(pluginsInCategory, PluginBase.INSULIN);
if (Config.logConfigBuilder)
log.debug("Selected insulin interface: " + ((PluginBase) activeInsulin).getName());
for (PluginBase p : pluginsInCategory) {
if (!p.getName().equals(((PluginBase) activeInsulin).getName())) {
p.setFragmentVisible(PluginBase.INSULIN, false);
}
}
// PluginBase.PROFILE
pluginsInCategory = MainApp.getSpecificPluginsListByInterface(ProfileInterface.class);
activeProfile = (ProfileInterface) getTheOneEnabledInArray(pluginsInCategory, PluginBase.PROFILE);
if (Config.logConfigBuilder)
@ -270,7 +291,7 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
// PluginBase.PUMP
pluginsInCategory = MainApp.getSpecificPluginsList(PluginBase.PUMP);
activePump = (PumpInterface) getTheOneEnabledInArray(pluginsInCategory, PluginBase.PUMP);
if (Config.logConfigBuilder)
if (Config.logConfigBuilder && activePump != null)
log.debug("Selected pump interface: " + ((PluginBase) activePump).getName());
for (PluginBase p : pluginsInCategory) {
if (!p.getName().equals(((PluginBase) activePump).getName())) {
@ -294,7 +315,7 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
// PluginBase.TEMPBASAL
pluginsInCategory = MainApp.getSpecificPluginsList(PluginBase.TEMPBASAL);
activeTempBasals = (TempBasalsInterface) getTheOneEnabledInArray(pluginsInCategory, PluginBase.TEMPBASAL);
if (Config.logConfigBuilder)
if (Config.logConfigBuilder && activeTempBasals != null)
log.debug("Selected tempbasal interface: " + ((PluginBase) activeTempBasals).getName());
for (PluginBase p : pluginsInCategory) {
if (!p.getName().equals(((PluginBase) activeTempBasals).getName())) {
@ -338,27 +359,37 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
*/
@Override
public boolean isInitialized() {
return activePump.isInitialized();
if (activePump != null)
return activePump.isInitialized();
else return true;
}
@Override
public boolean isSuspended() {
return activePump.isSuspended();
if (activePump != null)
return activePump.isSuspended();
else return false;
}
@Override
public boolean isBusy() {
return activePump.isBusy();
if (activePump != null)
return activePump.isBusy();
else return false;
}
@Override
public boolean isTempBasalInProgress() {
return activePump.isTempBasalInProgress();
if (activePump != null)
return activePump.isTempBasalInProgress();
else return false;
}
@Override
public boolean isExtendedBoluslInProgress() {
return activePump.isExtendedBoluslInProgress();
if (activePump != null)
return activePump.isExtendedBoluslInProgress();
else return false;
}
@Override
@ -379,147 +410,195 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
if (isThisProfileSet(profile)) {
log.debug("Correct profile already set");
return NOT_NEEDED;
} else {
} else if (activePump != null) {
return activePump.setNewBasalProfile(profile);
}
} else
return SUCCESS;
}
@Override
public boolean isThisProfileSet(NSProfile profile) {
return activePump.isThisProfileSet(profile);
if (activePump != null)
return activePump.isThisProfileSet(profile);
else return true;
}
@Override
public Date lastStatusTime() {
return activePump.lastStatusTime();
public Date lastDataTime() {
if (activePump != null)
return activePump.lastDataTime();
else return new Date();
}
@Override
public void updateStatus(String reason) {
activePump.updateStatus(reason);
public void refreshDataFromPump(String reason) {
if (activePump != null)
activePump.refreshDataFromPump(reason);
}
@Override
public double getBaseBasalRate() {
return activePump.getBaseBasalRate();
if (activePump != null)
return activePump.getBaseBasalRate();
else
return 0d;
}
@Override
public double getTempBasalAbsoluteRate() {
return activePump.getTempBasalAbsoluteRate();
if (activePump != null)
return activePump.getTempBasalAbsoluteRate();
else
return 0d;
}
@Override
public double getTempBasalRemainingMinutes() {
return activePump.getTempBasalRemainingMinutes();
if (activePump != null)
return activePump.getTempBasalRemainingMinutes();
else
return 0d;
}
@Override
public TempBasal getTempBasal(Date time) {
return activePump.getTempBasal(time);
if (activePump != null)
return activePump.getTempBasal(time);
else
return null;
}
@Override
public TempBasal getTempBasal() {
return activePump.getTempBasal();
if (activePump != null)
return activePump.getTempBasal();
else
return null;
}
@Override
public TempBasal getExtendedBolus() {
return activePump.getExtendedBolus();
if (activePump != null)
return activePump.getExtendedBolus();
else
return null;
}
public PumpEnactResult deliverTreatmentFromBolusWizard(Context context, Double insulin, Integer carbs, Double glucose, String glucoseType, int carbTime, JSONObject boluscalc) {
public PumpEnactResult deliverTreatmentFromBolusWizard(InsulinInterface insulinType, Context context, Double insulin, Integer carbs, Double glucose, String glucoseType, int carbTime, JSONObject boluscalc) {
mWakeLock.acquire();
insulin = applyBolusConstraints(insulin);
carbs = applyCarbsConstraints(carbs);
PumpEnactResult result;
if (activePump != null) {
insulin = applyBolusConstraints(insulin);
carbs = applyCarbsConstraints(carbs);
BolusProgressDialog bolusProgressDialog = null;
if (context != null) {
bolusProgressDialog = new BolusProgressDialog();
bolusProgressDialog.setInsulin(insulin);
bolusProgressDialog.show(((AppCompatActivity) context).getSupportFragmentManager(), "BolusProgress");
}
MainApp.bus().post(new EventBolusRequested(insulin));
PumpEnactResult result = activePump.deliverTreatment(insulin, carbs, context);
BolusProgressDialog.bolusEnded = true;
if (bolusProgressDialog != null && BolusProgressDialog.running) {
try {
bolusProgressDialog.dismiss();
} catch (Exception e) {
e.printStackTrace(); // TODO: handle this better
BolusProgressDialog bolusProgressDialog = null;
if (context != null) {
bolusProgressDialog = new BolusProgressDialog();
bolusProgressDialog.setInsulin(insulin);
bolusProgressDialog.show(((AppCompatActivity) context).getSupportFragmentManager(), "BolusProgress");
}
}
if (result.success) {
Treatment t = new Treatment();
t.insulin = result.bolusDelivered;
if (carbTime == 0)
t.carbs = (double) result.carbsDelivered; // with different carbTime record will come back from nightscout
MainApp.bus().post(new EventBolusRequested(insulin));
result = activePump.deliverTreatment(insulinType, insulin, carbs, context);
BolusProgressDialog.bolusEnded = true;
MainApp.bus().post(new EventDismissBolusprogressIfRunning(result));
if (result.success) {
Treatment t = new Treatment(insulinType);
t.insulin = result.bolusDelivered;
if (carbTime == 0)
t.carbs = (double) result.carbsDelivered; // with different carbTime record will come back from nightscout
t.created_at = new Date();
t.mealBolus = result.carbsDelivered > 0;
MainApp.getDbHelper().create(t);
t.setTimeIndex(t.getTimeIndex());
t.carbs = (double) result.carbsDelivered;
uploadBolusWizardRecord(t, glucose, glucoseType, carbTime, boluscalc);
}
} else {
if (Config.logCongigBuilderActions)
log.debug("Creating treatment: " + insulin + " carbs: " + carbs);
Treatment t = new Treatment(insulinType);
t.insulin = insulin;
t.carbs = (double) carbs;
t.created_at = new Date();
t.mealBolus = result.carbsDelivered > 0;
t.mealBolus = t.carbs > 0;
MainApp.getDbHelper().create(t);
t.setTimeIndex(t.getTimeIndex());
t.carbs = (double) result.carbsDelivered;
uploadBolusWizardRecord(t, glucose, glucoseType, carbTime, boluscalc);
t.sendToNSClient();
result = new PumpEnactResult();
result.success = true;
result.bolusDelivered = insulin;
result.carbsDelivered = carbs;
}
mWakeLock.release();
return result;
}
@Override
public PumpEnactResult deliverTreatment(Double insulin, Integer carbs, Context context) {
return deliverTreatment(insulin, carbs, context, true);
public PumpEnactResult deliverTreatment(InsulinInterface insulinType, Double insulin, Integer carbs, Context context) {
return deliverTreatment(insulinType, insulin, carbs, context, true);
}
public PumpEnactResult deliverTreatment(Double insulin, Integer carbs, Context context, boolean createTreatment) {
public PumpEnactResult deliverTreatment(InsulinInterface insulinType, Double insulin, Integer carbs, Context context, boolean createTreatment) {
mWakeLock.acquire();
insulin = applyBolusConstraints(insulin);
carbs = applyCarbsConstraints(carbs);
PumpEnactResult result;
if (activePump != null) {
insulin = applyBolusConstraints(insulin);
carbs = applyCarbsConstraints(carbs);
BolusProgressDialog bolusProgressDialog = null;
if (context != null ) {
bolusProgressDialog = new BolusProgressDialog();
bolusProgressDialog.setInsulin(insulin);
bolusProgressDialog.show(((AppCompatActivity) context).getSupportFragmentManager(), "BolusProgress");
} else {
Intent i = new Intent();
i.putExtra("insulin", insulin.doubleValue());
i.setClass(MainApp.instance(), BolusProgressHelperActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
MainApp.instance().startActivity(i);
}
MainApp.bus().post(new EventBolusRequested(insulin));
PumpEnactResult result = activePump.deliverTreatment(insulin, carbs, context);
BolusProgressDialog.bolusEnded = true;
if (bolusProgressDialog != null && BolusProgressDialog.running) {
try {
bolusProgressDialog.dismiss();
} catch (Exception e) {
e.printStackTrace(); // TODO: handle this better
BolusProgressDialog bolusProgressDialog = null;
if (context != null) {
bolusProgressDialog = new BolusProgressDialog();
bolusProgressDialog.setInsulin(insulin);
bolusProgressDialog.show(((AppCompatActivity) context).getSupportFragmentManager(), "BolusProgress");
} else {
Intent i = new Intent();
i.putExtra("insulin", insulin.doubleValue());
i.setClass(MainApp.instance(), BolusProgressHelperActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
MainApp.instance().startActivity(i);
}
}
if (Config.logCongigBuilderActions)
log.debug("deliverTreatment insulin: " + insulin + " carbs: " + carbs + " success: " + result.success + " enacted: " + result.enacted + " bolusDelivered: " + result.bolusDelivered);
MainApp.bus().post(new EventBolusRequested(insulin));
if (result.success && createTreatment) {
Treatment t = new Treatment();
t.insulin = result.bolusDelivered;
t.carbs = (double) result.carbsDelivered;
result = activePump.deliverTreatment(insulinType, insulin, carbs, context);
BolusProgressDialog.bolusEnded = true;
MainApp.bus().post(new EventDismissBolusprogressIfRunning(result));
if (Config.logCongigBuilderActions)
log.debug("deliverTreatment insulin: " + insulin + " carbs: " + carbs + " success: " + result.success + " enacted: " + result.enacted + " bolusDelivered: " + result.bolusDelivered);
if (result.success && createTreatment) {
Treatment t = new Treatment(insulinType);
t.insulin = result.bolusDelivered;
t.carbs = (double) result.carbsDelivered;
t.created_at = new Date();
t.mealBolus = t.carbs > 0;
MainApp.getDbHelper().create(t);
t.setTimeIndex(t.getTimeIndex());
t.sendToNSClient();
}
} else {
if (Config.logCongigBuilderActions)
log.debug("Creating treatment: " + insulin + " carbs: " + carbs);
Treatment t = new Treatment(insulinType);
t.insulin = insulin;
t.carbs = (double) carbs;
t.created_at = new Date();
t.mealBolus = t.carbs > 0;
MainApp.getDbHelper().create(t);
t.setTimeIndex(t.getTimeIndex());
t.sendToNSClient();
result = new PumpEnactResult();
result.success = true;
result.bolusDelivered = insulin;
result.carbsDelivered = carbs;
}
mWakeLock.release();
return result;
@ -682,7 +761,7 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
public String deviceID() {
if (activePump != null)
return activePump.deviceID();
else return "Unknown";
else return "No Pump active!";
}
@Override
@ -825,11 +904,6 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
return maxIobAfterConstrain;
}
@Subscribe
public void onStatusEvent(final EventNewBG ev) {
uploadDeviceStatus(120);
}
public void uploadTempBasalStartAbsolute(Double absolute, double durationInMinutes) {
try {
Context context = MainApp.instance().getApplicationContext();
@ -933,7 +1007,7 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
}
}
public void doUploadDeviceStatus() {
public void uploadDeviceStatus() {
DeviceStatus deviceStatus = new DeviceStatus();
try {
LoopPlugin.LastRun lastRun = LoopPlugin.lastRun;
@ -966,39 +1040,27 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
requested.put("temp", "absolute");
deviceStatus.enacted.put("requested", requested);
}
} else {
log.debug("OpenAPS data too old to upload");
}
if (activePump != null) {
deviceStatus.device = "openaps://" + deviceID();
JSONObject pumpstatus = getJSONStatus();
if (pumpstatus != null) {
deviceStatus.pump = getJSONStatus();
deviceStatus.pump = pumpstatus;
}
deviceStatus.created_at = DateUtil.toISOString(new Date());
deviceStatus.sendToNSClient();
}
int batteryLevel = BatteryLevel.getBatteryLevel();
deviceStatus.uploaderBattery = batteryLevel;
deviceStatus.created_at = DateUtil.toISOString(new Date());
deviceStatus.sendToNSClient();
} catch (JSONException e) {
e.printStackTrace();
}
}
static public void uploadDeviceStatus(int sec) {
class PostRunnable implements Runnable {
public void run() {
MainApp.getConfigBuilder().doUploadDeviceStatus();
scheduledPost = null;
}
}
// prepare task for execution
// cancel waiting task to prevent sending multiple posts
if (scheduledPost != null)
scheduledPost.cancel(false);
Runnable task = new PostRunnable();
scheduledPost = worker.schedule(task, sec, TimeUnit.SECONDS);
log.debug("Scheduling devicestatus upload in " + sec + " sec");
}
public void uploadBolusWizardRecord(Treatment t, double glucose, String glucoseType, int carbTime, JSONObject boluscalc) {
JSONObject data = new JSONObject();
try {
@ -1088,24 +1150,26 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
}
public void uploadAppStart() {
Context context = MainApp.instance().getApplicationContext();
Bundle bundle = new Bundle();
bundle.putString("action", "dbAdd");
bundle.putString("collection", "treatments");
JSONObject data = new JSONObject();
try {
data.put("eventType", "Note");
data.put("created_at", DateUtil.toISOString(new Date()));
data.put("notes", MainApp.sResources.getString(R.string.androidaps_start));
} catch (JSONException e) {
e.printStackTrace();
if (SP.getBoolean(R.string.key_ns_logappstartedevent, true)) {
Context context = MainApp.instance().getApplicationContext();
Bundle bundle = new Bundle();
bundle.putString("action", "dbAdd");
bundle.putString("collection", "treatments");
JSONObject data = new JSONObject();
try {
data.put("eventType", "Note");
data.put("created_at", DateUtil.toISOString(new Date()));
data.put("notes", MainApp.sResources.getString(R.string.androidaps_start));
} catch (JSONException e) {
e.printStackTrace();
}
bundle.putString("data", data.toString());
Intent intent = new Intent(Intents.ACTION_DATABASE);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
context.sendBroadcast(intent);
DbLogger.dbAdd(intent, data.toString(), ConfigBuilderPlugin.class);
}
bundle.putString("data", data.toString());
Intent intent = new Intent(Intents.ACTION_DATABASE);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
context.sendBroadcast(intent);
DbLogger.dbAdd(intent, data.toString(), ConfigBuilderPlugin.class);
}
}

View file

@ -1,4 +1,4 @@
package info.nightscout.androidaps.plugins.Objectives;
package info.nightscout.androidaps.plugins.ConstraintsObjectives;
import android.app.Activity;
import android.content.Context;
@ -7,7 +7,6 @@ import android.support.v4.app.Fragment;
import android.support.v7.widget.CardView;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.Layout;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@ -24,9 +23,8 @@ import java.util.List;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.interfaces.FragmentBase;
public class ObjectivesFragment extends Fragment implements View.OnClickListener, FragmentBase {
public class ObjectivesFragment extends Fragment {
private static Logger log = LoggerFactory.getLogger(ObjectivesFragment.class);
private static ObjectivesPlugin objectivesPlugin;
@ -44,15 +42,6 @@ public class ObjectivesFragment extends Fragment implements View.OnClickListener
LinearLayout fake_layout;
TextView reset;
@Override
public void onClick(View v) {
int id = v.getId();
switch (id) {
default:
break;
}
}
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ObjectiveViewHolder> {
List<ObjectivesPlugin.Objective> objectives;
@ -237,16 +226,4 @@ public class ObjectivesFragment extends Fragment implements View.OnClickListener
});
}
@Override
public void onPause() {
super.onPause();
MainApp.bus().unregister(this);
}
@Override
public void onResume() {
super.onResume();
MainApp.bus().register(this);
}
}

View file

@ -1,4 +1,4 @@
package info.nightscout.androidaps.plugins.Objectives;
package info.nightscout.androidaps.plugins.ConstraintsObjectives;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
@ -16,7 +16,7 @@ import info.nightscout.androidaps.R;
import info.nightscout.androidaps.interfaces.ConstraintsInterface;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.plugins.Loop.LoopPlugin;
import info.nightscout.utils.SafeParse;
import info.nightscout.utils.SP;
/**
* Created by mike on 05.08.2016.
@ -76,6 +76,16 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface {
return true;
}
@Override
public boolean hasFragment() {
return true;
}
@Override
public boolean showInList(int type) {
return true;
}
@Override
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
}
@ -152,7 +162,7 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface {
MainApp.sResources.getString(R.string.objectives_0_objective),
MainApp.sResources.getString(R.string.objectives_0_gate),
new Date(0),
1, // 1 day
0, // 0 day
new Date(0)));
objectives.add(new Objective(1,
MainApp.sResources.getString(R.string.objectives_1_objective),
@ -211,20 +221,19 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface {
}
void loadProgress() {
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
for (int num = 0; num < objectives.size(); num++) {
Objective o = objectives.get(num);
try {
o.started = new Date(SafeParse.stringToLong(settings.getString("Objectives" + num + "started", "0")));
o.accomplished = new Date(SafeParse.stringToLong(settings.getString("Objectives" + num + "accomplished", "0")));
o.started = new Date(SP.getLong("Objectives" + num + "started", 0L));
o.accomplished = new Date(SP.getLong("Objectives" + num + "accomplished", 0L));
} catch (Exception e) {
e.printStackTrace();
}
}
bgIsAvailableInNS = settings.getBoolean("Objectives" + "bgIsAvailableInNS", false);
pumpStatusIsAvailableInNS = settings.getBoolean("Objectives" + "pumpStatusIsAvailableInNS", false);
bgIsAvailableInNS = SP.getBoolean("Objectives" + "bgIsAvailableInNS", false);
pumpStatusIsAvailableInNS = SP.getBoolean("Objectives" + "pumpStatusIsAvailableInNS", false);
try {
manualEnacts = SafeParse.stringToInt(settings.getString("Objectives" + "manualEnacts", "0"));
manualEnacts = SP.getInt("Objectives" + "manualEnacts", 0);
} catch (Exception e) {
e.printStackTrace();
}

View file

@ -1,4 +1,4 @@
package info.nightscout.androidaps.plugins.SafetyFragment;
package info.nightscout.androidaps.plugins.ConstraintsSafety;
import android.support.v4.app.Fragment;
@ -6,9 +6,7 @@ import android.support.v4.app.Fragment;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.interfaces.FragmentBase;
public class SafetyFragment extends Fragment implements FragmentBase{
public class SafetyFragment extends Fragment {
private static Logger log = LoggerFactory.getLogger(SafetyFragment.class);
private static SafetyPlugin safetyPlugin = new SafetyPlugin();

View file

@ -1,7 +1,4 @@
package info.nightscout.androidaps.plugins.SafetyFragment;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
package info.nightscout.androidaps.plugins.ConstraintsSafety;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -13,9 +10,10 @@ import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.interfaces.ConstraintsInterface;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.client.data.NSProfile;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile;
import info.nightscout.utils.HardLimits;
import info.nightscout.utils.Round;
import info.nightscout.utils.SafeParse;
import info.nightscout.utils.SP;
/**
* Created by mike on 05.08.2016.
@ -59,6 +57,16 @@ public class SafetyPlugin implements PluginBase, ConstraintsInterface {
return true;
}
@Override
public boolean hasFragment() {
return false;
}
@Override
public boolean showInList(int type) {
return false;
}
@Override
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
@ -78,7 +86,6 @@ public class SafetyPlugin implements PluginBase, ConstraintsInterface {
**/
@Override
public boolean isClosedModeEnabled() {
SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
String mode = SP.getString("aps_mode", "open");
return mode.equals("closed") && BuildConfig.CLOSEDLOOP;
}
@ -96,15 +103,14 @@ public class SafetyPlugin implements PluginBase, ConstraintsInterface {
@Override
public Double applyBasalConstraints(Double absoluteRate) {
Double origAbsoluteRate = absoluteRate;
SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
Double maxBasal = SafeParse.stringToDouble(SP.getString("openapsma_max_basal", "1"));
Double maxBasal = SP.getDouble("openapsma_max_basal", 1d);
NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile();
if (profile == null) return absoluteRate;
if (absoluteRate < 0) absoluteRate = 0d;
Integer maxBasalMult = SafeParse.stringToInt(SP.getString("openapsama_current_basal_safety_multiplier", "4"));
Integer maxBasalFromDaily = SafeParse.stringToInt(SP.getString("openapsama_max_daily_safety_multiplier", "3"));
Integer maxBasalMult = SP.getInt("openapsama_current_basal_safety_multiplier", 4);
Integer maxBasalFromDaily = SP.getInt("openapsama_max_daily_safety_multiplier", 3);
// Check percentRate but absolute rate too, because we know real current basal in pump
Double origRate = absoluteRate;
if (absoluteRate > maxBasal) {
@ -128,8 +134,7 @@ public class SafetyPlugin implements PluginBase, ConstraintsInterface {
@Override
public Integer applyBasalConstraints(Integer percentRate) {
Integer origPercentRate = percentRate;
SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
Double maxBasal = SafeParse.stringToDouble(SP.getString("openapsma_max_basal", "1"));
Double maxBasal = SP.getDouble("openapsma_max_basal", 1d);
NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile();
if (profile == null) return percentRate;
@ -142,8 +147,8 @@ public class SafetyPlugin implements PluginBase, ConstraintsInterface {
if (absoluteRate < 0) absoluteRate = 0d;
Integer maxBasalMult = SafeParse.stringToInt(SP.getString("openapsama_current_basal_safety_multiplier", "4"));
Integer maxBasalFromDaily = SafeParse.stringToInt(SP.getString("openapsama_max_daily_safety_multiplier", "3"));
Integer maxBasalMult = SP.getInt("openapsama_current_basal_safety_multiplier", 4);
Integer maxBasalFromDaily = SP.getInt("openapsama_max_daily_safety_multiplier", 3);
// Check percentRate but absolute rate too, because we know real current basal in pump
Double origRate = absoluteRate;
if (absoluteRate > maxBasal) {
@ -174,24 +179,22 @@ public class SafetyPlugin implements PluginBase, ConstraintsInterface {
@Override
public Double applyBolusConstraints(Double insulin) {
SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
try {
Double maxBolus = SafeParse.stringToDouble(SP.getString("treatmentssafety_maxbolus", "3"));
Double maxBolus = SP.getDouble("treatmentssafety_maxbolus", 3d);
if (insulin < 0) insulin = 0d;
if (insulin > maxBolus) insulin = maxBolus;
} catch (Exception e) {
insulin = 0d;
}
if (insulin > BuildConfig.MAXBOLUS) insulin = Double.valueOf(BuildConfig.MAXBOLUS);
if (insulin > HardLimits.maxBolus()) insulin = HardLimits.maxBolus();
return insulin;
}
@Override
public Integer applyCarbsConstraints(Integer carbs) {
SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
try {
Integer maxCarbs = SafeParse.stringToInt(SP.getString("treatmentssafety_maxcarbs", "48"));
Integer maxCarbs = SP.getInt("treatmentssafety_maxcarbs", 48);
if (carbs < 0) carbs = 0;
if (carbs > maxCarbs) carbs = maxCarbs;

View file

@ -1,23 +0,0 @@
package info.nightscout.androidaps.plugins.DanaR.events;
public class EventDanaRConnectionStatus {
public static final int CONNECTING = 0;
public static final int CONNECTED = 1;
public static final int DISCONNECTED = 2;
public static final int PERFORMING = 3;
public int sStatus = DISCONNECTED;
public int sSecondsElapsed = 0;
public String sAction = "";
public EventDanaRConnectionStatus(int status, int secondsElapsed) {
sStatus = status;
sSecondsElapsed = secondsElapsed;
}
public EventDanaRConnectionStatus(int status, int secondsElapsed, String action) {
sStatus = status;
sSecondsElapsed = secondsElapsed;
sAction = action;
}
}

View file

@ -0,0 +1,78 @@
package info.nightscout.androidaps.plugins.InsulinFastacting;
import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import com.jjoe64.graphview.GraphView;
import com.jjoe64.graphview.series.DataPoint;
import com.jjoe64.graphview.series.LineGraphSeries;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import info.nightscout.androidaps.data.Iob;
import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.interfaces.InsulinInterface;
import info.nightscout.androidaps.plugins.Overview.graphExtensions.TimeAsXAxisLabelFormatter;
/**
* Created by mike on 21.04.2017.
*/
public class ActivityGraph extends GraphView {
Context context;
public ActivityGraph(Context context) {
super(context);
this.context = context;
}
public ActivityGraph(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
}
public void show(InsulinInterface insulin) {
double dia = insulin.getDia();
int hours = (int) Math.floor(dia + 1);
Treatment t = new Treatment(insulin);
t.created_at = new Date(0);
t.timeIndex = 0;
t.insulin = 1d;
LineGraphSeries<DataPoint> activitySeries = null;
LineGraphSeries<DataPoint> iobSeries = null;
List<DataPoint> activityArray = new ArrayList<DataPoint>();
List<DataPoint> iobArray = new ArrayList<DataPoint>();
for (long time = 0; time <= hours * 60 * 60 * 1000; time += 5 * 60 * 1000L) {
Iob iob = insulin.iobCalc(t, time, dia);
activityArray.add(new DataPoint(time / 60 / 1000, iob.activityContrib));
iobArray.add(new DataPoint(time / 60 / 1000, iob.iobContrib));
}
DataPoint[] activityDataPoints = new DataPoint[activityArray.size()];
activityDataPoints = activityArray.toArray(activityDataPoints);
addSeries(activitySeries = new LineGraphSeries<DataPoint>(activityDataPoints));
activitySeries.setThickness(8);
getViewport().setXAxisBoundsManual(true);
getViewport().setMinX(0);
getViewport().setMaxX(hours * 60);
getGridLabelRenderer().setNumHorizontalLabels(hours + 1);
getGridLabelRenderer().setHorizontalAxisTitle("[min]");
DataPoint[] iobDataPoints = new DataPoint[iobArray.size()];
iobDataPoints = iobArray.toArray(iobDataPoints);
getSecondScale().addSeries(iobSeries = new LineGraphSeries<DataPoint>(iobDataPoints));
iobSeries.setDrawBackground(true);
iobSeries.setColor(Color.MAGENTA);
iobSeries.setBackgroundColor(Color.argb(70, 255, 0, 255));
getSecondScale().setMinY(0);
getSecondScale().setMaxY(1);
}
}

View file

@ -0,0 +1,46 @@
package info.nightscout.androidaps.plugins.InsulinFastacting;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
/**
* Created by mike on 17.04.2017.
*/
public class InsulinFastactingFragment extends Fragment {
static InsulinFastactingPlugin insulinFastactingPlugin = new InsulinFastactingPlugin();
static public InsulinFastactingPlugin getPlugin() {
return insulinFastactingPlugin;
}
TextView insulinName;
TextView insulinComment;
TextView insulinDia;
ActivityGraph insulinGraph;
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.insulin_fragment, container, false);
insulinName = (TextView) view.findViewById(R.id.insulin_name);
insulinComment = (TextView) view.findViewById(R.id.insulin_comment);
insulinDia = (TextView) view.findViewById(R.id.insulin_dia);
insulinGraph = (ActivityGraph) view.findViewById(R.id.insuling_graph);
insulinName.setText(insulinFastactingPlugin.getFriendlyName());
insulinComment.setText(insulinFastactingPlugin.getComment());
insulinDia.setText(MainApp.sResources.getText(R.string.dia) + " " + new Double(insulinFastactingPlugin.getDia()).toString() + "h");
insulinGraph.show(insulinFastactingPlugin);
return view;
}
}

View file

@ -0,0 +1,129 @@
package info.nightscout.androidaps.plugins.InsulinFastacting;
import java.util.Date;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Iob;
import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.interfaces.InsulinInterface;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.ProfileInterface;
/**
* Created by mike on 17.04.2017.
*/
public class InsulinFastactingPlugin implements PluginBase, InsulinInterface {
private static boolean fragmentEnabled = true;
private static boolean fragmentVisible = false;
@Override
public int getType() {
return INSULIN;
}
@Override
public String getFragmentClass() {
return InsulinFastactingFragment.class.getName();
}
@Override
public String getName() {
return MainApp.sResources.getString(R.string.fastactinginsulin);
}
@Override
public String getNameShort() {
return MainApp.sResources.getString(R.string.insulin_shortname);
}
@Override
public boolean isEnabled(int type) {
return type == INSULIN && fragmentEnabled;
}
@Override
public boolean isVisibleInTabs(int type) {
return type == INSULIN && fragmentVisible;
}
@Override
public boolean canBeHidden(int type) {
return true;
}
@Override
public boolean hasFragment() {
return true;
}
@Override
public boolean showInList(int type) {
return true;
}
@Override
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
if (type == INSULIN) this.fragmentEnabled = fragmentEnabled;
}
@Override
public void setFragmentVisible(int type, boolean fragmentVisible) {
if (type == INSULIN) this.fragmentVisible = fragmentVisible;
}
// Insulin interface
@Override
public int getId() {
return FASTACTINGINSULIN;
}
@Override
public String getFriendlyName() {
return MainApp.sResources.getString(R.string.fastactinginsulin);
}
@Override
public String getComment() {
return MainApp.sResources.getString(R.string.fastactinginsulincomment);
}
@Override
public double getDia() {
ProfileInterface profileInterface = MainApp.getConfigBuilder().getActiveProfile();
if (profileInterface.getProfile() != null)
return profileInterface.getProfile().getDia();
return Constants.defaultDIA;
}
@Override
public Iob iobCalc(Treatment treatment, long time, Double dia) {
Iob result = new Iob();
Double scaleFactor = 3.0 / dia;
Double peak = 75d;
Double end = 180d;
if (treatment.insulin != 0d) {
Long bolusTime = treatment.created_at.getTime();
Double minAgo = scaleFactor * (time - bolusTime) / 1000d / 60d;
if (minAgo < peak) {
Double x1 = minAgo / 5d + 1;
result.iobContrib = treatment.insulin * (1 - 0.001852 * x1 * x1 + 0.001852 * x1);
// units: BG (mg/dL) = (BG/U) * U insulin * scalar
result.activityContrib = treatment.insulin * (2 / dia / 60 / peak) * minAgo;
} else if (minAgo < end) {
Double x2 = (minAgo - 75) / 5;
result.iobContrib = treatment.insulin * (0.001323 * x2 * x2 - 0.054233 * x2 + 0.55556);
result.activityContrib = treatment.insulin * (2 / dia / 60 - (minAgo - peak) * 2 / dia / 60 / (60 * 3 - peak));
}
}
return result;
}
}

View file

@ -0,0 +1,47 @@
package info.nightscout.androidaps.plugins.InsulinFastactingProlonged;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.plugins.InsulinFastacting.ActivityGraph;
/**
* Created by mike on 17.04.2017.
*/
public class InsulinFastactingProlongedFragment extends Fragment {
static InsulinFastactingProlongedPlugin insulinFastactingProlongedPlugin = new InsulinFastactingProlongedPlugin();
static public InsulinFastactingProlongedPlugin getPlugin() {
return insulinFastactingProlongedPlugin;
}
TextView insulinName;
TextView insulinComment;
TextView insulinDia;
ActivityGraph insulinGraph;
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.insulin_fragment, container, false);
insulinName = (TextView) view.findViewById(R.id.insulin_name);
insulinComment = (TextView) view.findViewById(R.id.insulin_comment);
insulinDia = (TextView) view.findViewById(R.id.insulin_dia);
insulinGraph = (ActivityGraph) view.findViewById(R.id.insuling_graph);
insulinName.setText(insulinFastactingProlongedPlugin.getFriendlyName());
insulinComment.setText(insulinFastactingProlongedPlugin.getComment());
insulinDia.setText(MainApp.sResources.getText(R.string.dia) + " " + new Double(insulinFastactingProlongedPlugin.getDia()).toString() + "h");
insulinGraph.show(insulinFastactingProlongedPlugin);
return view;
}
}

View file

@ -0,0 +1,134 @@
package info.nightscout.androidaps.plugins.InsulinFastactingProlonged;
import java.util.Date;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Iob;
import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.interfaces.InsulinInterface;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.ProfileInterface;
/**
* Created by mike on 17.04.2017.
*/
public class InsulinFastactingProlongedPlugin implements PluginBase, InsulinInterface {
private static boolean fragmentEnabled = false;
private static boolean fragmentVisible = false;
@Override
public int getType() {
return INSULIN;
}
@Override
public String getFragmentClass() {
return InsulinFastactingProlongedFragment.class.getName();
}
@Override
public String getName() {
return MainApp.sResources.getString(R.string.fastactinginsulinprolonged);
}
@Override
public String getNameShort() {
return MainApp.sResources.getString(R.string.insulin_shortname);
}
@Override
public boolean isEnabled(int type) {
return type == INSULIN && fragmentEnabled;
}
@Override
public boolean isVisibleInTabs(int type) {
return type == INSULIN && fragmentVisible;
}
@Override
public boolean canBeHidden(int type) {
return true;
}
@Override
public boolean hasFragment() {
return true;
}
@Override
public boolean showInList(int type) {
return true;
}
@Override
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
if (type == INSULIN) this.fragmentEnabled = fragmentEnabled;
}
@Override
public void setFragmentVisible(int type, boolean fragmentVisible) {
if (type == INSULIN) this.fragmentVisible = fragmentVisible;
}
// Insulin interface
@Override
public int getId() {
return FASTACTINGINSULINPROLONGED;
}
@Override
public String getFriendlyName() {
return MainApp.sResources.getString(R.string.fastactinginsulinprolonged);
}
@Override
public String getComment() {
return MainApp.sResources.getString(R.string.fastactinginsulincomment);
}
@Override
public double getDia() {
ProfileInterface profileInterface = MainApp.getConfigBuilder().getActiveProfile();
if (profileInterface.getProfile() != null)
return profileInterface.getProfile().getDia();
return Constants.defaultDIA;
}
@Override
public Iob iobCalc(Treatment treatment, long time, Double dia) {
Iob result = new Iob();
//Double scaleFactor = 3.0 / dia;
Double peak = 75d * dia / 6.0;
Double tail = 180d * dia / 6.0;
Double end = 360d * dia / 6.0;
Double Total = 2 * peak + (tail - peak) * 5 / 2 + (end - tail) / 2;
if (treatment.insulin != 0d) {
Long bolusTime = treatment.created_at.getTime();
Double minAgo = (time - bolusTime) / 1000d / 60d;
if (minAgo < peak) {
Double x1 = 6 / dia * minAgo / 5d + 1;
result.iobContrib = treatment.insulin * (1 - 0.0012595 * x1 * x1 + 0.0012595 * x1);
// units: BG (mg/dL) = (BG/U) * U insulin * scalar
result.activityContrib = treatment.insulin * ((2 * peak / Total) * 2 / peak / peak * minAgo);
} else if (minAgo < tail) {
Double x2 = (6 / dia * (minAgo - peak)) / 5;
result.iobContrib = treatment.insulin * (0.00074 * x2 * x2 - 0.0403 * x2 + 0.69772);
result.activityContrib = treatment.insulin * (-((2 * peak / Total) * 2 / peak * 3 / 4) / (tail - peak) * (minAgo - peak) + (2 * peak / Total) * 2 / peak);
} else if (minAgo < end) {
Double x3 = (6 / dia * (minAgo - tail)) / 5;
result.iobContrib = treatment.insulin * (0.0001323 * x3 * x3 - 0.0097 * x3 + 0.17776);
result.activityContrib = treatment.insulin * (-((2 * peak / Total) * 2 / peak * 1 / 4) / (end - tail) * (minAgo - tail) + (2 * peak / Total) * 2 / peak / 4);
}
}
return result;
}
}

View file

@ -0,0 +1,22 @@
package info.nightscout.androidaps.plugins.IobCobCalculator;
import java.util.Date;
/**
* Created by mike on 25.04.2017.
*/
public class AutosensData {
long time = 0L;
String pastSensitivity = "";
double deviation = 0d;
boolean calculateWithDeviation = false;
double absorbed = 0d;
double carbsFromBolus = 0d;
public double cob = 0;
public String log(long time) {
return "AutosensData: " + new Date(time).toLocaleString() + " " + pastSensitivity + " Deviation=" + deviation + " Absorbed=" + absorbed + " CarbsFromBolus=" + carbsFromBolus + " COB=" + cob;
}
}

View file

@ -1,4 +1,4 @@
package info.nightscout.androidaps.plugins.OpenAPSAMA;
package info.nightscout.androidaps.plugins.IobCobCalculator;
import org.json.JSONException;
import org.json.JSONObject;

View file

@ -0,0 +1,16 @@
package info.nightscout.androidaps.plugins.IobCobCalculator;
import android.support.v4.app.Fragment;
/**
* Created by adrian on 17/11/16.
*/
public class IobCobCalculatorFragment extends Fragment {
private static IobCobCalculatorPlugin iobCobCalculatorPlugin = new IobCobCalculatorPlugin();
public static IobCobCalculatorPlugin getPlugin() {
return iobCobCalculatorPlugin;
}
}

View file

@ -0,0 +1,571 @@
package info.nightscout.androidaps.plugins.IobCobCalculator;
import android.os.Handler;
import android.os.HandlerThread;
import android.support.annotation.Nullable;
import android.support.v4.util.LongSparseArray;
import com.squareup.otto.Subscribe;
import org.json.JSONArray;
import org.slf4j.Logger;
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.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.events.EventNewBG;
import info.nightscout.androidaps.events.EventNewBasalProfile;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.TreatmentsInterface;
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.NSClientInternal.data.NSProfile;
import info.nightscout.utils.Round;
import info.nightscout.utils.SP;
import info.nightscout.utils.SafeParse;
/**
* Created by mike on 24.04.2017.
*/
public class IobCobCalculatorPlugin implements PluginBase {
private static Logger log = LoggerFactory.getLogger(IobCobCalculatorPlugin.class);
private static LongSparseArray<IobTotal> iobTable = new LongSparseArray<>(); // oldest at index 0
private static LongSparseArray<AutosensData> autosensDataTable = new LongSparseArray<>(); // oldest at index 0
private static volatile List<BgReading> bgReadings = null; // newest at index 0
private static volatile List<BgReading> bucketed_data = null;
private static double dia = Constants.defaultDIA;
private static Handler sHandler = null;
private static HandlerThread sHandlerThread = null;
private static Object dataLock = new Object();
@Override
public int getType() {
return GENERAL;
}
@Override
public String getFragmentClass() {
return IobCobCalculatorFragment.class.getName();
}
@Override
public String getName() {
return "IOB COB Calculator";
}
@Override
public String getNameShort() {
return "IOC";
}
@Override
public boolean isEnabled(int type) {
return type == GENERAL;
}
@Override
public boolean isVisibleInTabs(int type) {
return false;
}
@Override
public boolean canBeHidden(int type) {
return false;
}
@Override
public boolean hasFragment() {
return false;
}
@Override
public boolean showInList(int type) {
return false;
}
@Override
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
}
@Override
public void setFragmentVisible(int type, boolean fragmentVisible) {
}
public IobCobCalculatorPlugin() {
MainApp.bus().register(this);
if (sHandlerThread == null) {
sHandlerThread = new HandlerThread(IobCobCalculatorPlugin.class.getSimpleName());
sHandlerThread.start();
sHandler = new Handler(sHandlerThread.getLooper());
}
onNewBg(new EventNewBG());
}
@Nullable
public static List<BgReading> getBucketedData(long fromTime) {
//log.debug("Locking getBucketedData");
synchronized (dataLock) {
if (bucketed_data == null) {
log.debug("No bucketed data available");
return null;
}
int index = indexNewerThan(fromTime);
if (index > -1) {
List<BgReading> part = bucketed_data.subList(0, index);
log.debug("Bucketed data striped off: " + part.size() + "/" + bucketed_data.size());
return part;
}
}
//log.debug("Releasing getBucketedData");
return null;
}
private static int indexNewerThan(long time) {
for (int index = 0; index < bucketed_data.size(); index++) {
if (bucketed_data.get(index).timeIndex < time)
return index - 1;
}
return -1;
}
public static long roundUpTime(long time) {
if (time % 60000 == 0)
return time;
long rouded = (time / 60000 + 1) * 60000;
return rouded;
}
private void loadBgData() {
//log.debug("Locking loadBgData");
synchronized (dataLock) {
onNewProfile(new EventNewBasalProfile(null));
bgReadings = MainApp.getDbHelper().getBgreadingsDataFromTime((long) (new Date().getTime() - 60 * 60 * 1000L * (24 + dia)), false);
log.debug("BG data loaded. Size: " + bgReadings.size());
}
//log.debug("Releasing loadBgData");
}
public void createBucketedData() {
//log.debug("Locking createBucketedData");
synchronized (dataLock) {
if (bgReadings == null || bgReadings.size() < 3) {
bucketed_data = null;
return;
}
bucketed_data = new ArrayList<>();
bucketed_data.add(bgReadings.get(0));
int j = 0;
for (int i = 1; i < bgReadings.size(); ++i) {
long bgTime = bgReadings.get(i).getTimeIndex();
long lastbgTime = bgReadings.get(i - 1).getTimeIndex();
//log.error("Processing " + i + ": " + new Date(bgTime).toString() + " " + bgReadings.get(i).value + " Previous: " + new Date(lastbgTime).toString() + " " + bgReadings.get(i - 1).value);
if (bgReadings.get(i).value < 39 || bgReadings.get(i - 1).value < 39) {
continue;
}
long elapsed_minutes = (bgTime - lastbgTime) / (60 * 1000);
if (Math.abs(elapsed_minutes) > 8) {
// interpolate missing data points
double lastbg = bgReadings.get(i - 1).value;
elapsed_minutes = Math.abs(elapsed_minutes);
//console.error(elapsed_minutes);
long nextbgTime;
while (elapsed_minutes > 5) {
nextbgTime = lastbgTime - 5 * 60 * 1000;
j++;
BgReading newBgreading = new BgReading();
newBgreading.timeIndex = nextbgTime;
double gapDelta = bgReadings.get(i).value - lastbg;
//console.error(gapDelta, lastbg, elapsed_minutes);
double nextbg = lastbg + (5d / elapsed_minutes * gapDelta);
newBgreading.value = Math.round(nextbg);
//console.error("Interpolated", bucketed_data[j]);
bucketed_data.add(newBgreading);
//log.error("******************************************************************************************************* Adding:" + new Date(newBgreading.timeIndex).toString() + " " + newBgreading.value);
elapsed_minutes = elapsed_minutes - 5;
lastbg = nextbg;
lastbgTime = nextbgTime;
}
j++;
BgReading newBgreading = new BgReading();
newBgreading.value = bgReadings.get(i).value;
newBgreading.timeIndex = bgTime;
bucketed_data.add(newBgreading);
//log.error("******************************************************************************************************* Copying:" + new Date(newBgreading.timeIndex).toString() + " " + newBgreading.value);
} else if (Math.abs(elapsed_minutes) > 2) {
j++;
BgReading newBgreading = new BgReading();
newBgreading.value = bgReadings.get(i).value;
newBgreading.timeIndex = bgTime;
bucketed_data.add(newBgreading);
//log.error("******************************************************************************************************* Copying:" + new Date(newBgreading.timeIndex).toString() + " " + newBgreading.value);
} else {
bucketed_data.get(j).value = (bucketed_data.get(j).value + bgReadings.get(i).value) / 2;
//log.error("***** Average");
}
}
log.debug("Bucketed data created. Size: " + bucketed_data.size());
}
//log.debug("Releasing createBucketedData");
}
public void calculateSensitivityData() {
//log.debug("Locking calculateSensitivityData");
synchronized (dataLock) {
NSProfile profile = ConfigBuilderPlugin.getActiveProfile() != null ? ConfigBuilderPlugin.getActiveProfile().getProfile() : null;
if (profile == null) {
log.debug("calculateSensitivityData: No profile available");
return;
}
if (ConfigBuilderPlugin.getActiveTreatments() == null) {
log.debug("calculateSensitivityData: No treatments plugin");
return;
}
TreatmentsInterface treatmentsInterface = ConfigBuilderPlugin.getActiveTreatments();
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).timeIndex);
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).timeIndex;
bgTime = roundUpTime(bgTime);
AutosensData existing;
if ((existing = autosensDataTable.get(bgTime)) != null) {
previous = existing;
continue;
}
int secondsFromMidnight = NSProfile.secondsFromMidnight(bgTime);
double sens = NSProfile.toMgdl(profile.getIsf(secondsFromMidnight), profile.getUnits());
AutosensData autosensData = new AutosensData();
autosensData.time = bgTime;
//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;
}
avgDelta = (bg - bucketed_data.get(i + 3).value) / 3;
delta = (bg - bucketed_data.get(i + 1).value);
IobTotal iob = calulateFromTreatmentsAndTemps(bgTime);
double bgi = Math.round((-iob.activity * sens * 5) * 100) / 100d;
double deviation = delta - bgi;
List<Treatment> recentTreatments = treatmentsInterface.getTreatments5MinBack(bgTime);
for (int ir = 0; ir < recentTreatments.size(); ir++) {
autosensData.carbsFromBolus += recentTreatments.get(ir).carbs;
}
// if we are absorbing carbs
if (previous != null && previous.cob > 0) {
// figure out how many carbs that represents
// but always assume at least 3mg/dL/5m (default) absorption
double ci = Math.max(deviation, SP.getDouble("openapsama_min_5m_carbimpact", 3.0));
autosensData.absorbed = ci * profile.getIc(secondsFromMidnight) / sens;
// and add that to the running total carbsAbsorbed
autosensData.cob = Math.max(previous.cob - autosensData.absorbed, 0d);
}
autosensData.cob += autosensData.carbsFromBolus;
autosensData.deviation = deviation;
// calculate autosens only without COB
if (autosensData.cob <= 0) {
if (deviation > 0) {
autosensData.pastSensitivity += "+";
} else if (deviation == 0) {
autosensData.pastSensitivity += "=";
} else {
autosensData.pastSensitivity += "-";
}
autosensData.calculateWithDeviation = 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);
log.debug(autosensData.log(bgTime));
}
}
MainApp.bus().post(new EventAutosensCalculationFinished());
//log.debug("Releasing calculateSensitivityData");
}
public static IobTotal calulateFromTreatmentsAndTemps(long time) {
long now = new Date().getTime();
time = roundUpTime(time);
if (time < now && iobTable.get(time) != null) {
//log.debug(">>> Cache hit");
return iobTable.get(time);
} else {
//log.debug(">>> Cache miss " + new Date(time).toLocaleString());
}
IobTotal bolusIob = ConfigBuilderPlugin.getActiveTreatments().getCalculationToTime(time).round();
IobTotal basalIob = ConfigBuilderPlugin.getActiveTempBasals().getCalculationToTime(time).round();
/*
if (basalIob.basaliob > 0) {
log.debug(new Date(time).toLocaleString() + " basaliob: " + basalIob.basaliob );
}
*/
IobTotal iobTotal = IobTotal.combine(bolusIob, basalIob).round();
if (time < new Date().getTime()) {
iobTable.put(time, iobTotal);
}
return iobTotal;
}
public static AutosensData getAutosensData(long time) {
long now = new Date().getTime();
if (time > now)
return null;
time = roundUpTime(time);
AutosensData data = autosensDataTable.get(time);
if (data != null) {
//log.debug(">>> Cache hit " + data.log(time));
return data;
} else {
//log.debug(">>> Cache miss " + new Date(time).toLocaleString());
return null;
}
}
public static AutosensData getLastAutosensData() {
AutosensData data = autosensDataTable.valueAt(autosensDataTable.size() - 1);
if (data.time < new Date().getTime() - 5 * 60 * 1000) {
return null;
} else {
return data;
}
}
public static IobTotal[] calculateIobArrayInDia() {
NSProfile profile = ConfigBuilderPlugin.getActiveProfile().getProfile();
// predict IOB out to DIA plus 30m
long time = new Date().getTime();
int len = (int) ((profile.getDia() * 60 + 30) / 5);
IobTotal[] array = new IobTotal[len];
int pos = 0;
for (int i = 0; i < len; i++) {
long t = time + i * 5 * 60000;
IobTotal iob = calulateFromTreatmentsAndTemps(t);
array[pos] = iob;
pos++;
}
return array;
}
public static AutosensResult detectSensitivity(long fromTime) {
//log.debug("Locking detectSensitivity");
synchronized (dataLock) {
if (autosensDataTable == null || autosensDataTable.size() < 4) {
log.debug("No bucketed data available");
return new AutosensResult();
}
AutosensData current = getLastAutosensData();
if (current == null) {
log.debug("No current autosens data available");
return new AutosensResult();
}
List<Double> deviationsArray = new ArrayList<>();
String pastSensitivity = "";
int index = 0;
while (index < autosensDataTable.size()) {
AutosensData autosensData = autosensDataTable.valueAt(index);
if (autosensData.time < fromTime) {
index++;
continue;
}
if (autosensData.calculateWithDeviation)
deviationsArray.add(autosensData.deviation);
pastSensitivity += autosensData.pastSensitivity;
int secondsFromMidnight = NSProfile.secondsFromMidnight(autosensData.time);
if (secondsFromMidnight % 3600 < 2.5 * 60 || secondsFromMidnight % 3600 > 57.5 * 60) {
pastSensitivity += "(" + Math.round(secondsFromMidnight / 3600d) + ")";
}
index++;
}
Double[] deviations = new Double[deviationsArray.size()];
deviations = deviationsArray.toArray(deviations);
NSProfile profile = ConfigBuilderPlugin.getActiveProfile().getProfile();
double ratio = 1;
String ratioLimit = "";
String sensResult = "";
log.debug("Records: " + index + " " + pastSensitivity);
Arrays.sort(deviations);
for (double i = 0.9; i > 0.1; i = i - 0.02) {
if (percentile(deviations, (i + 0.02)) >= 0 && percentile(deviations, i) < 0) {
log.debug(Math.round(100 * i) + "% of non-meal deviations negative (target 45%-50%)");
}
}
double pSensitive = percentile(deviations, 0.50);
double pResistant = percentile(deviations, 0.45);
double basalOff = 0;
if (pSensitive < 0) { // sensitive
basalOff = pSensitive * (60 / 5) / NSProfile.toMgdl(profile.getIsf(NSProfile.secondsFromMidnight()), profile.getUnits());
sensResult = "Excess insulin sensitivity detected";
} else if (pResistant > 0) { // resistant
basalOff = pResistant * (60 / 5) / NSProfile.toMgdl(profile.getIsf(NSProfile.secondsFromMidnight()), profile.getUnits());
sensResult = "Excess insulin resistance detected";
} else {
sensResult = "Sensitivity normal";
}
log.debug(sensResult);
ratio = 1 + (basalOff / profile.getMaxDailyBasal());
double rawRatio = ratio;
ratio = Math.max(ratio, SafeParse.stringToDouble(SP.getString("openapsama_autosens_min", "0.7")));
ratio = Math.min(ratio, SafeParse.stringToDouble(SP.getString("openapsama_autosens_max", "1.2")));
if (ratio != rawRatio) {
ratioLimit = "Ratio limited from " + rawRatio + " to " + ratio;
log.debug(ratioLimit);
}
double newisf = Math.round(NSProfile.toMgdl(profile.getIsf(NSProfile.secondsFromMidnight()), profile.getUnits()) / ratio);
if (ratio != 1) {
log.debug("ISF adjusted from " + NSProfile.toMgdl(profile.getIsf(NSProfile.secondsFromMidnight()), profile.getUnits()) + " to " + newisf);
}
AutosensResult output = new AutosensResult();
output.ratio = Round.roundTo(ratio, 0.01);
output.carbsAbsorbed = Round.roundTo(current.cob, 0.01);
output.pastSensitivity = pastSensitivity;
output.ratioLimit = ratioLimit;
output.sensResult = sensResult;
return output;
}
//log.debug("Releasing detectSensitivity");
}
public static JSONArray convertToJSONArray(IobTotal[] iobArray) {
JSONArray array = new JSONArray();
for (int i = 0; i < iobArray.length; i++) {
array.put(iobArray[i].determineBasalJson());
}
return array;
}
@Subscribe
public void onNewBg(EventNewBG ev) {
sHandler.post(new Runnable() {
@Override
public void run() {
loadBgData();
createBucketedData();
calculateSensitivityData();
}
});
}
@Subscribe
public void onNewProfile(EventNewBasalProfile ev) {
if (MainApp.getConfigBuilder().getActiveProfile() == null)
return;
NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile();
if (profile != null) {
dia = profile.getDia();
}
}
// When historical data is changed (comming from NS etc) finished calculations after this date must be invalidated
@Subscribe
public void onNewHistoryData(EventNewHistoryData ev) {
//log.debug("Locking onNewHistoryData");
synchronized (dataLock) {
long time = ev.time;
log.debug("Invalidating cached data to: " + new Date(time).toLocaleString());
for (int index = iobTable.size() - 1; index >= 0; index--) {
if (iobTable.keyAt(index) > time) {
log.debug("Removing from iobTable: " + new Date(iobTable.keyAt(index)).toLocaleString());
iobTable.removeAt(index);
} else {
break;
}
}
for (int index = autosensDataTable.size() - 1; index >= 0; index--) {
if (autosensDataTable.keyAt(index) > time) {
log.debug("Removing from autosensDataTable: " + new Date(autosensDataTable.keyAt(index)).toLocaleString());
autosensDataTable.removeAt(index);
} else {
break;
}
}
}
sHandler.post(new Runnable() {
@Override
public void run() {
calculateSensitivityData();
}
});
//log.debug("Releasing onNewHistoryData");
}
// From https://gist.github.com/IceCreamYou/6ffa1b18c4c8f6aeaad2
// Returns the value at a given percentile in a sorted numeric array.
// "Linear interpolation between closest ranks" method
public static double percentile(Double[] arr, double p) {
if (arr.length == 0) return 0;
if (p <= 0) return arr[0];
if (p >= 1) return arr[arr.length - 1];
double index = arr.length * p,
lower = Math.floor(index),
upper = lower + 1,
weight = index % 1;
if (upper >= arr.length) return arr[(int) lower];
return arr[(int) lower] * (1 - weight) + arr[(int) upper] * weight;
}
}

View file

@ -0,0 +1,8 @@
package info.nightscout.androidaps.plugins.IobCobCalculator.events;
/**
* Created by mike on 30.04.2017.
*/
public class EventAutosensCalculationFinished {
}

View file

@ -0,0 +1,13 @@
package info.nightscout.androidaps.plugins.IobCobCalculator.events;
/**
* Created by mike on 26.04.2017.
*/
public class EventNewHistoryData {
public long time = 0;
public EventNewHistoryData(long time) {
this.time = time;
}
}

View file

@ -2,7 +2,6 @@ package info.nightscout.androidaps.plugins.Loop;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import org.json.JSONException;
@ -10,12 +9,9 @@ import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.Services.Intents;
import info.nightscout.client.data.DbLogger;
import info.nightscout.androidaps.plugins.NSClientInternal.data.DbLogger;
/*
{
@ -382,6 +378,7 @@ public class DeviceStatus {
public JSONObject enacted = null;
public JSONObject suggested = null;
public JSONObject iob = null;
public int uploaderBattery = 0;
public String created_at = null;
public JSONObject mongoRecord () {
@ -397,6 +394,7 @@ public class DeviceStatus {
if (iob != null) openaps.put("iob", iob);
record.put("openaps", openaps);
}
if (uploaderBattery != 0) record.put("uploaderBattery", uploaderBattery);
if (created_at != null) record.put("created_at" , created_at);
} catch (JSONException e) {
e.printStackTrace();

View file

@ -10,6 +10,8 @@ import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import com.crashlytics.android.answers.Answers;
import com.crashlytics.android.answers.CustomEvent;
import com.squareup.otto.Subscribe;
import org.slf4j.Logger;
@ -17,11 +19,10 @@ import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.interfaces.FragmentBase;
import info.nightscout.androidaps.plugins.Loop.events.EventLoopSetLastRunGui;
import info.nightscout.androidaps.plugins.Loop.events.EventLoopUpdateGui;
public class LoopFragment extends Fragment implements View.OnClickListener, FragmentBase {
public class LoopFragment extends Fragment implements View.OnClickListener {
private static Logger log = LoggerFactory.getLogger(LoopFragment.class);
private static LoopPlugin loopPlugin;
@ -84,6 +85,7 @@ public class LoopFragment extends Fragment implements View.OnClickListener, Frag
}
});
thread.start();
Answers.getInstance().logCustom(new CustomEvent("Loop_Run"));
break;
}

View file

@ -32,6 +32,7 @@ import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Loop.events.EventLoopSetLastRunGui;
import info.nightscout.androidaps.plugins.Loop.events.EventLoopUpdateGui;
import info.nightscout.androidaps.plugins.Loop.events.EventNewOpenLoopNotification;
import info.nightscout.utils.SP;
/**
* Created by mike on 05.08.2016.
@ -43,7 +44,10 @@ public class LoopPlugin implements PluginBase {
private static HandlerThread sHandlerThread;
private boolean fragmentEnabled = false;
private boolean fragmentVisible = true;
private boolean fragmentVisible = false;
private long loopSuspendedTill = 0L; // end of manual loop suspend
private boolean isSuperBolus = false;
public class LastRun {
public APSResult request = null;
@ -64,6 +68,8 @@ public class LoopPlugin implements PluginBase {
sHandler = new Handler(sHandlerThread.getLooper());
}
MainApp.bus().register(this);
loopSuspendedTill = SP.getLong("loopSuspendedTill", 0L);
isSuperBolus = SP.getBoolean("isSuperBolus", false);
}
@Override
@ -107,6 +113,16 @@ public class LoopPlugin implements PluginBase {
return true;
}
@Override
public boolean hasFragment() {
return true;
}
@Override
public boolean showInList(int type) {
return true;
}
@Override
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
if (type == LOOP) this.fragmentEnabled = fragmentEnabled;
@ -127,12 +143,72 @@ public class LoopPlugin implements PluginBase {
invoke("EventNewBG", true);
}
public long suspendedTo() {
return loopSuspendedTill;
}
public void suspendTo(long endTime) {
loopSuspendedTill = endTime;
isSuperBolus = false;
SP.putLong("loopSuspendedTill", loopSuspendedTill);
}
public void superBolusTo(long endTime) {
loopSuspendedTill = endTime;
isSuperBolus = true;
SP.putLong("loopSuspendedTill", loopSuspendedTill);
}
public int minutesToEndOfSuspend() {
if (loopSuspendedTill == 0)
return 0;
long now = new Date().getTime();
long msecDiff = loopSuspendedTill - now;
if (loopSuspendedTill <= now) { // time exceeded
suspendTo(0L);
return 0;
}
return (int) (msecDiff / 60d / 1000d);
}
public boolean isSuspended() {
if (loopSuspendedTill == 0)
return false;
long now = new Date().getTime();
if (loopSuspendedTill <= now) { // time exceeded
suspendTo(0L);
return false;
}
return true;
}
public boolean isSuperBolus() {
if (loopSuspendedTill == 0)
return false;
long now = new Date().getTime();
if (loopSuspendedTill <= now) { // time exceeded
suspendTo(0L);
return false;
}
return isSuperBolus;
}
public void invoke(String initiator, boolean allowNotification) {
try {
if (Config.logFunctionCalls)
log.debug("invoke");
ConstraintsInterface constraintsInterface = MainApp.getConfigBuilder();
if (!constraintsInterface.isLoopEnabled()) {
log.debug(MainApp.sResources.getString(R.string.loopdisabled));
MainApp.bus().post(new EventLoopSetLastRunGui(MainApp.sResources.getString(R.string.loopdisabled)));
return;
}
@ -142,6 +218,18 @@ public class LoopPlugin implements PluginBase {
if (configBuilder == null || !isEnabled(PluginBase.LOOP))
return;
if (isSuspended()) {
log.debug(MainApp.sResources.getString(R.string.loopsuspended));
MainApp.bus().post(new EventLoopSetLastRunGui(MainApp.sResources.getString(R.string.loopsuspended)));
return;
}
if (configBuilder.isSuspended()) {
log.debug(MainApp.sResources.getString(R.string.pumpsuspended));
MainApp.bus().post(new EventLoopSetLastRunGui(MainApp.sResources.getString(R.string.pumpsuspended)));
return;
}
// Check if pump info is loaded
if (configBuilder.getBaseBasalRate() < 0.01d) return;
@ -196,7 +284,7 @@ public class LoopPlugin implements PluginBase {
if (result.changeRequested && allowNotification) {
NotificationCompat.Builder builder =
new NotificationCompat.Builder(MainApp.instance().getApplicationContext());
builder.setSmallIcon(R.drawable.notification_icon)
builder.setSmallIcon(R.drawable.notif_icon)
.setContentTitle(MainApp.sResources.getString(R.string.openloop_newsuggestion))
.setContentText(resultAfterConstraints.toString())
.setAutoCancel(true)
@ -228,7 +316,7 @@ public class LoopPlugin implements PluginBase {
}
MainApp.bus().post(new EventLoopUpdateGui());
MainApp.getConfigBuilder().uploadDeviceStatus(120);
MainApp.getConfigBuilder().uploadDeviceStatus();
} finally {
if (Config.logFunctionCalls)
log.debug("invoke end");

View file

@ -1,33 +0,0 @@
package info.nightscout.androidaps.plugins.MDI;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.squareup.otto.Subscribe;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.interfaces.FragmentBase;
import info.nightscout.androidaps.plugins.VirtualPump.VirtualPumpPlugin;
import info.nightscout.androidaps.plugins.VirtualPump.events.EventVirtualPumpUpdateGui;
public class MDIFragment extends Fragment implements FragmentBase {
private static Logger log = LoggerFactory.getLogger(MDIFragment.class);
private static MDIPlugin mdiPlugin = new MDIPlugin();
public static MDIPlugin getPlugin() {
return mdiPlugin;
}
}

View file

@ -0,0 +1,191 @@
package info.nightscout.androidaps.plugins.NSClientInternal;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Paint;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.text.Html;
import android.text.Spanned;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.ScrollView;
import android.widget.TextView;
import com.crashlytics.android.answers.Answers;
import com.crashlytics.android.answers.CustomEvent;
import com.squareup.otto.Subscribe;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.events.EventPreferenceChange;
import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientNewLog;
import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientRestart;
import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientUpdateGUI;
import info.nightscout.utils.SP;
public class NSClientInternalFragment extends Fragment implements View.OnClickListener, CompoundButton.OnCheckedChangeListener {
private static Logger log = LoggerFactory.getLogger(NSClientInternalFragment.class);
static NSClientInternalPlugin nsClientInternalPlugin;
static public NSClientInternalPlugin getPlugin() {
if (nsClientInternalPlugin == null) {
nsClientInternalPlugin = new NSClientInternalPlugin();
}
return nsClientInternalPlugin;
}
private TextView logTextView;
private TextView queueTextView;
private TextView urlTextView;
private TextView statusTextView;
private TextView clearlog;
private TextView restart;
private TextView delivernow;
private TextView clearqueue;
private TextView showqueue;
private ScrollView logScrollview;
private CheckBox autoscrollCheckbox;
private CheckBox pausedCheckbox;
String status = "";
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.nsclientinternal_fragment, container, false);
logScrollview = (ScrollView) view.findViewById(R.id.nsclientinternal_logscrollview);
autoscrollCheckbox = (CheckBox) view.findViewById(R.id.nsclientinternal_autoscroll);
autoscrollCheckbox.setChecked(getPlugin().autoscroll);
autoscrollCheckbox.setOnCheckedChangeListener(this);
pausedCheckbox = (CheckBox) view.findViewById(R.id.nsclientinternal_paused);
pausedCheckbox.setChecked(getPlugin().paused);
pausedCheckbox.setOnCheckedChangeListener(this);
logTextView = (TextView) view.findViewById(R.id.nsclientinternal_log);
queueTextView = (TextView) view.findViewById(R.id.nsclientinternal_queue);
urlTextView = (TextView) view.findViewById(R.id.nsclientinternal_url);
statusTextView = (TextView) view.findViewById(R.id.nsclientinternal_status);
clearlog = (TextView) view.findViewById(R.id.nsclientinternal_clearlog);
clearlog.setOnClickListener(this);
clearlog.setPaintFlags(clearlog.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
restart = (TextView) view.findViewById(R.id.nsclientinternal_restart);
restart.setOnClickListener(this);
restart.setPaintFlags(restart.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
delivernow = (TextView) view.findViewById(R.id.nsclientinternal_delivernow);
delivernow.setOnClickListener(this);
delivernow.setPaintFlags(delivernow.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
clearqueue = (TextView) view.findViewById(R.id.nsclientinternal_clearqueue);
clearqueue.setOnClickListener(this);
clearqueue.setPaintFlags(clearqueue.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
showqueue = (TextView) view.findViewById(R.id.nsclientinternal_showqueue);
showqueue.setOnClickListener(this);
showqueue.setPaintFlags(showqueue.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
updateGUI();
return view;
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.nsclientinternal_restart:
MainApp.bus().post(new EventNSClientRestart());
Answers.getInstance().logCustom(new CustomEvent("NSClientRestart"));
break;
case R.id.nsclientinternal_delivernow:
getPlugin().resend("GUI");
Answers.getInstance().logCustom(new CustomEvent("NSClientDeliverNow"));
break;
case R.id.nsclientinternal_clearlog:
getPlugin().clearLog();
break;
case R.id.nsclientinternal_clearqueue:
final Context context = getContext();
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(this.getContext().getString(R.string.confirmation));
builder.setMessage("Clear queue? All data in queue will be lost!");
builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
getPlugin().queue().clearQueue();
updateGUI();
Answers.getInstance().logCustom(new CustomEvent("NSClientClearQueue"));
}
});
builder.setNegativeButton(getString(R.string.cancel), null);
builder.show();
break;
case R.id.nsclientinternal_showqueue:
MainApp.bus().post(new EventNSClientNewLog("QUEUE", getPlugin().queue().textList()));
Answers.getInstance().logCustom(new CustomEvent("NSClientShowQueue"));
break;
}
}
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
switch (buttonView.getId()) {
case R.id.nsclientinternal_paused:
SP.putBoolean(R.string.key_nsclientinternal_paused, isChecked);
getPlugin().paused = isChecked;
MainApp.bus().post(new EventPreferenceChange(R.string.key_nsclientinternal_paused));
updateGUI();
Answers.getInstance().logCustom(new CustomEvent("NSClientPause"));
break;
case R.id.nsclientinternal_autoscroll:
SP.putBoolean(R.string.key_nsclientinternal_autoscroll, isChecked);
getPlugin().autoscroll = isChecked;
updateGUI();
break;
}
}
@Override
public void onPause() {
super.onPause();
MainApp.bus().unregister(this);
}
@Override
public void onResume() {
super.onResume();
MainApp.bus().register(this);
updateGUI();
}
@Subscribe
public void onStatusEvent(final EventNSClientUpdateGUI ev) {
updateGUI();
}
private void updateGUI() {
Activity activity = getActivity();
if (activity != null)
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
logTextView.setText(getPlugin().textLog);
if (getPlugin().autoscroll) {
logScrollview.fullScroll(ScrollView.FOCUS_DOWN);
}
urlTextView.setText(getPlugin().url());
Spanned queuetext = Html.fromHtml(MainApp.sResources.getString(R.string.queue) + " <b>" + getPlugin().queue().size() + "</b>");
queueTextView.setText(queuetext);
statusTextView.setText(getPlugin().status);
}
});
}
}

View file

@ -0,0 +1,220 @@
package info.nightscout.androidaps.plugins.NSClientInternal;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.text.Html;
import android.text.Spanned;
import android.text.TextUtils;
import com.squareup.otto.Subscribe;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.events.EventAppExit;
import info.nightscout.androidaps.events.EventPreferenceChange;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientNewLog;
import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientStatus;
import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientUpdateGUI;
import info.nightscout.androidaps.plugins.NSClientInternal.services.NSClientService;
import info.nightscout.utils.SP;
import info.nightscout.utils.ToastUtils;
public class NSClientInternalPlugin implements PluginBase {
private static Logger log = LoggerFactory.getLogger(NSClientInternalPlugin.class);
boolean fragmentEnabled = true;
boolean fragmentVisible = true;
static public Handler handler;
static private HandlerThread handlerThread;
public List<EventNSClientNewLog> listLog = new ArrayList<EventNSClientNewLog>();
public Spanned textLog = Html.fromHtml("");
public boolean paused = false;
public boolean autoscroll = true;
public String status = "";
public NSClientService nsClientService = null;
public NSClientInternalPlugin() {
MainApp.bus().register(this);
paused = SP.getBoolean(R.string.key_nsclientinternal_paused, false);
autoscroll = SP.getBoolean(R.string.key_nsclientinternal_autoscroll, true);
if (handler == null) {
handlerThread = new HandlerThread(NSClientInternalPlugin.class.getSimpleName() + "Handler");
handlerThread.start();
handler = new Handler(handlerThread.getLooper());
}
Context context = MainApp.instance().getApplicationContext();
Intent intent = new Intent(context, NSClientService.class);
context.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
@Override
public int getType() {
return PluginBase.GENERAL;
}
@Override
public String getFragmentClass() {
return NSClientInternalFragment.class.getName();
}
@Override
public String getName() {
return MainApp.sResources.getString(R.string.nsclientinternal);
}
@Override
public String getNameShort() {
String name = MainApp.sResources.getString(R.string.nsclientinternal_shortname);
if (!name.trim().isEmpty()) {
//only if translation exists
return name;
}
// use long name as fallback
return getName();
}
@Override
public boolean isEnabled(int type) {
return type == GENERAL && fragmentEnabled;
}
@Override
public boolean isVisibleInTabs(int type) {
return type == GENERAL && fragmentVisible;
}
@Override
public boolean canBeHidden(int type) {
return true;
}
@Override
public boolean hasFragment() {
return true;
}
@Override
public boolean showInList(int type) {
return true;
}
@Override
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
if (type == GENERAL) this.fragmentEnabled = fragmentEnabled;
}
@Override
public void setFragmentVisible(int type, boolean fragmentVisible) {
if (type == GENERAL) this.fragmentVisible = fragmentVisible;
}
ServiceConnection mConnection = new ServiceConnection() {
public void onServiceDisconnected(ComponentName name) {
log.debug("Service is disconnected");
nsClientService = null;
}
public void onServiceConnected(ComponentName name, IBinder service) {
log.debug("Service is connected");
NSClientService.LocalBinder mLocalBinder = (NSClientService.LocalBinder) service;
nsClientService = mLocalBinder.getServiceInstance();
}
};
@SuppressWarnings("UnusedParameters")
@Subscribe
public void onStatusEvent(final EventAppExit e) {
if (nsClientService != null)
MainApp.instance().getApplicationContext().unbindService(mConnection);
}
@Subscribe
public void onStatusEvent(final EventPreferenceChange s) {
//TODO
}
@Subscribe
public void onStatusEvent(final EventNSClientNewLog ev) {
addToLog(ev);
log.debug(ev.action + " " + ev.logText);
}
@Subscribe
public void onStatusEvent(final EventNSClientStatus ev) {
status = ev.status;
MainApp.bus().post(new EventNSClientUpdateGUI());
}
public void clearLog() {
handler.post(new Runnable() {
@Override
public void run() {
listLog = new ArrayList<EventNSClientNewLog>();
updateLog();
}
});
}
private void addToLog(final EventNSClientNewLog ev) {
handler.post(new Runnable() {
@Override
public void run() {
SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss");
listLog.add(ev);
// remove the first line if log is too large
if (listLog.size() >= Constants.MAX_LOG_LINES) {
listLog.remove(0);
}
updateLog();
}
});
}
private void updateLog() {
try {
Spanned newTextLog = Html.fromHtml("");
for (EventNSClientNewLog log : listLog) {
newTextLog = (Spanned) TextUtils.concat(newTextLog, log.toHtml());
}
textLog = newTextLog;
MainApp.bus().post(new EventNSClientUpdateGUI());
} catch (OutOfMemoryError e) {
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), "Out of memory!\nStop using this phone !!!", R.raw.error);
}
}
public void resend(String reason) {
if (nsClientService != null)
nsClientService.resend(reason);
}
public UploadQueue queue() {
return NSClientService.uploadQueue;
}
public String url() {
return NSClientService.nsURL;
}
}

View file

@ -0,0 +1,139 @@
package info.nightscout.androidaps.plugins.NSClientInternal;
import android.content.Context;
import android.content.Intent;
import com.j256.ormlite.dao.CloseableIterator;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.db.DatabaseHelper;
import info.nightscout.androidaps.db.DbRequest;
import info.nightscout.androidaps.plugins.NSClientInternal.services.NSClientService;
import info.nightscout.utils.SP;
/**
* Created by mike on 21.02.2016.
*/
public class UploadQueue {
private static Logger log = LoggerFactory.getLogger(UploadQueue.class);
public static String status() {
return "QUEUE: " + MainApp.getDbHelper().size(DatabaseHelper.DATABASE_DBREQUESTS);
}
public static long size() {
return MainApp.getDbHelper().size(DatabaseHelper.DATABASE_DBREQUESTS);
}
private static void startService() {
if (NSClientService.handler == null) {
Context context = MainApp.instance();
context.startService(new Intent(context, NSClientService.class));
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
}
}
}
public static void add(final DbRequest dbr) {
startService();
if (NSClientService.handler != null) {
NSClientService.handler.post(new Runnable() {
@Override
public void run() {
log.debug("QUEUE adding: " + dbr.data);
MainApp.getDbHelper().create(dbr);
NSClientInternalPlugin plugin = (NSClientInternalPlugin) MainApp.getSpecificPlugin(NSClientInternalPlugin.class);
if (plugin != null) {
plugin.resend("newdata");
}
}
});
}
}
public static void clearQueue() {
startService();
if (NSClientService.handler != null) {
NSClientService.handler.post(new Runnable() {
@Override
public void run() {
log.debug("QUEUE ClearQueue");
MainApp.getDbHelper().deleteAllDbRequests();
log.debug(status());
}
});
}
}
public static void removeID(final JSONObject record) {
startService();
if (NSClientService.handler != null) {
NSClientService.handler.post(new Runnable() {
@Override
public void run() {
try {
String id;
if (record.has("NSCLIENT_ID")) {
id = record.getString("NSCLIENT_ID");
} else {
return;
}
if (MainApp.getDbHelper().deleteDbRequest(id) == 1) {
log.debug("Removed item from UploadQueue. " + UploadQueue.status());
}
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
}
public static void removeID(final String action, final String _id) {
startService();
if (NSClientService.handler != null) {
NSClientService.handler.post(new Runnable() {
@Override
public void run() {
MainApp.getDbHelper().deleteDbRequestbyMongoId(action, _id);
}
});
}
}
public String textList() {
String result = "";
CloseableIterator<DbRequest> iterator = null;
try {
iterator = MainApp.getDbHelper().getDaoDbRequest().closeableIterator();
try {
while (iterator.hasNext()) {
DbRequest dbr = iterator.next();
result += "<br>";
result += dbr.action.toUpperCase() + " ";
result += dbr.collection + ": ";
result += dbr.data;
}
} finally {
iterator.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
return result;
}
}

View file

@ -0,0 +1,55 @@
package info.nightscout.androidaps.plugins.NSClientInternal.acks;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientRestart;
import info.nightscout.androidaps.plugins.NSClientInternal.services.NSClientService;
import io.socket.client.Ack;
/**
* Created by mike on 29.12.2015.
*/
public class NSAddAck implements Ack {
private static Logger log = LoggerFactory.getLogger(NSAddAck.class);
public String _id = null;
public String nsClientID = null;
public JSONObject json = null;
public void call(Object...args) {
// Regular response
try {
JSONArray responsearray = (JSONArray) (args[0]);
JSONObject response = null;
if (responsearray.length()>0) {
response = responsearray.getJSONObject(0);
_id = response.getString("_id");
json = response;
if (response.has("NSCLIENT_ID")) {
nsClientID = response.getString("NSCLIENT_ID");
}
}
MainApp.bus().post(this);
return;
} catch (Exception e) {
}
// Check for not authorized
try {
JSONObject response = (JSONObject) (args[0]);
if (response.has("result")) {
_id = null;
if (response.getString("result").contains("Not")) {
MainApp.bus().post(new EventNSClientRestart());
return;
}
log.debug("DBACCESS " + response.getString("result"));
}
return;
} catch (Exception e) {
e.printStackTrace();
}
}
}

View file

@ -0,0 +1,24 @@
package info.nightscout.androidaps.plugins.NSClientInternal.acks;
import org.json.JSONObject;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientNewLog;
import io.socket.client.Ack;
/**
* Created by mike on 02.01.2016.
*/
public class NSAuthAck implements Ack{
public boolean read = false;
public boolean write = false;
public boolean write_treatment = false;
public void call(Object...args) {
JSONObject response = (JSONObject)args[0];
read = response.optBoolean("read");
write = response.optBoolean("write");
write_treatment = response.optBoolean("write_treatment");
MainApp.bus().post(this);
}
}

View file

@ -0,0 +1,38 @@
package info.nightscout.androidaps.plugins.NSClientInternal.acks;
import org.json.JSONException;
import org.json.JSONObject;
import io.socket.client.Ack;
/**
* Created by mike on 29.12.2015.
*/
public class NSPingAck implements Ack {
public long mills = 0;
public boolean received = false;
public boolean auth_received = false;
public boolean read = false;
public boolean write = false;
public boolean write_treatment = false;
public void call(Object...args) {
JSONObject response = (JSONObject)args[0];
mills = response.optLong("mills");
if (response.has("authorization")) {
auth_received = true;
try {
JSONObject authorization = response.getJSONObject("authorization");
read = authorization.optBoolean("read");
write = authorization.optBoolean("write");
write_treatment = authorization.optBoolean("write_treatment");
} catch (JSONException e) {
e.printStackTrace();
}
}
received = true;
synchronized(this) {
this.notify();
}
}
}

View file

@ -0,0 +1,39 @@
package info.nightscout.androidaps.plugins.NSClientInternal.acks;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.MainApp;
import io.socket.client.Ack;
/**
* Created by mike on 21.02.2016.
*/
public class NSUpdateAck implements Ack {
private static Logger log = LoggerFactory.getLogger(NSUpdateAck.class);
public boolean result = false;
public String _id = null;
public String action;
public void call(Object...args) {
JSONObject response = (JSONObject)args[0];
if (response.has("result"))
try {
if (response.getString("result").equals("success"))
result = true;
else if (response.getString("result").equals("Missing _id")) {
result = true;
log.debug("Internal error: Missing _id returned on dbUpdate ack");
}
MainApp.bus().post(this);
} catch (JSONException e) {
}
}
public NSUpdateAck(String action, String _id) {
super();
this.action = action;
this._id = _id;
}
}

View file

@ -0,0 +1,34 @@
package info.nightscout.androidaps.plugins.NSClientInternal.broadcasts;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import org.json.JSONArray;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import info.nightscout.androidaps.Services.Intents;
/**
* Created by mike on 26.06.2016.
*/
public class BroadcastCals {
private static Logger log = LoggerFactory.getLogger(BroadcastCals.class);
public void handleNewCal(JSONArray cals, Context context, boolean isDelta) {
Bundle bundle = new Bundle();
bundle.putString("cals", cals.toString());
bundle.putBoolean("delta", isDelta);
Intent intent = new Intent(Intents.ACTION_NEW_CAL);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
context.sendBroadcast(intent);
List<ResolveInfo> x = context.getPackageManager().queryBroadcastReceivers(intent, 0);
log.debug("CAL " + x.size() + " receivers");
}
}

View file

@ -0,0 +1,45 @@
package info.nightscout.androidaps.plugins.NSClientInternal.broadcasts;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import org.json.JSONArray;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import info.nightscout.androidaps.Services.Intents;
public class BroadcastDeviceStatus {
private static Logger log = LoggerFactory.getLogger(BroadcastDeviceStatus.class);
public void handleNewDeviceStatus(JSONObject status, Context context, boolean isDelta) {
Bundle bundle = new Bundle();
bundle.putString("devicestatus", status.toString());
bundle.putBoolean("delta", isDelta);
Intent intent = new Intent(Intents.ACTION_NEW_DEVICESTATUS);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
context.sendBroadcast(intent);
List<ResolveInfo> x = context.getPackageManager().queryBroadcastReceivers(intent, 0);
log.debug("DEVICESTATUS " + x.size() + " receivers");
}
public void handleNewDeviceStatus(JSONArray statuses, Context context, boolean isDelta) {
Bundle bundle = new Bundle();
bundle.putString("devicestatuses", statuses.toString());
bundle.putBoolean("delta", isDelta);
Intent intent = new Intent(Intents.ACTION_NEW_DEVICESTATUS);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
context.sendBroadcast(intent);
List<ResolveInfo> x = context.getPackageManager().queryBroadcastReceivers(intent, 0);
log.debug("DEVICESTATUS " + x.size() + " receivers");
}
}

View file

@ -0,0 +1,34 @@
package info.nightscout.androidaps.plugins.NSClientInternal.broadcasts;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import org.json.JSONArray;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import info.nightscout.androidaps.Services.Intents;
/**
* Created by mike on 26.06.2016.
*/
public class BroadcastMbgs {
private static Logger log = LoggerFactory.getLogger(BroadcastMbgs.class);
public void handleNewMbg(JSONArray mbgs, Context context, boolean isDelta) {
Bundle bundle = new Bundle();
bundle.putString("mbgs", mbgs.toString());
bundle.putBoolean("delta", isDelta);
Intent intent = new Intent(Intents.ACTION_NEW_MBG);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
context.sendBroadcast(intent);
List<ResolveInfo> x = context.getPackageManager().queryBroadcastReceivers(intent, 0);
log.debug("MBG " + x.size() + " receivers");
}
}

View file

@ -0,0 +1,37 @@
package info.nightscout.androidaps.plugins.NSClientInternal.broadcasts;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import info.nightscout.androidaps.Services.Intents;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile;
/**
* Created by mike on 20.02.2016.
*/
public class BroadcastProfile {
private static Logger log = LoggerFactory.getLogger(BroadcastProfile.class);
public void handleNewTreatment(NSProfile profile, Context context, boolean isDelta) {
Bundle bundle = new Bundle();
bundle.putString("profile", profile.getData().toString());
bundle.putString("activeprofile", profile.getActiveProfile());
bundle.putBoolean("delta", isDelta);
Intent intent = new Intent(Intents.ACTION_NEW_PROFILE);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
context.sendBroadcast(intent);
List<ResolveInfo> x = context.getPackageManager().queryBroadcastReceivers(intent, 0);
log.debug("PROFILE " + x.size() + " receivers");
}
}

View file

@ -0,0 +1,30 @@
package info.nightscout.androidaps.plugins.NSClientInternal.broadcasts;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.PowerManager;
import info.nightscout.androidaps.Services.Intents;
/**
* Created by mike on 28.02.2016.
*/
public class BroadcastQueueStatus {
public void handleNewStatus(int size, Context context) {
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"sendQueue");
wakeLock.acquire();
try {
Bundle bundle = new Bundle();
bundle.putInt("size", size);
Intent intent = new Intent(Intents.ACTION_QUEUE_STATUS);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
context.sendBroadcast(intent);
} finally {
wakeLock.release();
}
}
}

View file

@ -0,0 +1,49 @@
package info.nightscout.androidaps.plugins.NSClientInternal.broadcasts;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import org.json.JSONArray;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import info.nightscout.androidaps.Services.Intents;
/**
* Created by mike on 22.02.2016.
*/
public class BroadcastSgvs {
private static Logger log = LoggerFactory.getLogger(BroadcastSgvs.class);
public void handleNewSgv(JSONObject sgv, Context context, boolean isDelta) {
Bundle bundle = new Bundle();
bundle.putString("sgv", sgv.toString());
bundle.putBoolean("delta", isDelta);
Intent intent = new Intent(Intents.ACTION_NEW_SGV);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
context.sendBroadcast(intent);
List<ResolveInfo> x = context.getPackageManager().queryBroadcastReceivers(intent, 0);
log.debug("SGV " + x.size() + " receivers");
}
public void handleNewSgv(JSONArray sgvs, Context context, boolean isDelta) {
Bundle bundle = new Bundle();
bundle.putString("sgvs", sgvs.toString());
bundle.putBoolean("delta", isDelta);
Intent intent = new Intent(Intents.ACTION_NEW_SGV);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
context.sendBroadcast(intent);
List<ResolveInfo> x = context.getPackageManager().queryBroadcastReceivers(intent, 0);
log.debug("SGV " + x.size() + " receivers");
}
}

View file

@ -0,0 +1,45 @@
package info.nightscout.androidaps.plugins.NSClientInternal.broadcasts;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.Services.Intents;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSStatus;
import info.nightscout.androidaps.plugins.NSClientInternal.services.NSClientService;
/**
* Created by mike on 24.02.2016.
*/
public class BroadcastStatus {
private static Logger log = LoggerFactory.getLogger(BroadcastStatus.class);
public void handleNewStatus(NSStatus status, Context context, boolean isDelta) {
Bundle bundle = new Bundle();
try {
bundle.putString("nsclientversionname", MainApp.instance().getPackageManager().getPackageInfo(MainApp.instance().getPackageName(), 0).versionName);
bundle.putInt("nsclientversioncode", MainApp.instance().getPackageManager().getPackageInfo(MainApp.instance().getPackageName(), 0).versionCode);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
};
bundle.putString("nightscoutversionname", NSClientService.nightscoutVersionName);
bundle.putInt("nightscoutversioncode", NSClientService.nightscoutVersionCode);
bundle.putString("status", status.getData().toString());
bundle.putBoolean("delta", isDelta);
Intent intent = new Intent(Intents.ACTION_NEW_STATUS);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
context.sendBroadcast(intent);
List<ResolveInfo> x = context.getPackageManager().queryBroadcastReceivers(intent, 0);
log.debug("STATUS: " + x.size() + " receivers");
}
}

View file

@ -0,0 +1,107 @@
package info.nightscout.androidaps.plugins.NSClientInternal.broadcasts;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import info.nightscout.androidaps.Services.Intents;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSTreatment;
/**
* Created by mike on 20.02.2016.
*/
public class BroadcastTreatment {
private static Logger log = LoggerFactory.getLogger(BroadcastTreatment.class);
public void handleNewTreatment(NSTreatment treatment, Context context, boolean isDelta) {
Bundle bundle = new Bundle();
bundle.putString("treatment", treatment.getData().toString());
bundle.putBoolean("delta", isDelta);
Intent intent = new Intent(Intents.ACTION_NEW_TREATMENT);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
context.sendBroadcast(intent);
List<ResolveInfo> x = context.getPackageManager().queryBroadcastReceivers(intent, 0);
log.debug("TREAT_ADD " + treatment.getEventType() + " " + x.size() + " receivers");
}
public void handleNewTreatment(JSONArray treatments, Context context, boolean isDelta) {
Bundle bundle = new Bundle();
bundle.putString("treatments", treatments.toString());
bundle.putBoolean("delta", isDelta);
Intent intent = new Intent(Intents.ACTION_NEW_TREATMENT);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
context.sendBroadcast(intent);
List<ResolveInfo> x = context.getPackageManager().queryBroadcastReceivers(intent, 0);
log.debug("TREAT_ADD " + treatments.length() + " " + x.size() + " receivers");
}
public void handleChangedTreatment(JSONObject treatment, Context context, boolean isDelta) {
Bundle bundle = new Bundle();
bundle.putString("treatment", treatment.toString());
bundle.putBoolean("delta", isDelta);
Intent intent = new Intent(Intents.ACTION_CHANGED_TREATMENT);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
context.sendBroadcast(intent);
List<ResolveInfo> x = context.getPackageManager().queryBroadcastReceivers(intent, 0);
try {
log.debug("TREAT_CHANGE " + treatment.getString("_id") + " " + x.size() + " receivers");
} catch (JSONException e) {}
}
public void handleChangedTreatment(JSONArray treatments, Context context, boolean isDelta) {
Bundle bundle = new Bundle();
bundle.putString("treatments", treatments.toString());
bundle.putBoolean("delta", isDelta);
Intent intent = new Intent(Intents.ACTION_CHANGED_TREATMENT);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
context.sendBroadcast(intent);
List<ResolveInfo> x = context.getPackageManager().queryBroadcastReceivers(intent, 0);
log.debug("TREAT_CHANGE " + treatments.length() + " " + x.size() + " receivers");
}
public void handleRemovedTreatment(JSONObject treatment, Context context, boolean isDelta) {
Bundle bundle = new Bundle();
bundle.putString("treatment", treatment.toString());
bundle.putBoolean("delta", isDelta);
Intent intent = new Intent(Intents.ACTION_REMOVED_TREATMENT);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
context.sendBroadcast(intent);
List<ResolveInfo> x = context.getPackageManager().queryBroadcastReceivers(intent, 0);
try {
log.debug("TREAT_REMOVE " + treatment.getString("_id") + " " + x.size() + " receivers");
} catch (JSONException e) {}
}
public void handleRemovedTreatment(JSONArray treatments, Context context, boolean isDelta) {
Bundle bundle = new Bundle();
bundle.putString("treatments", treatments.toString());
bundle.putBoolean("delta", isDelta);
Intent intent = new Intent(Intents.ACTION_REMOVED_TREATMENT);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
context.sendBroadcast(intent);
List<ResolveInfo> x = context.getPackageManager().queryBroadcastReceivers(intent, 0);
log.debug("TREAT_REMOVE " + treatments.length() + " treatments " + x.size() + " receivers");
}
}

View file

@ -1,4 +1,4 @@
package info.nightscout.client.data;
package info.nightscout.androidaps.plugins.NSClientInternal.data;
import android.content.Intent;
import android.content.pm.ResolveInfo;

View file

@ -1,9 +1,12 @@
package info.nightscout.client.data;
package info.nightscout.androidaps.plugins.NSClientInternal.data;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class NSCal {
private static Logger log = LoggerFactory.getLogger(NSCal.class);
public long date;
public double slope;
public double intercept;
@ -17,6 +20,7 @@ public class NSCal {
scale = json.getDouble("scale");
} catch (JSONException e) {
e.printStackTrace();
log.debug("Data: " + json.toString());
}
}
}

View file

@ -1,4 +1,6 @@
package info.nightscout.client.data;
package info.nightscout.androidaps.plugins.NSClientInternal.data;
import android.support.annotation.Nullable;
import com.crashlytics.android.Crashlytics;
@ -118,7 +120,7 @@ public class NSProfile {
e.printStackTrace();
}
}
return 3D;
return Constants.defaultDIA;
}
/*
public Double getCarbAbsorbtionRate() {
@ -178,6 +180,7 @@ public class NSProfile {
return TimeZone.getDefault();
}
@Nullable
public Double getValueToTime(JSONArray array, Integer timeAsSeconds) {
Double lastValue = null;
@ -221,10 +224,12 @@ public class NSProfile {
return retValue;
}
@Nullable
public Double getIsf(Integer timeAsSeconds) {
return getIsf(getDefaultProfile(), timeAsSeconds);
}
@Nullable
public Double getIsf(JSONObject profile, Integer timeAsSeconds) {
if (profile != null) {
try {
@ -251,10 +256,12 @@ public class NSProfile {
return "";
}
@Nullable
public Double getIc(Integer timeAsSeconds) {
return getIc(getDefaultProfile(), timeAsSeconds);
}
@Nullable
public Double getIc(JSONObject profile, Integer timeAsSeconds) {
if (profile != null) {
try {
@ -281,10 +288,12 @@ public class NSProfile {
return "";
}
@Nullable
public Double getBasal(Integer timeAsSeconds) {
return getBasal(getDefaultProfile(), timeAsSeconds);
}
@Nullable
public Double getBasal(JSONObject profile, Integer timeAsSeconds) {
if (profile != null) {
try {
@ -339,10 +348,12 @@ public class NSProfile {
return "";
}
@Nullable
public Double getTargetLow(Integer timeAsSeconds) {
return getTargetLow(getDefaultProfile(), timeAsSeconds);
}
@Nullable
public Double getTargetLow(JSONObject profile, Integer timeAsSeconds) {
if (profile != null) {
try {
@ -354,10 +365,12 @@ public class NSProfile {
return 0D;
}
@Nullable
public Double getTargetHigh(Integer timeAsSeconds) {
return getTargetHigh(getDefaultProfile(), timeAsSeconds);
}
@Nullable
public Double getTargetHigh(JSONObject profile, Integer timeAsSeconds) {
if (profile != null) {
try {
@ -448,6 +461,17 @@ public class NSProfile {
return (int) (passed / 1000);
}
public static int secondsFromMidnight(long date) {
Calendar c = Calendar.getInstance();
c.setTimeInMillis(date);
c.set(Calendar.HOUR_OF_DAY, 0);
c.set(Calendar.MINUTE, 0);
c.set(Calendar.SECOND, 0);
c.set(Calendar.MILLISECOND, 0);
long passed = date - c.getTimeInMillis();
return (int) (passed / 1000);
}
public static Double toMgdl(Double value, String units) {
if (units.equals(Constants.MGDL)) return value;
else return value * Constants.MMOLL_TO_MGDL;

View file

@ -1,4 +1,4 @@
package info.nightscout.client.data;
package info.nightscout.androidaps.plugins.NSClientInternal.data;
import org.json.JSONException;
import org.json.JSONObject;

View file

@ -1,4 +1,4 @@
package info.nightscout.client.data;
package info.nightscout.androidaps.plugins.NSClientInternal.data;
import org.json.JSONException;
import org.json.JSONObject;

View file

@ -1,4 +1,4 @@
package info.nightscout.client.data;
package info.nightscout.androidaps.plugins.NSClientInternal.data;
import org.json.JSONException;
import org.json.JSONObject;

View file

@ -0,0 +1,30 @@
package info.nightscout.androidaps.plugins.NSClientInternal.events;
import android.text.Html;
import android.text.Spanned;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* Created by mike on 15.02.2017.
*/
public class EventNSClientNewLog {
public Date date = new Date();
public String action;
public String logText;
public EventNSClientNewLog(String action, String logText) {
this.action = action;
this.logText = logText;
}
public Spanned toHtml() {
SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss");
Spanned line = Html.fromHtml(timeFormat.format(date) + " <b>" + action + "</b> " + logText + "<br>");
return line;
}
}

View file

@ -0,0 +1,8 @@
package info.nightscout.androidaps.plugins.NSClientInternal.events;
/**
* Created by mike on 15.02.2017.
*/
public class EventNSClientRestart {
}

View file

@ -0,0 +1,16 @@
package info.nightscout.androidaps.plugins.NSClientInternal.events;
/**
* Created by mike on 02.01.2016.
*/
public class EventNSClientStatus {
public String status = "";
public EventNSClientStatus(String status) {
this.status = status;
}
public EventNSClientStatus() {
}
}

View file

@ -0,0 +1,8 @@
package info.nightscout.androidaps.plugins.NSClientInternal.events;
/**
* Created by mike on 17.02.2017.
*/
public class EventNSClientUpdateGUI {
}

View file

@ -0,0 +1,17 @@
package info.nightscout.androidaps.plugins.NSClientInternal.receivers;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import info.nightscout.androidaps.plugins.NSClientInternal.services.NSClientService;
public class AutoStartReceiver extends BroadcastReceiver {
public AutoStartReceiver() {
}
@Override
public void onReceive(Context context, Intent intent) {
context.startService(new Intent(context, NSClientService.class));
}
}

View file

@ -0,0 +1,93 @@
package info.nightscout.androidaps.plugins.NSClientInternal.receivers;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.PowerManager;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Date;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.plugins.NSClientInternal.NSClientInternalPlugin;
import info.nightscout.androidaps.plugins.NSClientInternal.UploadQueue;
import info.nightscout.androidaps.db.DbRequest;
public class DBAccessReceiver extends BroadcastReceiver {
private static Logger log = LoggerFactory.getLogger(DBAccessReceiver.class);
@Override
public void onReceive(Context context, Intent intent) {
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"sendQueue");
NSClientInternalPlugin nsClientInternalPlugin = (NSClientInternalPlugin) MainApp.getSpecificPlugin(NSClientInternalPlugin.class);
if (!nsClientInternalPlugin.isEnabled(PluginBase.GENERAL)) {
return;
}
wakeLock.acquire();
try {
Bundle bundles = intent.getExtras();
if (bundles == null) return;
if (!bundles.containsKey("action")) return;
String collection = null;
String _id = null;
JSONObject data = null;
String action = bundles.getString("action");
try { collection = bundles.getString("collection"); } catch (Exception e) {}
try { _id = bundles.getString("_id"); } catch (Exception e) {}
try { data = new JSONObject(bundles.getString("data")); } catch (Exception e) {}
if (data == null && !action.equals("dbRemove") || _id == null && action.equals("dbRemove")) {
log.debug("DBACCESS no data inside record");
return;
}
if (action.equals("dbRemove")) {
data = new JSONObject();
}
// mark by id
Long nsclientid = new Date().getTime();
try {
data.put("NSCLIENT_ID", nsclientid);
} catch (JSONException e) {
e.printStackTrace();
}
if (!isAllowedCollection(collection)) {
log.debug("DBACCESS wrong collection specified");
return;
}
if (action.equals("dbRemove")) {
DbRequest dbr = new DbRequest(action, collection, nsclientid.toString(), _id);
UploadQueue.add(dbr);
} else {
DbRequest dbr = new DbRequest(action, collection, nsclientid.toString(), data);
UploadQueue.add(dbr);
}
} finally {
wakeLock.release();
}
}
private boolean isAllowedCollection(String collection) {
// "treatments" || "entries" || "devicestatus" || "profile" || "food"
if (collection.equals("treatments")) return true;
if (collection.equals("entries")) return true;
if (collection.equals("devicestatus")) return true;
if (collection.equals("profile")) return true;
if (collection.equals("food")) return true;
return false;
}
}

View file

@ -0,0 +1,25 @@
package info.nightscout.androidaps.plugins.NSClientInternal.receivers;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.support.v4.content.WakefulBroadcastReceiver;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientRestart;
import info.nightscout.androidaps.plugins.NSClientInternal.services.NSClientService;
public class RestartReceiver extends WakefulBroadcastReceiver {
public RestartReceiver() {
}
@Override
public void onReceive(Context context, Intent intent) {
startWakefulService(context, new Intent(context, NSClientService.class)
.setAction(intent.getAction())
.putExtras(intent));
MainApp.bus().post(new EventNSClientRestart());
completeWakefulIntent(intent);
}
}

View file

@ -0,0 +1,691 @@
package info.nightscout.androidaps.plugins.NSClientInternal.services;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Binder;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.PowerManager;
import android.preference.PreferenceManager;
import com.google.common.base.Charsets;
import com.google.common.hash.Hashing;
import com.j256.ormlite.dao.CloseableIterator;
import com.squareup.otto.Subscribe;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.URISyntaxException;
import java.sql.SQLException;
import java.util.Date;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.events.EventAppExit;
import info.nightscout.androidaps.events.EventConfigBuilderChange;
import info.nightscout.androidaps.events.EventPreferenceChange;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.plugins.PumpDanaR.Services.ExecutionService;
import info.nightscout.androidaps.plugins.NSClientInternal.NSClientInternalPlugin;
import info.nightscout.androidaps.plugins.NSClientInternal.UploadQueue;
import info.nightscout.androidaps.plugins.NSClientInternal.acks.NSAddAck;
import info.nightscout.androidaps.plugins.NSClientInternal.acks.NSAuthAck;
import info.nightscout.androidaps.plugins.NSClientInternal.acks.NSPingAck;
import info.nightscout.androidaps.plugins.NSClientInternal.acks.NSUpdateAck;
import info.nightscout.androidaps.plugins.NSClientInternal.broadcasts.BroadcastCals;
import info.nightscout.androidaps.plugins.NSClientInternal.broadcasts.BroadcastDeviceStatus;
import info.nightscout.androidaps.plugins.NSClientInternal.broadcasts.BroadcastMbgs;
import info.nightscout.androidaps.plugins.NSClientInternal.broadcasts.BroadcastProfile;
import info.nightscout.androidaps.plugins.NSClientInternal.broadcasts.BroadcastSgvs;
import info.nightscout.androidaps.plugins.NSClientInternal.broadcasts.BroadcastStatus;
import info.nightscout.androidaps.plugins.NSClientInternal.broadcasts.BroadcastTreatment;
import info.nightscout.androidaps.db.DbRequest;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSCal;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSgv;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSStatus;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSTreatment;
import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientNewLog;
import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientRestart;
import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientStatus;
import info.nightscout.androidaps.plugins.Overview.Notification;
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.SP;
import io.socket.client.IO;
import io.socket.client.Socket;
import io.socket.emitter.Emitter;
public class NSClientService extends Service {
private static Logger log = LoggerFactory.getLogger(ExecutionService.class);
static public PowerManager.WakeLock mWakeLock;
private IBinder mBinder = new NSClientService.LocalBinder();
static NSProfile nsProfile;
static public Handler handler;
static private HandlerThread handlerThread;
public static Socket mSocket;
public static boolean isConnected = false;
public static boolean hasWriteAuth = false;
private static Integer dataCounter = 0;
private static Integer connectCounter = 0;
public static String nightscoutVersionName = "";
public static Integer nightscoutVersionCode = 0;
private boolean nsEnabled = false;
static public String nsURL = "";
private String nsAPISecret = "";
private String nsDevice = "";
private Integer nsHours = 24;
private final Integer timeToWaitForResponseInMs = 30000;
private boolean uploading = false;
public Date lastReception = new Date();
public long latestDateInReceivedData = 0;
private String nsAPIhashCode = "";
public static UploadQueue uploadQueue = new UploadQueue();
public NSClientService() {
registerBus();
if (handler == null) {
handlerThread = new HandlerThread(NSClientService.class.getSimpleName() + "Handler");
handlerThread.start();
handler = new Handler(handlerThread.getLooper());
}
PowerManager powerManager = (PowerManager) MainApp.instance().getApplicationContext().getSystemService(Context.POWER_SERVICE);
mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "NSClientService");
initialize();
}
public class LocalBinder extends Binder {
public NSClientService getServiceInstance() {
return NSClientService.this;
}
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
private void registerBus() {
try {
MainApp.bus().unregister(this);
} catch (RuntimeException x) {
// Ignore
}
MainApp.bus().register(this);
}
@Subscribe
public void onStatusEvent(EventAppExit event) {
if (Config.logFunctionCalls)
log.debug("EventAppExit received");
destroy();
stopSelf();
if (Config.logFunctionCalls)
log.debug("EventAppExit finished");
}
@Subscribe
public void onStatusEvent(EventPreferenceChange ev) {
if (ev.isChanged(R.string.key_nsclientinternal_url) ||
ev.isChanged(R.string.key_nsclientinternal_api_secret) ||
ev.isChanged(R.string.key_nsclientinternal_paused)
) {
destroy();
initialize();
}
}
@Subscribe
public void onStatusEvent(EventConfigBuilderChange ev) {
if (nsEnabled != MainApp.getSpecificPlugin(NSClientInternalPlugin.class).isEnabled(PluginBase.GENERAL)) {
destroy();
initialize();
}
}
@Subscribe
public void onStatusEvent(final EventNSClientRestart ev) {
latestDateInReceivedData = 0;
restart();
}
public static void setNsProfile(NSProfile profile) {
nsProfile = profile;
}
public static NSProfile getNsProfile() {
return nsProfile;
}
public void initialize() {
dataCounter = 0;
NSClientService.mWakeLock.acquire();
readPreferences();
if (!nsAPISecret.equals(""))
nsAPIhashCode = Hashing.sha1().hashString(nsAPISecret, Charsets.UTF_8).toString();
MainApp.bus().post(new EventNSClientStatus("Initializing"));
if (((NSClientInternalPlugin)MainApp.getSpecificPlugin(NSClientInternalPlugin.class)).paused) {
MainApp.bus().post(new EventNSClientNewLog("NSCLIENT", "paused"));
MainApp.bus().post(new EventNSClientStatus("Paused"));
} else if (!nsEnabled) {
MainApp.bus().post(new EventNSClientNewLog("NSCLIENT", "disabled"));
MainApp.bus().post(new EventNSClientStatus("Disabled"));
} else if (!nsURL.equals("")) {
try {
MainApp.bus().post(new EventNSClientStatus("Connecting ..."));
IO.Options opt = new IO.Options();
opt.forceNew = true;
opt.reconnection = true;
mSocket = IO.socket(nsURL, opt);
mSocket.on(Socket.EVENT_CONNECT, onConnect);
mSocket.on(Socket.EVENT_DISCONNECT, onDisconnect);
mSocket.on(Socket.EVENT_PING, onPing);
MainApp.bus().post(new EventNSClientNewLog("NSCLIENT", "do connect"));
mSocket.connect();
mSocket.on("dataUpdate", onDataUpdate);
} catch (URISyntaxException | RuntimeException e) {
MainApp.bus().post(new EventNSClientNewLog("NSCLIENT", "Wrong URL syntax"));
MainApp.bus().post(new EventNSClientStatus("Wrong URL syntax"));
}
} else {
MainApp.bus().post(new EventNSClientNewLog("NSCLIENT", "No NS URL specified"));
MainApp.bus().post(new EventNSClientStatus("Not configured"));
}
NSClientService.mWakeLock.release();
}
private Emitter.Listener onConnect = new Emitter.Listener() {
@Override
public void call(Object... args) {
connectCounter++;
MainApp.bus().post(new EventNSClientNewLog("NSCLIENT", "connect #" + connectCounter + " event. ID: " + mSocket.id()));
sendAuthMessage(new NSAuthAck());
}
};
private Emitter.Listener onDisconnect = new Emitter.Listener() {
@Override
public void call(Object... args) {
MainApp.bus().post(new EventNSClientNewLog("NSCLIENT", "disconnect event"));
}
};
public void destroy() {
if (mSocket != null) {
MainApp.bus().post(new EventNSClientNewLog("NSCLIENT", "destroy"));
isConnected = false;
hasWriteAuth = false;
mSocket.disconnect();
mSocket = null;
}
}
public void sendAuthMessage(NSAuthAck ack) {
JSONObject authMessage = new JSONObject();
try {
authMessage.put("client", "Android_" + nsDevice);
authMessage.put("history", nsHours);
authMessage.put("status", true); // receive status
authMessage.put("from", latestDateInReceivedData); // send data newer than
authMessage.put("secret", nsAPIhashCode);
} catch (JSONException e) {
e.printStackTrace();
return;
}
MainApp.bus().post(new EventNSClientNewLog("AUTH", "requesting auth"));
mSocket.emit("authorize", authMessage, ack);
}
@Subscribe
public void onStatusEvent(NSAuthAck ack) {
String connectionStatus = "Authenticated (";
if (ack.read) connectionStatus += "R";
if (ack.write) connectionStatus += "W";
if (ack.write_treatment) connectionStatus += "T";
connectionStatus += ')';
isConnected = true;
hasWriteAuth = ack.write && ack.write_treatment;
MainApp.bus().post(new EventNSClientStatus(connectionStatus));
MainApp.bus().post(new EventNSClientNewLog("AUTH", connectionStatus));
if (!ack.write) {
MainApp.bus().post(new EventNSClientNewLog("ERROR", "Write permission not granted !!!!"));
}
if (!ack.write_treatment) {
MainApp.bus().post(new EventNSClientNewLog("ERROR", "Write treatment permission not granted !!!!"));
}
if (!hasWriteAuth) {
Notification noperm = new Notification(Notification.NSCLIENT_NO_WRITE_PERMISSION, MainApp.sResources.getString(R.string.nowritepermission), Notification.URGENT);
MainApp.bus().post(new EventNewNotification(noperm));
} else {
MainApp.bus().post(new EventDismissNotification(Notification.NSCLIENT_NO_WRITE_PERMISSION));
}
lastReception = new Date();
}
public void readPreferences() {
nsEnabled = MainApp.getSpecificPlugin(NSClientInternalPlugin.class).isEnabled(PluginBase.GENERAL);
nsURL = SP.getString(R.string.key_nsclientinternal_url, "");
nsAPISecret = SP.getString(R.string.key_nsclientinternal_api_secret, "");
nsDevice = SP.getString("careportal_enteredby", "");
}
private Emitter.Listener onPing = new Emitter.Listener() {
@Override
public void call(final Object... args) {
if (Config.detailedLog)
MainApp.bus().post(new EventNSClientNewLog("PING", "received"));
// send data if there is something waiting
resend("Ping received");
}
};
private Emitter.Listener onDataUpdate = new Emitter.Listener() {
@Override
public void call(final Object... args) {
lastReception = new Date();
NSClientService.handler.post(new Runnable() {
@Override
public void run() {
PowerManager powerManager = (PowerManager) MainApp.instance().getApplicationContext().getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"onDataUpdate");
wakeLock.acquire();
try {
SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
JSONObject data = (JSONObject) args[0];
NSCal actualCal = new NSCal();
boolean broadcastProfile = false;
try {
// delta means only increment/changes are comming
boolean isDelta = data.has("delta");
boolean isFull = !isDelta;
MainApp.bus().post(new EventNSClientNewLog("DATA", "Data packet #" + dataCounter++ + (isDelta ? " delta" : " full")));
if (data.has("profiles")) {
JSONArray profiles = (JSONArray) data.getJSONArray("profiles");
if (profiles.length() > 0) {
JSONObject profile = (JSONObject) profiles.get(profiles.length() - 1);
String activeProfile = NSClientService.getNsProfile() == null ? null : NSClientService.getNsProfile().getActiveProfile();
NSProfile nsProfile = new NSProfile(profile, activeProfile);
NSClientService.setNsProfile(nsProfile);
broadcastProfile = true;
MainApp.bus().post(new EventNSClientNewLog("PROFILE", "profile received"));
}
}
if (data.has("status")) {
JSONObject status = data.getJSONObject("status");
NSStatus nsStatus = new NSStatus(status);
if (!status.has("versionNum")) {
if (status.getInt("versionNum") < 900) {
MainApp.bus().post(new EventNSClientNewLog("ERROR", "Unsupported Nightscout version !!!!"));
}
} else {
nightscoutVersionName = status.getString("version");
nightscoutVersionCode = status.getInt("versionNum");
}
BroadcastStatus bs = new BroadcastStatus();
bs.handleNewStatus(nsStatus, MainApp.instance().getApplicationContext(), isDelta);
if (NSClientService.getNsProfile() != null) {
String oldActiveProfile = NSClientService.getNsProfile().getActiveProfile();
String receivedActiveProfile = nsStatus.getActiveProfile();
NSClientService.getNsProfile().setActiveProfile(receivedActiveProfile);
if (receivedActiveProfile != null) {
MainApp.bus().post(new EventNSClientNewLog("PROFILE", "status activeProfile received: " + receivedActiveProfile));
}
// Change possible nulls to ""
String oldP = oldActiveProfile == null ? "" : oldActiveProfile;
String newP = receivedActiveProfile == null ? "" : receivedActiveProfile;
if (!newP.equals(oldP)) {
broadcastProfile = true;
}
}
/* Other received data to 2016/02/10
{
status: 'ok'
, name: env.name
, version: env.version
, versionNum: versionNum (for ver 1.2.3 contains 10203)
, serverTime: new Date().toISOString()
, apiEnabled: apiEnabled
, careportalEnabled: apiEnabled && env.settings.enable.indexOf('careportal') > -1
, boluscalcEnabled: apiEnabled && env.settings.enable.indexOf('boluscalc') > -1
, head: env.head
, settings: env.settings
, extendedSettings: ctx.plugins && ctx.plugins.extendedClientSettings ? ctx.plugins.extendedClientSettings(env.extendedSettings) : {}
, activeProfile ..... calculated from treatments or missing
}
*/
} else if (!isDelta) {
MainApp.bus().post(new EventNSClientNewLog("ERROR", "Unsupported Nightscout version !!!!"));
}
// If new profile received or change detected broadcast it
if (broadcastProfile && nsProfile != null) {
BroadcastProfile bp = new BroadcastProfile();
bp.handleNewTreatment(nsProfile, MainApp.instance().getApplicationContext(), isDelta);
MainApp.bus().post(new EventNSClientNewLog("PROFILE", "broadcasting"));
}
if (data.has("treatments")) {
JSONArray treatments = (JSONArray) data.getJSONArray("treatments");
JSONArray removedTreatments = new JSONArray();
JSONArray updatedTreatments = new JSONArray();
JSONArray addedTreatments = new JSONArray();
BroadcastTreatment bt = new BroadcastTreatment();
if (treatments.length() > 0)
MainApp.bus().post(new EventNSClientNewLog("DATA", "received " + treatments.length() + " treatments"));
for (Integer index = 0; index < treatments.length(); index++) {
JSONObject jsonTreatment = treatments.getJSONObject(index);
NSTreatment treatment = new NSTreatment(jsonTreatment);
// remove from upload queue if Ack is failing
UploadQueue.removeID(jsonTreatment);
//Find latest date in treatment
if (treatment.getMills() != null && treatment.getMills() < new Date().getTime())
if (treatment.getMills() > latestDateInReceivedData)
latestDateInReceivedData = treatment.getMills();
if (treatment.getAction() == null) {
if (!isCurrent(treatment)) continue;
addedTreatments.put(jsonTreatment);
} else if (treatment.getAction().equals("update")) {
if (!isCurrent(treatment)) continue;
updatedTreatments.put(jsonTreatment);
} else if (treatment.getAction().equals("remove")) {
removedTreatments.put(jsonTreatment);
}
}
if (removedTreatments.length() > 0) {
bt.handleRemovedTreatment(removedTreatments, MainApp.instance().getApplicationContext(), isDelta);
}
if (updatedTreatments.length() > 0) {
bt.handleChangedTreatment(updatedTreatments, MainApp.instance().getApplicationContext(), isDelta);
}
if (addedTreatments.length() > 0) {
bt.handleNewTreatment(addedTreatments, MainApp.instance().getApplicationContext(), isDelta);
}
}
if (data.has("devicestatus")) {
BroadcastDeviceStatus bds = new BroadcastDeviceStatus();
JSONArray devicestatuses = (JSONArray) data.getJSONArray("devicestatus");
if (devicestatuses.length() > 0) {
MainApp.bus().post(new EventNSClientNewLog("DATA", "received " + devicestatuses.length() + " devicestatuses"));
for (Integer index = 0; index < devicestatuses.length(); index++) {
JSONObject jsonStatus = devicestatuses.getJSONObject(index);
// remove from upload queue if Ack is failing
UploadQueue.removeID(jsonStatus);
}
// send only last record
bds.handleNewDeviceStatus(devicestatuses.getJSONObject(devicestatuses.length() - 1), MainApp.instance().getApplicationContext(), isDelta);
}
}
if (data.has("mbgs")) {
BroadcastMbgs bmbg = new BroadcastMbgs();
JSONArray mbgs = (JSONArray) data.getJSONArray("mbgs");
if (mbgs.length() > 0)
MainApp.bus().post(new EventNSClientNewLog("DATA", "received " + mbgs.length() + " mbgs"));
for (Integer index = 0; index < mbgs.length(); index++) {
JSONObject jsonMbg = mbgs.getJSONObject(index);
// remove from upload queue if Ack is failing
UploadQueue.removeID(jsonMbg);
}
bmbg.handleNewMbg(mbgs, MainApp.instance().getApplicationContext(), isDelta);
}
if (data.has("cals")) {
BroadcastCals bc = new BroadcastCals();
JSONArray cals = (JSONArray) data.getJSONArray("cals");
if (cals.length() > 0)
MainApp.bus().post(new EventNSClientNewLog("DATA", "received " + cals.length() + " cals"));
// Retreive actual calibration
for (Integer index = 0; index < cals.length(); index++) {
if (index == 0) {
actualCal.set(cals.optJSONObject(index));
}
// remove from upload queue if Ack is failing
UploadQueue.removeID(cals.optJSONObject(index));
}
bc.handleNewCal(cals, MainApp.instance().getApplicationContext(), isDelta);
}
if (data.has("sgvs")) {
BroadcastSgvs bs = new BroadcastSgvs();
String units = nsProfile != null ? nsProfile.getUnits() : "mg/dl";
JSONArray sgvs = (JSONArray) data.getJSONArray("sgvs");
if (sgvs.length() > 0)
MainApp.bus().post(new EventNSClientNewLog("DATA", "received " + sgvs.length() + " sgvs"));
for (Integer index = 0; index < sgvs.length(); index++) {
JSONObject jsonSgv = sgvs.getJSONObject(index);
// MainApp.bus().post(new EventNSClientNewLog("DATA", "svg " + sgvs.getJSONObject(index).toString());
NSSgv sgv = new NSSgv(jsonSgv);
// Handle new sgv here
// remove from upload queue if Ack is failing
UploadQueue.removeID(jsonSgv);
//Find latest date in sgv
if (sgv.getMills() != null && sgv.getMills() < new Date().getTime())
if (sgv.getMills() > latestDateInReceivedData)
latestDateInReceivedData = sgv.getMills();
}
bs.handleNewSgv(sgvs, MainApp.instance().getApplicationContext(), isDelta);
}
MainApp.bus().post(new EventNSClientNewLog("LAST", DateUtil.dateAndTimeString(latestDateInReceivedData)));
} catch (JSONException e) {
e.printStackTrace();
}
//MainApp.bus().post(new EventNSClientNewLog("NSCLIENT", "onDataUpdate end");
} finally {
wakeLock.release();
}
}
});
}
};
public void dbUpdate(DbRequest dbr, NSUpdateAck ack) {
try {
if (!isConnected || !hasWriteAuth) return;
JSONObject message = new JSONObject();
message.put("collection", dbr.collection);
message.put("_id", dbr._id);
message.put("data", new JSONObject(dbr.data));
mSocket.emit("dbUpdate", message, ack);
MainApp.bus().post(new EventNSClientNewLog("DBUPDATE " + dbr.collection, "Sent " + dbr._id));
} catch (JSONException e) {
e.printStackTrace();
}
}
public void dbUpdateUnset(DbRequest dbr, NSUpdateAck ack) {
try {
if (!isConnected || !hasWriteAuth) return;
JSONObject message = new JSONObject();
message.put("collection", dbr.collection);
message.put("_id", dbr._id);
message.put("data", new JSONObject(dbr.data));
mSocket.emit("dbUpdateUnset", message, ack);
MainApp.bus().post(new EventNSClientNewLog("DBUPDATEUNSET " + dbr.collection, "Sent " + dbr._id));
} catch (JSONException e) {
e.printStackTrace();
}
}
public void dbRemove(DbRequest dbr, NSUpdateAck ack) {
try {
if (!isConnected || !hasWriteAuth) return;
JSONObject message = new JSONObject();
message.put("collection", dbr.collection);
message.put("_id", dbr._id);
mSocket.emit("dbRemove", message, ack);
MainApp.bus().post(new EventNSClientNewLog("DBREMOVE " + dbr.collection, "Sent " + dbr._id));
} catch (JSONException e) {
e.printStackTrace();
}
}
@Subscribe
public void onStatusEvent(NSUpdateAck ack) {
if (ack.result) {
uploadQueue.removeID(ack.action, ack._id);
MainApp.bus().post(new EventNSClientNewLog("DBUPDATE/DBREMOVE", "Acked " + ack._id));
} else {
MainApp.bus().post(new EventNSClientNewLog("ERROR", "DBUPDATE/DBREMOVE Unknown response"));
}
}
public void dbAdd(DbRequest dbr, NSAddAck ack) {
try {
if (!isConnected || !hasWriteAuth) return;
JSONObject message = new JSONObject();
message.put("collection", dbr.collection);
message.put("data", new JSONObject(dbr.data));
mSocket.emit("dbAdd", message, ack);
MainApp.bus().post(new EventNSClientNewLog("DBADD " + dbr.collection, "Sent " + dbr.nsClientID));
} catch (JSONException e) {
e.printStackTrace();
}
}
@Subscribe
public void onStatusEvent(NSAddAck ack) {
if (ack.nsClientID != null) {
uploadQueue.removeID(ack.json);
MainApp.bus().post(new EventNSClientNewLog("DBADD", "Acked " + ack.nsClientID));
} else {
MainApp.bus().post(new EventNSClientNewLog("ERROR", "DBADD Unknown response"));
}
}
public void doPing() {
if (!isConnected || !hasWriteAuth) return;
MainApp.bus().post(new EventNSClientNewLog("PING", "Sending"));
uploading = true;
JSONObject message = new JSONObject();
try {
message.put("mills", new Date().getTime());
} catch (JSONException e) {
e.printStackTrace();
}
NSPingAck ack = new NSPingAck();
mSocket.emit("nsping", message, ack);
synchronized (ack) {
try {
ack.wait(timeToWaitForResponseInMs);
} catch (InterruptedException e) {
}
}
if (ack.received) {
String connectionStatus = "Pong received";
if (ack.auth_received) {
connectionStatus += ": ";
if (ack.read) connectionStatus += "R";
if (ack.write) connectionStatus += "W";
if (ack.write_treatment) connectionStatus += "T";
}
if (!ack.read) sendAuthMessage(new NSAuthAck());
MainApp.bus().post(new EventNSClientNewLog("AUTH ", connectionStatus));
} else {
MainApp.bus().post(new EventNSClientNewLog("PING", "Ping lost"));
}
uploading = false;
}
private boolean isCurrent(NSTreatment treatment) {
long now = (new Date()).getTime();
long minPast = now - nsHours * 60L * 60 * 1000;
if (treatment.getMills() == null) {
log.debug("treatment.getMills() == null " + treatment.getData().toString());
return false;
}
if (treatment.getMills() > minPast) return true;
return false;
}
public void resend(final String reason) {
if (UploadQueue.size() == 0)
return;
if (!isConnected || !hasWriteAuth) return;
MainApp.bus().post(new EventNSClientNewLog("QUEUE", "Resend started: " + reason));
handler.post(new Runnable() {
@Override
public void run() {
Logger log = LoggerFactory.getLogger(UploadQueue.class);
if (mSocket == null || !mSocket.connected()) return;
CloseableIterator<DbRequest> iterator = null;
try {
iterator = MainApp.getDbHelper().getDaoDbRequest().closeableIterator();
try {
while (iterator.hasNext()) {
DbRequest dbr = iterator.next();
if (dbr.action.equals("dbAdd")) {
NSAddAck addAck = new NSAddAck();
dbAdd(dbr, addAck);
} else if (dbr.action.equals("dbRemove")) {
NSUpdateAck removeAck = new NSUpdateAck(dbr.action, dbr._id);
dbRemove(dbr, removeAck);
} else if (dbr.action.equals("dbUpdate")) {
NSUpdateAck updateAck = new NSUpdateAck(dbr.action, dbr._id);
dbUpdate(dbr, updateAck);
} else if (dbr.action.equals("dbUpdateUnset")) {
NSUpdateAck updateUnsetAck = new NSUpdateAck(dbr.action, dbr._id);
dbUpdateUnset(dbr, updateUnsetAck);
}
}
} finally {
iterator.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
MainApp.bus().post(new EventNSClientNewLog("QUEUE", "Resend ended: " + reason));
}
});
}
public void restart() {
destroy();
initialize();
}
}

View file

@ -1,242 +0,0 @@
package info.nightscout.androidaps.plugins.OpenAPSAMA;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.db.BgReading;
import info.nightscout.client.data.NSProfile;
import info.nightscout.utils.Round;
import info.nightscout.utils.SafeParse;
public class Autosens {
private static Logger log = LoggerFactory.getLogger(Autosens.class);
public static AutosensResult detectSensitivityandCarbAbsorption(List<BgReading> glucose_data, Long mealTime) {
SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile();
//console.error(mealTime);
double deviationSum = 0;
double carbsAbsorbed = 0;
List<BgReading> bucketed_data = new ArrayList<>();
bucketed_data.add(glucose_data.get(0));
int j = 0;
for (int i = 1; i < glucose_data.size(); ++i) {
long bgTime = glucose_data.get(i).getTimeIndex();
long lastbgTime = glucose_data.get(i - 1).getTimeIndex();
if (glucose_data.get(i).value < 39 || glucose_data.get(i - 1).value < 39) {
continue;
}
long elapsed_minutes = (bgTime - lastbgTime) / (60 * 1000);
if (Math.abs(elapsed_minutes) > 8) {
// interpolate missing data points
double lastbg = glucose_data.get(i - 1).value;
elapsed_minutes = Math.abs(elapsed_minutes);
//console.error(elapsed_minutes);
long nextbgTime;
while (elapsed_minutes > 5) {
nextbgTime = lastbgTime + 5 * 60 * 1000;
j++;
BgReading newBgreading = new BgReading();
newBgreading.timeIndex = nextbgTime;
double gapDelta = glucose_data.get(i).value - lastbg;
//console.error(gapDelta, lastbg, elapsed_minutes);
double nextbg = lastbg + (5 / elapsed_minutes * gapDelta);
newBgreading.value = Math.round(nextbg);
//console.error("Interpolated", bucketed_data[j]);
bucketed_data.add(newBgreading);
elapsed_minutes = elapsed_minutes - 5;
lastbg = nextbg;
lastbgTime = nextbgTime;
}
} else if (Math.abs(elapsed_minutes) > 2) {
j++;
BgReading newBgreading = new BgReading();
newBgreading.value = glucose_data.get(i).value;
newBgreading.timeIndex = bgTime;
bucketed_data.add(newBgreading);
} else {
bucketed_data.get(j).value = (bucketed_data.get(j).value + glucose_data.get(i).value) / 2;
}
}
//console.error(bucketed_data);
double[] avgDeltas = new double[bucketed_data.size() - 2];
double[] bgis = new double[bucketed_data.size() - 2];
double[] deviations = new double[bucketed_data.size() - 2];
String pastSensitivity = "";
for (int i = 0; i < bucketed_data.size() - 3; ++i) {
long bgTime = bucketed_data.get(i).timeIndex;
int secondsFromMidnight = NSProfile.secondsFromMidnight(new Date(bgTime));
double sens = NSProfile.toMgdl(profile.getIsf(secondsFromMidnight), profile.getUnits());
//console.error(bgTime , bucketed_data[i].glucose);
double bg;
double avgDelta;
double delta;
bg = bucketed_data.get(i).value;
if (bg < 40 || bucketed_data.get(i + 3).value < 40) {
log.error("! value < 40");
continue;
}
avgDelta = (bg - bucketed_data.get(i + 3).value) / 3;
delta = (bg - bucketed_data.get(i + 1).value);
// avgDelta = avgDelta.toFixed(2);
IobTotal iob = IobTotal.calulateFromTreatmentsAndTemps(bgTime);
double bgi = Math.round((-iob.activity * sens * 5) * 100) / 100d;
// bgi = bgi.toFixed(2);
//console.error(delta);
double deviation = delta - bgi;
// deviation = deviation.toFixed(2);
//if (deviation < 0 && deviation > -2) { console.error("BG: "+bg+", avgDelta: "+avgDelta+", BGI: "+bgi+", deviation: "+deviation); }
// Exclude large positive deviations (carb absorption) from autosens
if (avgDelta - bgi < 6) {
if (deviation > 0) {
pastSensitivity += "+";
} else if (deviation == 0) {
pastSensitivity += "=";
} else {
pastSensitivity += "-";
}
avgDeltas[i] = avgDelta;
bgis[i] = bgi;
deviations[i] = deviation;
deviationSum += deviation;
} else {
pastSensitivity += ">";
//console.error(bgTime);
}
//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);
// if bgTime is more recent than mealTime
if (mealTime != null && bgTime > mealTime) {
// figure out how many carbs that represents
// but always assume at least 3mg/dL/5m (default) absorption
double ci = Math.max(deviation, SafeParse.stringToDouble(SP.getString("openapsama_min_5m_carbimpact", "3.0")));
double absorbed = ci * profile.getIc(secondsFromMidnight) / sens;
// and add that to the running total carbsAbsorbed
carbsAbsorbed += absorbed;
}
}
double ratio = 1;
String ratioLimit = "";
String sensResult = "";
if (mealTime == null) {
//console.error("");
log.debug(pastSensitivity);
//console.log(JSON.stringify(avgDeltas));
//console.log(JSON.stringify(bgis));
Arrays.sort(avgDeltas);
Arrays.sort(bgis);
Arrays.sort(deviations);
for (double i = 0.9; i > 0.1; i = i - 0.02) {
//console.error("p="+i.toFixed(2)+": "+percentile(avgDeltas, i).toFixed(2)+", "+percentile(bgis, i).toFixed(2)+", "+percentile(deviations, i).toFixed(2));
if (percentile(deviations, (i + 0.02)) >= 0 && percentile(deviations, i) < 0) {
//console.error("p="+i.toFixed(2)+": "+percentile(avgDeltas, i).toFixed(2)+", "+percentile(bgis, i).toFixed(2)+", "+percentile(deviations, i).toFixed(2));
log.debug(Math.round(100 * i) + "% of non-meal deviations negative (target 45%-50%)");
}
}
double pSensitive = percentile(deviations, 0.50);
double pResistant = percentile(deviations, 0.45);
//p30 = percentile(deviations, 0.3);
// average = deviationSum / deviations.length;
//console.error("Mean deviation: "+average.toFixed(2));
double basalOff = 0;
if (pSensitive < 0) { // sensitive
basalOff = pSensitive * (60 / 5) / NSProfile.toMgdl(profile.getIsf(NSProfile.secondsFromMidnight()), profile.getUnits());
sensResult = "Excess insulin sensitivity detected";
} else if (pResistant > 0) { // resistant
basalOff = pResistant * (60 / 5) / NSProfile.toMgdl(profile.getIsf(NSProfile.secondsFromMidnight()), profile.getUnits());
sensResult = "Excess insulin resistance detected";
} else {
sensResult = "Sensitivity normal";
}
log.debug(sensResult);
ratio = 1 + (basalOff / profile.getMaxDailyBasal());
// don't adjust more than 1.5x
double rawRatio = ratio;
ratio = Math.max(ratio, SafeParse.stringToDouble(SP.getString("openapsama_autosens_min", "0.7")));
ratio = Math.min(ratio, SafeParse.stringToDouble(SP.getString("openapsama_autosens_max", "1.2")));
if (ratio != rawRatio) {
ratioLimit = "Ratio limited from " + rawRatio + " to " + ratio;
log.debug(ratioLimit);
}
double newisf = Math.round(NSProfile.toMgdl(profile.getIsf(NSProfile.secondsFromMidnight()), profile.getUnits()) / ratio);
if (ratio != 1) {
log.debug("ISF adjusted from " + NSProfile.toMgdl(profile.getIsf(NSProfile.secondsFromMidnight()), profile.getUnits()) + " to " + newisf);
}
//console.error("Basal adjustment "+basalOff.toFixed(2)+"U/hr");
//console.error("Ratio: "+ratio*100+"%: new ISF: "+newisf.toFixed(1)+"mg/dL/U");
}
AutosensResult output = new AutosensResult();
output.ratio = Round.roundTo(ratio, 0.01);
output.carbsAbsorbed = Round.roundTo(carbsAbsorbed, 0.01);
output.pastSensitivity = pastSensitivity;
output.ratioLimit = ratioLimit;
output.sensResult = sensResult;
return output;
}
// From https://gist.github.com/IceCreamYou/6ffa1b18c4c8f6aeaad2
// Returns the value at a given percentile in a sorted numeric array.
// "Linear interpolation between closest ranks" method
public static double percentile(double[] arr, double p) {
if (arr.length == 0) return 0;
if (p <= 0) return arr[0];
if (p >= 1) return arr[arr.length - 1];
double index = arr.length * p,
lower = Math.floor(index),
upper = lower + 1,
weight = index % 1;
if (upper >= arr.length) return arr[(int) lower];
return arr[(int) lower] * (1 - weight) + arr[(int) upper] * weight;
}
// Returns the percentile of the given value in a sorted numeric array.
public static double percentRank(double[] arr, double v) {
for (int i = 0, l = arr.length; i < l; i++) {
if (v <= arr[i]) {
while (i < l && v == arr[i]) i++;
if (i == 0) return 0;
if (v != arr[i - 1]) {
i += (v - arr[i - 1]) / (arr[i] - arr[i - 1]);
}
return i / l;
}
}
return 1;
}
}

View file

@ -1,8 +1,5 @@
package info.nightscout.androidaps.plugins.OpenAPSAMA;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import com.eclipsesource.v8.JavaVoidCallback;
import com.eclipsesource.v8.V8;
import com.eclipsesource.v8.V8Array;
@ -16,18 +13,16 @@ import org.slf4j.LoggerFactory;
import java.io.IOException;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.data.GlucoseStatus;
import info.nightscout.androidaps.data.MealData;
import info.nightscout.androidaps.db.TempBasal;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin;
import info.nightscout.androidaps.plugins.Loop.ScriptReader;
import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.client.data.NSProfile;
import info.nightscout.utils.SafeParse;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile;
import info.nightscout.utils.SP;
public class DetermineBasalAdapterAMAJS {
private static Logger log = LoggerFactory.getLogger(DetermineBasalAdapterAMAJS.class);
@ -209,7 +204,6 @@ public class DetermineBasalAdapterAMAJS {
double min_5m_carbimpact) {
String units = profile.getUnits();
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
mProfile = new V8Object(mV8rt);
mProfile.add("max_iob", maxIob);
@ -222,13 +216,13 @@ public class DetermineBasalAdapterAMAJS {
mProfile.add("target_bg", targetBg);
mProfile.add("carb_ratio", profile.getIc(profile.secondsFromMidnight()));
mProfile.add("sens", NSProfile.toMgdl(profile.getIsf(NSProfile.secondsFromMidnight()).doubleValue(), units));
mProfile.add("max_daily_safety_multiplier", SafeParse.stringToInt(preferences.getString("openapsama_max_daily_safety_multiplier", "3")));
mProfile.add("current_basal_safety_multiplier", SafeParse.stringToInt(preferences.getString("openapsama_current_basal_safety_multiplier", "4")));
mProfile.add("max_daily_safety_multiplier", SP.getInt("openapsama_max_daily_safety_multiplier", 3));
mProfile.add("current_basal_safety_multiplier", SP.getInt("openapsama_current_basal_safety_multiplier", 4));
mProfile.add("skip_neutral_temps", true);
mProfile.add("current_basal", pump.getBaseBasalRate());
mProfile.add("temptargetSet", tempTargetSet);
mProfile.add("autosens_adjust_targets", preferences.getBoolean("openapsama_autosens_adjusttargets", true));
mProfile.add("min_5m_carbimpact", SafeParse.stringToDouble(preferences.getString("openapsama_min_5m_carbimpact", "3.0")));
mProfile.add("autosens_adjust_targets", SP.getBoolean("openapsama_autosens_adjusttargets", true));
mProfile.add("min_5m_carbimpact", SP.getDouble("openapsama_min_5m_carbimpact", 3d));
mV8rt.add(PARAM_profile, mProfile);
mCurrentTemp = new V8Object(mV8rt);
@ -244,7 +238,7 @@ public class DetermineBasalAdapterAMAJS {
mV8rt.add(PARAM_currentTemp, mCurrentTemp);
mIobData = mV8rt.executeArrayScript(IobTotal.convertToJSONArray(iobArray).toString());
mIobData = mV8rt.executeArrayScript(IobCobCalculatorPlugin.convertToJSONArray(iobArray).toString());
mV8rt.add(PARAM_iobData, mIobData);
mGlucoseStatus = new V8Object(mV8rt);

View file

@ -9,6 +9,8 @@ import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import com.crashlytics.android.answers.Answers;
import com.crashlytics.android.answers.CustomEvent;
import com.squareup.otto.Subscribe;
import org.json.JSONArray;
@ -18,12 +20,11 @@ import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.interfaces.FragmentBase;
import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateGui;
import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateResultGui;
import info.nightscout.utils.JSONFormatter;
public class OpenAPSAMAFragment extends Fragment implements View.OnClickListener, FragmentBase {
public class OpenAPSAMAFragment extends Fragment implements View.OnClickListener {
private static Logger log = LoggerFactory.getLogger(OpenAPSAMAFragment.class);
private static OpenAPSAMAPlugin openAPSAMAPlugin;
@ -74,6 +75,7 @@ public class OpenAPSAMAFragment extends Fragment implements View.OnClickListener
switch (view.getId()) {
case R.id.openapsma_run:
getPlugin().invoke("OpenAPSAMA button");
Answers.getInstance().logCustom(new CustomEvent("OpenAPS_AMA_Run"));
break;
}

View file

@ -1,15 +1,11 @@
package info.nightscout.androidaps.plugins.OpenAPSAMA;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import org.json.JSONException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.Constants;
@ -17,22 +13,23 @@ import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.GlucoseStatus;
import info.nightscout.androidaps.data.MealData;
import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.interfaces.APSInterface;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.interfaces.TempBasalsInterface;
import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensResult;
import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin;
import info.nightscout.androidaps.plugins.Loop.APSResult;
import info.nightscout.androidaps.plugins.Loop.ScriptReader;
import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateGui;
import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateResultGui;
import info.nightscout.androidaps.plugins.TempTargetRange.TempTargetRangePlugin;
import info.nightscout.client.data.NSProfile;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.Profiler;
import info.nightscout.utils.Round;
import info.nightscout.utils.SP;
import info.nightscout.utils.SafeParse;
import info.nightscout.utils.ToastUtils;
@ -82,6 +79,16 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface {
return true;
}
@Override
public boolean hasFragment() {
return true;
}
@Override
public boolean showInList(int type) {
return true;
}
@Override
public void setFragmentVisible(int type, boolean fragmentVisible) {
if (type == APS) this.fragmentVisible = fragmentVisible;
@ -142,7 +149,7 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface {
return;
}
if (profile == null) {
if (profile == null || profile.getIc(NSProfile.secondsFromMidnight()) == null || profile.getIsf(NSProfile.secondsFromMidnight()) == null || profile.getBasal(NSProfile.secondsFromMidnight()) == null ) {
MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.instance().getString(R.string.openapsma_noprofile)));
if (Config.logAPSResult)
log.debug(MainApp.instance().getString(R.string.openapsma_noprofile));
@ -156,12 +163,11 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface {
return;
}
SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
String units = profile.getUnits();
String maxBgDefault = Constants.MAX_BG_DEFAULT_MGDL;
String minBgDefault = Constants.MIN_BG_DEFAULT_MGDL;
String targetBgDefault = Constants.TARGET_BG_DEFAULT_MGDL;
Double maxBgDefault = Constants.MAX_BG_DEFAULT_MGDL;
Double minBgDefault = Constants.MIN_BG_DEFAULT_MGDL;
Double targetBgDefault = Constants.TARGET_BG_DEFAULT_MGDL;
if (!units.equals(Constants.MGDL)) {
maxBgDefault = Constants.MAX_BG_DEFAULT_MMOL;
minBgDefault = Constants.MIN_BG_DEFAULT_MMOL;
@ -170,18 +176,18 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface {
Date now = new Date();
double maxIob = SafeParse.stringToDouble(SP.getString("openapsma_max_iob", "1.5"));
double maxBasal = SafeParse.stringToDouble(SP.getString("openapsma_max_basal", "1"));
double minBg = NSProfile.toMgdl(SafeParse.stringToDouble(SP.getString("openapsma_min_bg", minBgDefault)), units);
double maxBg = NSProfile.toMgdl(SafeParse.stringToDouble(SP.getString("openapsma_max_bg", maxBgDefault)), units);
double targetBg = NSProfile.toMgdl(SafeParse.stringToDouble(SP.getString("openapsma_target_bg", targetBgDefault)), units);
double maxIob = SP.getDouble("openapsma_max_iob", 1.5d);
double maxBasal = SP.getDouble("openapsma_max_basal", 1d);
double minBg = NSProfile.toMgdl(SP.getDouble("openapsma_min_bg", minBgDefault), units);
double maxBg = NSProfile.toMgdl(SP.getDouble("openapsma_max_bg", maxBgDefault), units);
double targetBg = NSProfile.toMgdl(SP.getDouble("openapsma_target_bg", targetBgDefault), units);
minBg = Round.roundTo(minBg, 0.1d);
maxBg = Round.roundTo(maxBg, 0.1d);
Date start = new Date();
Date startPart = new Date();
IobTotal[] iobArray = IobTotal.calculateIobArrayInDia();
IobTotal[] iobArray = IobCobCalculatorPlugin.calculateIobArrayInDia();
Profiler.log(log, "calculateIobArrayInDia()", startPart);
startPart = new Date();
@ -216,15 +222,14 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface {
if (!checkOnlyHardLimits(profile.getMaxDailyBasal(), "max_daily_basal", 0.1, 10)) return;
if (!checkOnlyHardLimits(pump.getBaseBasalRate(), "current_basal", 0.01, 5)) return;
startPart = new Date();
long oldestDataAvailable = MainApp.getConfigBuilder().getActiveTempBasals().oldestDataAvaialable();
List<BgReading> bgReadings = MainApp.getDbHelper().getBgreadingsDataFromTime(Math.max(oldestDataAvailable, (long) (new Date().getTime() - 60 * 60 * 1000L * (24 + profile.getDia()))), false);
log.debug("Limiting data to oldest available temps: " + new Date(oldestDataAvailable).toString() + " (" + bgReadings.size() + " records)");
Profiler.log(log, "getBgreadingsDataFromTime()", startPart);
long getBGDataFrom = Math.max(oldestDataAvailable, (long) (new Date().getTime() - 60 * 60 * 1000L * (24 + profile.getDia())));
log.debug("Limiting data to oldest available temps: " + new Date(oldestDataAvailable).toString());
startPart = new Date();
if(MainApp.getConfigBuilder().isAMAModeEnabled()){
lastAutosensResult = Autosens.detectSensitivityandCarbAbsorption(bgReadings, null);
//lastAutosensResult = Autosens.detectSensitivityandCarbAbsorption(getBGDataFrom, null);
lastAutosensResult = IobCobCalculatorPlugin.detectSensitivity(getBGDataFrom);
} else {
lastAutosensResult = new AutosensResult();
}

View file

@ -18,7 +18,7 @@ import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.data.MealData;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.Loop.ScriptReader;
import info.nightscout.client.data.NSProfile;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile;
public class DetermineBasalAdapterMAJS {
private static Logger log = LoggerFactory.getLogger(DetermineBasalAdapterMAJS.class);

View file

@ -9,6 +9,8 @@ import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import com.crashlytics.android.answers.Answers;
import com.crashlytics.android.answers.CustomEvent;
import com.squareup.otto.Subscribe;
import org.slf4j.Logger;
@ -16,18 +18,17 @@ import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.interfaces.FragmentBase;
import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateGui;
import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateResultGui;
import info.nightscout.utils.JSONFormatter;
public class OpenAPSMAFragment extends Fragment implements View.OnClickListener, FragmentBase {
public class OpenAPSMAFragment extends Fragment implements View.OnClickListener {
private static Logger log = LoggerFactory.getLogger(OpenAPSMAFragment.class);
private static OpenAPSMAPlugin openAPSMAPlugin;
public static OpenAPSMAPlugin getPlugin() {
if(openAPSMAPlugin==null){
if (openAPSMAPlugin == null) {
openAPSMAPlugin = new OpenAPSMAPlugin();
}
return openAPSMAPlugin;
@ -68,6 +69,7 @@ public class OpenAPSMAFragment extends Fragment implements View.OnClickListener,
switch (view.getId()) {
case R.id.openapsma_run:
getPlugin().invoke("OpenAPSMA button");
Answers.getInstance().logCustom(new CustomEvent("OpenAPS_MA_Run"));
break;
}

View file

@ -1,8 +1,5 @@
package info.nightscout.androidaps.plugins.OpenAPSMA;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import org.json.JSONException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -25,15 +22,15 @@ import info.nightscout.androidaps.interfaces.TempBasalsInterface;
import info.nightscout.androidaps.interfaces.TreatmentsInterface;
import info.nightscout.androidaps.plugins.Loop.APSResult;
import info.nightscout.androidaps.plugins.Loop.ScriptReader;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile;
import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateGui;
import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateResultGui;
import info.nightscout.androidaps.plugins.TempTargetRange.TempTargetRangePlugin;
import info.nightscout.client.data.NSProfile;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.Profiler;
import info.nightscout.utils.Round;
import info.nightscout.utils.SP;
import info.nightscout.utils.SafeParse;
import info.nightscout.utils.ToastUtils;
import static info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin.checkOnlyHardLimits;
import static info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin.verifyHardLimits;
@ -83,6 +80,16 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface {
return true;
}
@Override
public boolean hasFragment() {
return true;
}
@Override
public boolean showInList(int type) {
return true;
}
@Override
public void setFragmentVisible(int type, boolean fragmentVisible) {
if (type == APS) this.fragmentVisible = fragmentVisible;
@ -157,12 +164,11 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface {
return;
}
SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
String units = profile.getUnits();
String maxBgDefault = Constants.MAX_BG_DEFAULT_MGDL;
String minBgDefault = Constants.MIN_BG_DEFAULT_MGDL;
String targetBgDefault = Constants.TARGET_BG_DEFAULT_MGDL;
Double maxBgDefault = Constants.MAX_BG_DEFAULT_MGDL;
Double minBgDefault = Constants.MIN_BG_DEFAULT_MGDL;
Double targetBgDefault = Constants.TARGET_BG_DEFAULT_MGDL;
if (!units.equals(Constants.MGDL)) {
maxBgDefault = Constants.MAX_BG_DEFAULT_MMOL;
minBgDefault = Constants.MIN_BG_DEFAULT_MMOL;
@ -171,11 +177,11 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface {
Date now = new Date();
double maxIob = SafeParse.stringToDouble(SP.getString("openapsma_max_iob", "1.5"));
double maxIob = SP.getDouble("openapsma_max_iob", 1.5d);
double maxBasal = SafeParse.stringToDouble(SP.getString("openapsma_max_basal", "1"));
double minBg = NSProfile.toMgdl(SafeParse.stringToDouble(SP.getString("openapsma_min_bg", minBgDefault)), units);
double maxBg = NSProfile.toMgdl(SafeParse.stringToDouble(SP.getString("openapsma_max_bg", maxBgDefault)), units);
double targetBg = NSProfile.toMgdl(SafeParse.stringToDouble(SP.getString("openapsma_target_bg", targetBgDefault)), units);
double minBg = NSProfile.toMgdl(SP.getDouble("openapsma_min_bg", minBgDefault), units);
double maxBg = NSProfile.toMgdl(SP.getDouble("openapsma_max_bg", maxBgDefault), units);
double targetBg = NSProfile.toMgdl(SP.getDouble("openapsma_target_bg", targetBgDefault), units);
minBg = Round.roundTo(minBg, 0.1d);
maxBg = Round.roundTo(maxBg, 0.1d);

View file

@ -18,10 +18,11 @@ import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.events.EventPumpStatusChanged;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.Overview.events.EventDismissBolusprogressIfRunning;
import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress;
import info.nightscout.androidaps.plugins.DanaR.events.EventDanaRBolusStart;
import info.nightscout.androidaps.plugins.DanaR.events.EventDanaRConnectionStatus;
import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRBolusStart;
public class BolusProgressDialog extends DialogFragment implements View.OnClickListener {
private static Logger log = LoggerFactory.getLogger(BolusProgressDialog.class);
@ -46,7 +47,7 @@ public class BolusProgressDialog extends DialogFragment implements View.OnClickL
bolusEnded = false;
}
public void setHelperActivity(BolusProgressHelperActivity activity){
public void setHelperActivity(BolusProgressHelperActivity activity) {
this.helperActivity = activity;
}
@ -77,9 +78,9 @@ public class BolusProgressDialog extends DialogFragment implements View.OnClickL
}
@Override
public void dismiss(){
public void dismiss() {
super.dismiss();
if (helperActivity!= null){
if (helperActivity != null) {
helperActivity.finish();
}
}
@ -128,7 +129,14 @@ public class BolusProgressDialog extends DialogFragment implements View.OnClickL
}
@Subscribe
public void onStatusEvent(final EventDanaRConnectionStatus c) {
public void onStatusEvent(final EventDismissBolusprogressIfRunning ev) {
if(BolusProgressDialog.running){
dismiss();
}
}
@Subscribe
public void onStatusEvent(final EventPumpStatusChanged c) {
Activity activity = getActivity();
if (activity != null) {
@ -136,14 +144,7 @@ public class BolusProgressDialog extends DialogFragment implements View.OnClickL
new Runnable() {
@Override
public void run() {
if (c.sStatus == c.CONNECTING) {
statusView.setText(String.format(MainApp.sResources.getString(R.string.danar_history_connectingfor), c.sSecondsElapsed));
} else if (c.sStatus == c.CONNECTED) {
statusView.setText(MainApp.sResources.getString(R.string.connected));
} else {
statusView.setText(MainApp.sResources.getString(R.string.disconnected));
if (started) scheduleDismiss();
}
statusView.setText(c.textStatus());
}
}
);

View file

@ -12,6 +12,9 @@ import android.view.WindowManager;
import android.widget.Button;
import android.widget.TextView;
import com.crashlytics.android.answers.Answers;
import com.crashlytics.android.answers.CustomEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -21,7 +24,7 @@ import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.GlucoseStatus;
import info.nightscout.client.data.NSProfile;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile;
import info.nightscout.utils.PlusMinusEditText;
import info.nightscout.utils.XdripCalibrations;
@ -32,14 +35,16 @@ public class CalibrationDialog extends DialogFragment implements View.OnClickLis
PlusMinusEditText bgText;
TextView unitsView;
Context parentContext;
Context context;
public CalibrationDialog() {
// Required empty public constructor
}
public void setContext(Context context) {
parentContext = context;
@Override
public void onAttach(Context context) {
super.onAttach(context);
this.context = context;
}
@Override
@ -54,14 +59,19 @@ public class CalibrationDialog extends DialogFragment implements View.OnClickLis
okButton.setOnClickListener(this);
NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile();
Double bg = NSProfile.fromMgdlToUnits(GlucoseStatus.getGlucoseStatusData() != null ? GlucoseStatus.getGlucoseStatusData().glucose : 0d, profile.getUnits());
if (profile.getUnits().equals(Constants.MMOL))
Double bg = profile != null ? NSProfile.fromMgdlToUnits(GlucoseStatus.getGlucoseStatusData() != null ? GlucoseStatus.getGlucoseStatusData().glucose : 0d, profile.getUnits()) : 0d;
String units = Constants.MGDL;
if (profile != null)
units = profile.getUnits();
if (units.equals(Constants.MMOL))
bgText = new PlusMinusEditText(view, R.id.overview_calibration_bg, R.id.overview_calibration_bg_plus, R.id.overview_calibration_bg_minus, bg, 0d, 30d, 0.1d, new DecimalFormat("0.0"), false);
else
bgText = new PlusMinusEditText(view, R.id.overview_calibration_bg, R.id.overview_calibration_bg_plus, R.id.overview_calibration_bg_minus, bg, 0d, 500d, 1d, new DecimalFormat("0"), false);
unitsView = (TextView) view.findViewById(R.id.overview_calibration_units);
unitsView.setText(profile.getUnits());
unitsView.setText(units);
return view;
}
@ -71,8 +81,9 @@ public class CalibrationDialog extends DialogFragment implements View.OnClickLis
switch (view.getId()) {
case R.id.overview_calibration_okbutton:
final Double bg = bgText.getValue();
XdripCalibrations.confirmAndSendCalibration(bg, parentContext);
XdripCalibrations.confirmAndSendCalibration(bg, context);
dismiss();
Answers.getInstance().logCustom(new CustomEvent("Calibration"));
break;
}
}

View file

@ -16,6 +16,9 @@ import android.view.WindowManager;
import android.widget.Button;
import android.widget.TextView;
import com.crashlytics.android.answers.Answers;
import com.crashlytics.android.answers.CustomEvent;
import java.text.DecimalFormat;
import info.nightscout.androidaps.Constants;
@ -107,7 +110,7 @@ public class NewTreatmentDialog extends DialogFragment implements OnClickListene
mHandler.post(new Runnable() {
@Override
public void run() {
PumpEnactResult result = pump.deliverTreatment(finalInsulinAfterConstraints, finalCarbsAfterConstraints, context);
PumpEnactResult result = pump.deliverTreatment(MainApp.getConfigBuilder().getActiveInsulin(), finalInsulinAfterConstraints, finalCarbsAfterConstraints, context);
if (!result.success) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(MainApp.sResources.getString(R.string.treatmentdeliveryerror));
@ -117,6 +120,7 @@ public class NewTreatmentDialog extends DialogFragment implements OnClickListene
}
}
});
Answers.getInstance().logCustom(new CustomEvent("Bolus"));
}
}
});

View file

@ -1,5 +1,6 @@
package info.nightscout.androidaps.plugins.Overview.Dialogs;
import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
@ -21,13 +22,19 @@ import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;
import com.crashlytics.android.answers.Answers;
import com.crashlytics.android.answers.CustomEvent;
import com.squareup.otto.Subscribe;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Text;
import java.text.DecimalFormat;
import java.util.ArrayList;
@ -39,36 +46,58 @@ import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.GlucoseStatus;
import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.events.EventNewBG;
import info.nightscout.androidaps.events.EventRefreshGui;
import info.nightscout.androidaps.interfaces.TempBasalsInterface;
import info.nightscout.androidaps.interfaces.TreatmentsInterface;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.client.data.NSProfile;
import info.nightscout.androidaps.plugins.Loop.APSResult;
import info.nightscout.androidaps.plugins.Loop.LoopPlugin;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile;
import info.nightscout.androidaps.plugins.OpenAPSAMA.DetermineBasalResultAMA;
import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin;
import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateGui;
import info.nightscout.utils.BolusWizard;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.PlusMinusEditText;
import info.nightscout.utils.SP;
import info.nightscout.utils.SafeParse;
import info.nightscout.utils.ToastUtils;
public class WizardDialog extends DialogFragment implements OnClickListener {
public class WizardDialog extends DialogFragment implements OnClickListener, CompoundButton.OnCheckedChangeListener, Spinner.OnItemSelectedListener {
private static Logger log = LoggerFactory.getLogger(WizardDialog.class);
Button wizardDialogDeliverButton;
TextView correctionInput;
TextView carbsInput;
TextView bgInput;
TextView bg, bgInsulin, bgUnits;
TextView bg;
TextView bgInsulin;
TextView bgUnits;
CheckBox bgCheckbox;
TextView carbs, carbsInsulin;
TextView carbs;
TextView carbsInsulin;
TextView bolusIobInsulin;
TextView basalIobInsulin;
CheckBox bolusIobCheckbox;
CheckBox basalIobCheckbox;
TextView correctionInsulin;
TextView total, totalInsulin;
TextView total;
TextView totalInsulin;
EditText carbTimeEdit;
Spinner profileSpinner;
CheckBox superbolusCheckbox;
TextView superbolus;
TextView superbolusInsulin;
CheckBox bgtrendCheckbox;
TextView bgTrend;
TextView bgTrendInsulin;
LinearLayout cobLayout;
CheckBox cobCheckbox;
TextView cob;
TextView cobInsulin;
PlusMinusEditText editBg;
PlusMinusEditText editCarbs;
@ -78,21 +107,69 @@ public class WizardDialog extends DialogFragment implements OnClickListener {
Integer calculatedCarbs = 0;
Double calculatedTotalInsulin = 0d;
JSONObject boluscalcJSON;
boolean cobAvailable = false;
Handler mHandler;
public static HandlerThread mHandlerThread;
Context parentContext;
Context context;
public WizardDialog() {
super();
mHandlerThread = new HandlerThread(WizardDialog.class.getSimpleName());
mHandlerThread.start();
mHandler = new Handler(mHandlerThread.getLooper());
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
this.context = context;
}
public void setContext(Context context) {
parentContext = context;
@Override
public void onResume() {
super.onResume();
if (getDialog() != null)
getDialog().getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
MainApp.bus().register(this);
}
@Override
public void onPause() {
super.onPause();
MainApp.bus().unregister(this);
}
@Subscribe
public void onStatusEvent(final EventOpenAPSUpdateGui e) {
Activity activity = getActivity();
if (activity != null)
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
if (ConfigBuilderPlugin.getActiveAPS() instanceof OpenAPSAMAPlugin && ConfigBuilderPlugin.getActiveAPS().getLastAPSResult() != null && ConfigBuilderPlugin.getActiveAPS().getLastAPSRun().after(new Date(new Date().getTime() - 11 * 60 * 1000L))) {
cobLayout.setVisibility(View.VISIBLE);
cobAvailable = true;
} else {
cobLayout.setVisibility(View.GONE);
cobAvailable = false;
}
calculateInsulin();
}
});
}
@Subscribe
public void onStatusEvent(final EventNewBG e) {
Activity activity = getActivity();
if (activity != null)
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
calculateInsulin();
}
});
}
final private TextWatcher textWatcher = new TextWatcher() {
@ -110,66 +187,61 @@ public class WizardDialog extends DialogFragment implements OnClickListener {
}
};
final CompoundButton.OnCheckedChangeListener onCheckedChangeListener = new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
calculateInsulin();
}
};
final AdapterView.OnItemSelectedListener onItemSelectedListener = new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
calculateInsulin();
wizardDialogDeliverButton.setVisibility(View.VISIBLE);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
ToastUtils.showToastInUiThread(parentContext, MainApp.sResources.getString(R.string.noprofileselected));
wizardDialogDeliverButton.setVisibility(View.GONE);
}
};
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.overview_wizard_dialog, null, false);
wizardDialogDeliverButton = (Button) view.findViewById(R.id.treatments_wizard_deliverButton);
wizardDialogDeliverButton.setOnClickListener(this);
getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
correctionInput = (TextView) view.findViewById(R.id.treatments_wizard_correctioninput);
carbsInput = (TextView) view.findViewById(R.id.treatments_wizard_carbsinput);
bgInput = (TextView) view.findViewById(R.id.treatments_wizard_bginput);
correctionInput.addTextChangedListener(textWatcher);
carbsInput.addTextChangedListener(textWatcher);
bgInput.addTextChangedListener(textWatcher);
wizardDialogDeliverButton = (Button) view.findViewById(R.id.treatments_wizard_deliverButton);
wizardDialogDeliverButton.setOnClickListener(this);
bg = (TextView) view.findViewById(R.id.treatments_wizard_bg);
bgInsulin = (TextView) view.findViewById(R.id.treatments_wizard_bginsulin);
bgUnits = (TextView) view.findViewById(R.id.treatments_wizard_bgunits);
bgCheckbox = (CheckBox) view.findViewById(R.id.treatments_wizard_bgcheckbox);
carbs = (TextView) view.findViewById(R.id.treatments_wizard_carbs);
carbsInsulin = (TextView) view.findViewById(R.id.treatments_wizard_carbsinsulin);
bolusIobInsulin = (TextView) view.findViewById(R.id.treatments_wizard_bolusiobinsulin);
basalIobInsulin = (TextView) view.findViewById(R.id.treatments_wizard_basaliobinsulin);
bolusIobCheckbox = (CheckBox) view.findViewById(R.id.treatments_wizard_bolusiobcheckbox);
basalIobCheckbox = (CheckBox) view.findViewById(R.id.treatments_wizard_basaliobcheckbox);
correctionInsulin = (TextView) view.findViewById(R.id.treatments_wizard_correctioninsulin);
total = (TextView) view.findViewById(R.id.treatments_wizard_total);
totalInsulin = (TextView) view.findViewById(R.id.treatments_wizard_totalinsulin);
carbTimeEdit = (EditText) view.findViewById(R.id.treatments_wizard_carbtimeinput);
profileSpinner = (Spinner) view.findViewById(R.id.treatments_wizard_profile);
superbolus = (TextView) view.findViewById(R.id.treatments_wizard_sb);
superbolusInsulin = (TextView) view.findViewById(R.id.treatments_wizard_sbinsulin);
bgCheckbox.setOnCheckedChangeListener(onCheckedChangeListener);
basalIobCheckbox.setOnCheckedChangeListener(onCheckedChangeListener);
bolusIobCheckbox.setOnCheckedChangeListener(onCheckedChangeListener);
profileSpinner.setOnItemSelectedListener(onItemSelectedListener);
bgTrend = (TextView) view.findViewById(R.id.treatments_wizard_bgtrend);
bgTrendInsulin = (TextView) view.findViewById(R.id.treatments_wizard_bgtrendinsulin);
cobLayout = (LinearLayout) view.findViewById(R.id.treatments_wizard_cob_layout);
cob = (TextView) view.findViewById(R.id.treatments_wizard_cob);;
cobInsulin = (TextView) view.findViewById(R.id.treatments_wizard_cobinsulin);;
bgCheckbox = (CheckBox) view.findViewById(R.id.treatments_wizard_bgcheckbox);
bolusIobCheckbox = (CheckBox) view.findViewById(R.id.treatments_wizard_bolusiobcheckbox);
basalIobCheckbox = (CheckBox) view.findViewById(R.id.treatments_wizard_basaliobcheckbox);
superbolusCheckbox = (CheckBox) view.findViewById(R.id.treatments_wizard_sbcheckbox);
bgtrendCheckbox = (CheckBox) view.findViewById(R.id.treatments_wizard_bgtrendcheckbox);
cobCheckbox = (CheckBox) view.findViewById(R.id.treatments_wizard_cobcheckbox);
bgCheckbox.setOnCheckedChangeListener(this);
basalIobCheckbox.setOnCheckedChangeListener(this);
bolusIobCheckbox.setOnCheckedChangeListener(this);
superbolusCheckbox.setOnCheckedChangeListener(this);
bgtrendCheckbox.setOnCheckedChangeListener(this);
cobCheckbox.setOnCheckedChangeListener(this);
profileSpinner = (Spinner) view.findViewById(R.id.treatments_wizard_profile);
profileSpinner.setOnItemSelectedListener(this);
correctionInput = (TextView) view.findViewById(R.id.treatments_wizard_correctioninput);
carbsInput = (TextView) view.findViewById(R.id.treatments_wizard_carbsinput);
bgInput = (TextView) view.findViewById(R.id.treatments_wizard_bginput);
correctionInput.addTextChangedListener(textWatcher);
carbsInput.addTextChangedListener(textWatcher);
bgInput.addTextChangedListener(textWatcher);
superbolusCheckbox.setVisibility(SP.getBoolean(R.string.key_usesuperbolus, false) ? View.VISIBLE : View.GONE);
Integer maxCarbs = MainApp.getConfigBuilder().applyCarbsConstraints(Constants.carbsOnlyForCheckLimit);
Double maxCorrection = MainApp.getConfigBuilder().applyBolusConstraints(Constants.bolusOnlyForCheckLimit);
@ -183,6 +255,23 @@ public class WizardDialog extends DialogFragment implements OnClickListener {
return view;
}
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
calculateInsulin();
}
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
calculateInsulin();
wizardDialogDeliverButton.setVisibility(View.VISIBLE);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
ToastUtils.showToastInUiThread(context, MainApp.sResources.getString(R.string.noprofileselected));
wizardDialogDeliverButton.setVisibility(View.GONE);
}
@Override
public void onClick(View view) {
switch (view.getId()) {
@ -197,8 +286,8 @@ public class WizardDialog extends DialogFragment implements OnClickListener {
confirmMessage += "\n" + getString(R.string.bolus) + ": " + formatNumber2decimalplaces.format(insulinAfterConstraints) + "U";
confirmMessage += "\n" + getString(R.string.carbs) + ": " + carbsAfterConstraints + "g";
if (insulinAfterConstraints - calculatedTotalInsulin != 0 || !carbsAfterConstraints.equals(calculatedCarbs)) {
AlertDialog.Builder builder = new AlertDialog.Builder(parentContext);
if (insulinAfterConstraints - calculatedTotalInsulin != 0 || !carbsAfterConstraints.equals(calculatedCarbs)) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(MainApp.sResources.getString(R.string.treatmentdeliveryerror));
builder.setMessage(getString(R.string.constraints_violation) + "\n" + getString(R.string.changeyourinput));
builder.setPositiveButton(MainApp.sResources.getString(R.string.ok), null);
@ -208,49 +297,64 @@ public class WizardDialog extends DialogFragment implements OnClickListener {
final Double finalInsulinAfterConstraints = insulinAfterConstraints;
final Integer finalCarbsAfterConstraints = carbsAfterConstraints;
final Double bg = SafeParse.stringToDouble(bgInput.getText().toString());
final int carbTime = SafeParse.stringToInt(carbTimeEdit.getText().toString());
final boolean useSuperBolus = superbolusCheckbox.isChecked();
if (parentContext != null) {
AlertDialog.Builder builder = new AlertDialog.Builder(parentContext);
builder.setTitle(MainApp.sResources.getString(R.string.confirmation));
builder.setMessage(confirmMessage);
builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
if (finalInsulinAfterConstraints > 0 || finalCarbsAfterConstraints > 0) {
final ConfigBuilderPlugin pump = MainApp.getConfigBuilder();
mHandler.post(new Runnable() {
@Override
public void run() {
PumpEnactResult result = pump.deliverTreatmentFromBolusWizard(
parentContext,
finalInsulinAfterConstraints,
finalCarbsAfterConstraints,
SafeParse.stringToDouble(bgInput.getText().toString()),
"Manual",
SafeParse.stringToInt(carbTimeEdit.getText().toString()),
boluscalcJSON
);
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(MainApp.sResources.getString(R.string.confirmation));
builder.setMessage(confirmMessage);
builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
if (finalInsulinAfterConstraints > 0 || finalCarbsAfterConstraints > 0) {
final ConfigBuilderPlugin pump = MainApp.getConfigBuilder();
mHandler.post(new Runnable() {
@Override
public void run() {
PumpEnactResult result = pump.deliverTreatmentFromBolusWizard(
MainApp.getConfigBuilder().getActiveInsulin(),
context,
finalInsulinAfterConstraints,
finalCarbsAfterConstraints,
bg,
"Manual",
carbTime,
boluscalcJSON
);
if (!result.success) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(MainApp.sResources.getString(R.string.treatmentdeliveryerror));
builder.setMessage(result.comment);
builder.setPositiveButton(MainApp.sResources.getString(R.string.ok), null);
builder.show();
}
if (useSuperBolus) {
final LoopPlugin activeloop = MainApp.getConfigBuilder().getActiveLoop();
result = pump.setTempBasalAbsolute(0d, 120);
if (!result.success) {
AlertDialog.Builder builder = new AlertDialog.Builder(parentContext);
builder.setTitle(MainApp.sResources.getString(R.string.treatmentdeliveryerror));
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(MainApp.sResources.getString(R.string.tempbasaldeliveryerror));
builder.setMessage(result.comment);
builder.setPositiveButton(MainApp.sResources.getString(R.string.ok), null);
builder.show();
}
if (activeloop != null) {
activeloop.superBolusTo(new Date().getTime() + 2 * 60L * 60 * 1000);
MainApp.bus().post(new EventRefreshGui(false));
}
}
});
}
}
});
Answers.getInstance().logCustom(new CustomEvent("Wizard"));
}
});
builder.setNegativeButton(getString(R.string.cancel), null);
builder.show();
dismiss();
} else {
log.error("parentContext == null");
}
}
});
builder.setNegativeButton(getString(R.string.cancel), null);
builder.show();
dismiss();
}
break;
}
}
private void initDialog() {
@ -264,8 +368,8 @@ public class WizardDialog extends DialogFragment implements OnClickListener {
ArrayList<CharSequence> profileList;
profileList = profile.getProfileList();
ArrayAdapter<CharSequence> adapter = new ArrayAdapter<CharSequence>(getContext(),
android.R.layout.simple_spinner_item, profileList);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
R.layout.spinner_centered, profileList);
profileSpinner.setAdapter(adapter);
// set selected to actual profile
for (int p = 0; p < profileList.size(); p++) {
@ -309,12 +413,15 @@ public class WizardDialog extends DialogFragment implements OnClickListener {
}
// IOB calculation
TreatmentsInterface treatments = MainApp.getConfigBuilder().getActiveTreatments();
TempBasalsInterface tempBasals = MainApp.getConfigBuilder().getActiveTempBasals();
TreatmentsInterface treatments = ConfigBuilderPlugin.getActiveTreatments();
treatments.updateTotalIOB();
tempBasals.updateTotalIOB();
IobTotal bolusIob = treatments.getLastCalculation();
IobTotal basalIob = tempBasals.getLastCalculation();
TempBasalsInterface tempBasals = ConfigBuilderPlugin.getActiveTempBasals();
IobTotal basalIob = new IobTotal(new Date().getTime());
if (tempBasals != null) {
tempBasals.updateTotalIOB();
basalIob = tempBasals.getLastCalculation().round();
}
bolusIobInsulin.setText(DecimalFormatter.to2Decimal(-bolusIob.iob) + "U");
basalIobInsulin.setText(DecimalFormatter.to2Decimal(-basalIob.basaliob) + "U");
@ -322,13 +429,14 @@ public class WizardDialog extends DialogFragment implements OnClickListener {
totalInsulin.setText("");
wizardDialogDeliverButton.setVisibility(Button.INVISIBLE);
}
@Override
public void onResume() {
super.onResume();
if (getDialog() != null)
getDialog().getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
// COB only if AMA is selected
if (ConfigBuilderPlugin.getActiveAPS() instanceof OpenAPSAMAPlugin && ConfigBuilderPlugin.getActiveAPS().getLastAPSResult() != null && ConfigBuilderPlugin.getActiveAPS().getLastAPSRun().after(new Date(new Date().getTime() - 11 * 60 * 1000L))) {
cobLayout.setVisibility(View.VISIBLE);
cobAvailable = true;
} else {
cobLayout.setVisibility(View.GONE);
cobAvailable = false;
}
}
private void calculateInsulin() {
@ -363,8 +471,19 @@ public class WizardDialog extends DialogFragment implements OnClickListener {
c_bg = bgCheckbox.isChecked() ? c_bg : 0d;
// COB
Double c_cob = 0d;
if (cobAvailable && cobCheckbox.isChecked()) {
if (ConfigBuilderPlugin.getActiveAPS().getLastAPSResult() != null && ConfigBuilderPlugin.getActiveAPS().getLastAPSRun().after(new Date(new Date().getTime() - 11 * 60 * 1000L))) {
try {
c_cob = SafeParse.stringToDouble(ConfigBuilderPlugin.getActiveAPS().getLastAPSResult().json().getString("COB"));
} catch (JSONException e) {
}
}
}
BolusWizard wizard = new BolusWizard();
wizard.doCalc(specificProfile, carbsAfterConstraint, c_bg, corrAfterConstraint, bolusIobCheckbox.isChecked(), basalIobCheckbox.isChecked());
wizard.doCalc(specificProfile, carbsAfterConstraint, c_cob, c_bg, corrAfterConstraint, bolusIobCheckbox.isChecked(), basalIobCheckbox.isChecked(), superbolusCheckbox.isChecked(), bgtrendCheckbox.isChecked());
bg.setText(c_bg + " ISF: " + DecimalFormatter.to1Decimal(wizard.sens));
bgInsulin.setText(DecimalFormatter.to2Decimal(wizard.insulinFromBG) + "U");
@ -388,6 +507,35 @@ public class WizardDialog extends DialogFragment implements OnClickListener {
calculatedCarbs = carbsAfterConstraint;
// Superbolus
if (superbolusCheckbox.isChecked()) {
superbolus.setText("2h");
} else {
superbolus.setText("");
}
superbolusInsulin.setText(DecimalFormatter.to2Decimal(wizard.insulinFromSuperBolus) + "U");
// Trend
if (bgtrendCheckbox.isChecked()) {
if (wizard.glucoseStatus != null) {
bgTrend.setText((wizard.glucoseStatus.avgdelta > 0 ? "+" : "") + NSProfile.toUnitsString(wizard.glucoseStatus.avgdelta * 3, wizard.glucoseStatus.avgdelta * 3 / 18, profile.getUnits()) + " " + profile.getUnits());
} else {
bgTrend.setText("");
}
} else {
bgTrend.setText("");
}
bgTrendInsulin.setText(DecimalFormatter.to2Decimal(wizard.insulinFromTrend) + "U");
// COB
if (cobAvailable && cobCheckbox.isChecked()) {
cob.setText(DecimalFormatter.to2Decimal(c_cob) + "g IC: " + DecimalFormatter.to1Decimal(wizard.ic));
cobInsulin.setText(DecimalFormatter.to2Decimal(wizard.insulinFromCOB) + "U");
} else {
cob.setText("");
cobInsulin.setText("");
}
if (calculatedTotalInsulin > 0d || calculatedCarbs > 0d) {
String insulinText = calculatedTotalInsulin > 0d ? (DecimalFormatter.to2Decimal(calculatedTotalInsulin) + "U") : "";
String carbsText = calculatedCarbs > 0d ? (DecimalFormatter.to0Decimal(calculatedCarbs) + "g") : "";
@ -414,10 +562,15 @@ public class WizardDialog extends DialogFragment implements OnClickListener {
boluscalcJSON.put("bgdiff", wizard.bgDiff);
boluscalcJSON.put("insulincarbs", wizard.insulinFromCarbs);
boluscalcJSON.put("carbs", c_carbs);
boluscalcJSON.put("cob", c_cob);
boluscalcJSON.put("insulincob", wizard.insulinFromCOB);
boluscalcJSON.put("othercorrection", corrAfterConstraint);
boluscalcJSON.put("insulinsuperbolus", wizard.insulinFromSuperBolus);
boluscalcJSON.put("insulintrend", wizard.insulinFromTrend);
boluscalcJSON.put("insulin", calculatedTotalInsulin);
} catch (JSONException e) {
e.printStackTrace();
}
}
}

View file

@ -23,6 +23,7 @@ public class Notification {
public static final int OLD_NSCLIENT = 8;
public static final int INVALID_PHONE_NUMBER = 9;
public static final int APPROACHING_DAILY_LIMIT = 10;
public static final int NSCLIENT_NO_WRITE_PERMISSION = 10;
public int id;
public Date date;

Some files were not shown because too many files have changed in this diff Show more