commit
7bcdf36ca0
263 changed files with 26193 additions and 280 deletions
|
@ -3,20 +3,16 @@
|
||||||
<component name="GradleSettings">
|
<component name="GradleSettings">
|
||||||
<option name="linkedExternalProjectsSettings">
|
<option name="linkedExternalProjectsSettings">
|
||||||
<GradleProjectSettings>
|
<GradleProjectSettings>
|
||||||
<option name="distributionType" value="DEFAULT_WRAPPED" />
|
<option name="distributionType" value="LOCAL" />
|
||||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||||
|
<option name="gradleHome" value="C:\Program Files\Android\Android Studio\gradle\gradle-2.14.1" />
|
||||||
<option name="modules">
|
<option name="modules">
|
||||||
<set>
|
<set>
|
||||||
<option value="$PROJECT_DIR$" />
|
<option value="$PROJECT_DIR$" />
|
||||||
<option value="$PROJECT_DIR$/app" />
|
<option value="$PROJECT_DIR$/app" />
|
||||||
</set>
|
</set>
|
||||||
</option>
|
</option>
|
||||||
<option name="myModules">
|
<option name="resolveModulePerSourceSet" value="false" />
|
||||||
<set>
|
|
||||||
<option value="$PROJECT_DIR$" />
|
|
||||||
<option value="$PROJECT_DIR$/app" />
|
|
||||||
</set>
|
|
||||||
</option>
|
|
||||||
</GradleProjectSettings>
|
</GradleProjectSettings>
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<component name="InspectionProjectProfileManager">
|
<component name="InspectionProjectProfileManager">
|
||||||
<profile version="1.0">
|
<profile version="1.0">
|
||||||
<option name="myName" value="Project Default" />
|
<option name="myName" value="Project Default" />
|
||||||
|
<inspection_tool class="AndroidLintLabelFor" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
<inspection_tool class="AndroidLintRtlHardcoded" enabled="false" level="WARNING" enabled_by_default="false" />
|
<inspection_tool class="AndroidLintRtlHardcoded" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
<inspection_tool class="AndroidLintUselessParent" enabled="false" level="WARNING" enabled_by_default="false" />
|
<inspection_tool class="AndroidLintUselessParent" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
<inspection_tool class="AndroidLintValidFragment" enabled="false" level="ERROR" enabled_by_default="false" />
|
<inspection_tool class="AndroidLintValidFragment" enabled="false" level="ERROR" enabled_by_default="false" />
|
||||||
|
|
|
@ -37,26 +37,10 @@
|
||||||
<ConfirmationsSetting value="0" id="Add" />
|
<ConfirmationsSetting value="0" id="Add" />
|
||||||
<ConfirmationsSetting value="0" id="Remove" />
|
<ConfirmationsSetting value="0" id="Remove" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectType">
|
<component name="ProjectType">
|
||||||
<option name="id" value="Android" />
|
<option name="id" value="Android" />
|
||||||
</component>
|
</component>
|
||||||
<component name="masterDetails">
|
|
||||||
<states>
|
|
||||||
<state key="ProjectJDKs.UI">
|
|
||||||
<settings>
|
|
||||||
<last-edited>1.8</last-edited>
|
|
||||||
<splitter-proportions>
|
|
||||||
<option name="proportions">
|
|
||||||
<list>
|
|
||||||
<option value="0.2" />
|
|
||||||
</list>
|
|
||||||
</option>
|
|
||||||
</splitter-proportions>
|
|
||||||
</settings>
|
|
||||||
</state>
|
|
||||||
</states>
|
|
||||||
</component>
|
|
||||||
</project>
|
</project>
|
6
README.md
Normal file
6
README.md
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
# AndroidAPS
|
||||||
|
|
||||||
|
* Check the wiki: https://github.com/MilosKozak/AndroidAPS/wiki
|
||||||
|
* Everyone who’s been looping with AndroidAPS needs to fill out the form after 3 days of looping https://docs.google.com/forms/d/14KcMjlINPMJHVt28MDRupa4sz4DDIooI4SrW0P3HSN8/viewform?c=0&w=1
|
||||||
|
|
||||||
|
[![Gitter](https://badges.gitter.im/MilosKozak/AndroidAPS.svg)](https://gitter.im/MilosKozak/AndroidAPS?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
|
@ -1,4 +1,19 @@
|
||||||
|
buildscript {
|
||||||
|
repositories {
|
||||||
|
maven { url 'https://maven.fabric.io/public' }
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
classpath 'io.fabric.tools:gradle:1.+'
|
||||||
|
}
|
||||||
|
}
|
||||||
apply plugin: 'com.android.application'
|
apply plugin: 'com.android.application'
|
||||||
|
apply plugin: 'io.fabric'
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
maven { url 'https://maven.fabric.io/public' }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 23
|
compileSdkVersion 23
|
||||||
|
@ -8,8 +23,11 @@ android {
|
||||||
applicationId "info.nightscout.androidaps"
|
applicationId "info.nightscout.androidaps"
|
||||||
minSdkVersion 21
|
minSdkVersion 21
|
||||||
targetSdkVersion 23
|
targetSdkVersion 23
|
||||||
versionCode 1
|
versionCode 1019
|
||||||
versionName "1.0"
|
versionName "1.0.19"
|
||||||
|
}
|
||||||
|
lintOptions {
|
||||||
|
disable 'MissingTranslation'
|
||||||
}
|
}
|
||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
release {
|
||||||
|
@ -17,12 +35,64 @@ android {
|
||||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
productFlavors {
|
||||||
|
full {
|
||||||
|
buildConfigField "boolean", "APS", "true"
|
||||||
|
buildConfigField "boolean", "PUMPDRIVERS", "true"
|
||||||
|
buildConfigField "boolean", "CLOSEDLOOP", "true"
|
||||||
|
buildConfigField "int", "MAXBOLUS", "17"
|
||||||
|
}
|
||||||
|
fullteenage {
|
||||||
|
buildConfigField "boolean", "APS", "true"
|
||||||
|
buildConfigField "boolean", "PUMPDRIVERS", "true"
|
||||||
|
buildConfigField "boolean", "CLOSEDLOOP", "true"
|
||||||
|
buildConfigField "int", "MAXBOLUS", "10"
|
||||||
|
}
|
||||||
|
fullchild {
|
||||||
|
buildConfigField "boolean", "APS", "true"
|
||||||
|
buildConfigField "boolean", "PUMPDRIVERS", "true"
|
||||||
|
buildConfigField "boolean", "CLOSEDLOOP", "true"
|
||||||
|
buildConfigField "int", "MAXBOLUS", "5"
|
||||||
|
}
|
||||||
|
danarcontrol {
|
||||||
|
buildConfigField "boolean", "APS", "false"
|
||||||
|
buildConfigField "boolean", "PUMPDRIVERS", "true"
|
||||||
|
buildConfigField "boolean", "CLOSEDLOOP", "false"
|
||||||
|
buildConfigField "int", "MAXBOLUS", "17"
|
||||||
|
}
|
||||||
|
careportal {
|
||||||
|
buildConfigField "boolean", "APS", "false"
|
||||||
|
buildConfigField "boolean", "PUMPDRIVERS", "false"
|
||||||
|
buildConfigField "boolean", "CLOSEDLOOP", "false"
|
||||||
|
buildConfigField "int", "MAXBOLUS", "17"
|
||||||
|
}
|
||||||
|
openloop {
|
||||||
|
buildConfigField "boolean", "APS", "true"
|
||||||
|
buildConfigField "boolean", "PUMPDRIVERS", "true"
|
||||||
|
buildConfigField "boolean", "CLOSEDLOOP", "false"
|
||||||
|
buildConfigField "int", "MAXBOLUS", "17"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
testCompile 'junit:junit:4.12'
|
compile('com.crashlytics.sdk.android:crashlytics:2.5.7@aar') {
|
||||||
|
transitive = true;
|
||||||
|
}
|
||||||
compile 'com.android.support:appcompat-v7:23.4.0'
|
compile 'com.android.support:appcompat-v7:23.4.0'
|
||||||
compile 'com.android.support:support-v4:23.4.0'
|
compile 'com.android.support:support-v4:23.4.0'
|
||||||
compile 'com.android.support:cardview-v7:23.0.+'
|
compile 'com.android.support:cardview-v7:23.4.0'
|
||||||
compile 'com.android.support:recyclerview-v7:23.0.+'}
|
compile 'com.android.support:recyclerview-v7:23.4.0'
|
||||||
|
compile 'com.android.support:gridlayout-v7:23.4.0'
|
||||||
|
compile 'com.wdullaer:materialdatetimepicker:2.3.0'
|
||||||
|
compile 'com.squareup:otto:1.3.7'
|
||||||
|
compile 'com.j256.ormlite:ormlite-core:4.46'
|
||||||
|
compile 'com.j256.ormlite:ormlite-android:4.46'
|
||||||
|
compile 'com.github.tony19:logback-android-classic:1.1.1-4'
|
||||||
|
compile 'org.slf4j:slf4j-api:1.7.12'
|
||||||
|
compile 'com.jjoe64:graphview:4.0.1'
|
||||||
|
compile 'com.eclipsesource.j2v8:j2v8:3.1.6@aar'
|
||||||
|
compile 'com.joanzapata.iconify:android-iconify-fontawesome:2.1.1'
|
||||||
|
testCompile 'junit:junit:4.12'
|
||||||
|
}
|
||||||
|
|
3
app/fabric.properties
Normal file
3
app/fabric.properties
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#Contains API Secret used to validate your application. Commit to internal source control; avoid making secret public.
|
||||||
|
#Sun Jul 03 14:29:18 CEST 2016
|
||||||
|
apiSecret=93ce8127162f8349a34eb7cd0756fe123ca8e971c50151906ea06ef38133cc34
|
9
app/proguard-rules.pro
vendored
9
app/proguard-rules.pro
vendored
|
@ -15,3 +15,12 @@
|
||||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||||
# public *;
|
# public *;
|
||||||
#}
|
#}
|
||||||
|
-dontwarn android.support.**
|
||||||
|
|
||||||
|
-keep class !android.support.v7.internal.view.menu.**,android.support.** {*;}
|
||||||
|
-ignorewarnings
|
||||||
|
-renamesourcefileattribute SourceFile
|
||||||
|
-keepattributes SourceFile,LineNumberTable
|
||||||
|
|
||||||
|
-keep public class * extends android.support.v4.** {*;}
|
||||||
|
-keep public class * extends android.app.Fragment
|
|
@ -2,7 +2,23 @@
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="info.nightscout.androidaps">
|
package="info.nightscout.androidaps">
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||||
|
<uses-permission android:name="android.permission.BLUETOOTH" />
|
||||||
|
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
|
||||||
|
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
|
||||||
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||||
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
|
<uses-permission android:name="android.permission.RECEIVE_SMS" />
|
||||||
|
<uses-permission android:name="android.permission.RECEIVE_MMS" />
|
||||||
|
<uses-permission android:name="android.permission.SEND_SMS" />
|
||||||
|
<uses-permission android:name="android.permission.SEND_MMS" />
|
||||||
|
|
||||||
|
<!-- To receive data from xdrip. -->
|
||||||
|
<uses-permission android:name="com.eveningoutpost.dexdrip.permissions.RECEIVE_BG_ESTIMATE" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
|
android:name=".MainApp"
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
|
@ -13,8 +29,60 @@
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|
||||||
</activity>
|
</activity>
|
||||||
|
<activity android:name=".PreferencesActivity" />
|
||||||
|
<activity android:name=".AgreementActivity" />
|
||||||
|
<activity android:name=".plugins.DanaR.History.DanaRHistoryActivity" />
|
||||||
|
<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>
|
||||||
|
|
||||||
|
<receiver
|
||||||
|
android:name=".receivers.DataReceiver"
|
||||||
|
android:enabled="true"
|
||||||
|
android:exported="true">
|
||||||
|
<intent-filter>
|
||||||
|
|
||||||
|
<!-- Receiver from NSClient -->
|
||||||
|
<action android:name="info.nightscout.client.NEW_SGV" />
|
||||||
|
<action android:name="info.nightscout.client.NEW_TREATMENT" />
|
||||||
|
<action android:name="info.nightscout.client.CHANGED_TREATMENT" />
|
||||||
|
<action android:name="info.nightscout.client.REMOVED_TREATMENT" />
|
||||||
|
<action android:name="info.nightscout.client.NEW_PROFILE" />
|
||||||
|
<action android:name="info.nightscout.client.NEW_STATUS" />
|
||||||
|
<action android:name="info.nightscout.client.NEW_MBG" />
|
||||||
|
<action android:name="info.nightscout.client.NEW_DEVICESTATUS" />
|
||||||
|
<action android:name="info.nightscout.client.NEW_CAL" />
|
||||||
|
<!-- Receive new SMS messages -->
|
||||||
|
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
|
||||||
|
<!-- Receiver from xDrip -->
|
||||||
|
<action android:name="com.eveningoutpost.dexdrip.BgEstimate" />
|
||||||
|
<!-- Auto start -->
|
||||||
|
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||||
|
</intent-filter>
|
||||||
|
</receiver>
|
||||||
|
|
||||||
|
<!-- Receiver keepalive, scheduled every 30 min -->
|
||||||
|
<receiver android:name=".receivers.KeepAliveReceiver" />
|
||||||
|
|
||||||
|
<!-- 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:enabled="true"
|
||||||
|
android:exported="false" />
|
||||||
|
|
||||||
|
<meta-data
|
||||||
|
android:name="io.fabric.ApiKey"
|
||||||
|
android:value="59d462666c664c57b29e1d79ea123e01f8057cfa" />
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
316
app/src/main/assets/OpenAPSMA/determine-basal.js
Normal file
316
app/src/main/assets/OpenAPSMA/determine-basal.js
Normal file
|
@ -0,0 +1,316 @@
|
||||||
|
/*
|
||||||
|
Determine Basal
|
||||||
|
|
||||||
|
Released under MIT license. See the accompanying LICENSE.txt file for
|
||||||
|
full terms and conditions
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
var determine_basal = function determine_basal(glucose_status, currenttemp, iob_data, profile, offline, meal_data, setTempBasal) {
|
||||||
|
var rT = { //short for requestedTemp
|
||||||
|
};
|
||||||
|
|
||||||
|
if (typeof profile === 'undefined' || typeof profile.current_basal === 'undefined') {
|
||||||
|
rT.error ='Error: could not get current basal rate';
|
||||||
|
return rT;
|
||||||
|
}
|
||||||
|
|
||||||
|
var bg = glucose_status.glucose;
|
||||||
|
if (bg < 30) { //Dexcom is in ??? mode or calibrating, do nothing. Asked @benwest for raw data in iter_glucose
|
||||||
|
rT.error = "CGM is calibrating or in ??? state";
|
||||||
|
return rT;
|
||||||
|
}
|
||||||
|
|
||||||
|
var max_iob = profile.max_iob; // maximum amount of non-bolus IOB OpenAPS will ever deliver
|
||||||
|
|
||||||
|
// if target_bg is set, great. otherwise, if min and max are set, then set target to their average
|
||||||
|
var target_bg;
|
||||||
|
if (typeof profile.target_bg !== 'undefined') {
|
||||||
|
target_bg = profile.target_bg;
|
||||||
|
} else {
|
||||||
|
if (typeof profile.min_bg !== 'undefined' && typeof profile.max_bg !== 'undefined') {
|
||||||
|
target_bg = (profile.min_bg + profile.max_bg) / 2;
|
||||||
|
} else {
|
||||||
|
rT.error ='Error: could not determine target_bg';
|
||||||
|
return rT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (typeof iob_data === 'undefined' ) {
|
||||||
|
rT.error ='Error: iob_data undefined';
|
||||||
|
return rT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof iob_data.activity === 'undefined' || typeof iob_data.iob === 'undefined' || typeof iob_data.activity === 'undefined') {
|
||||||
|
rT.error ='Error: iob_data missing some property';
|
||||||
|
return rT;
|
||||||
|
}
|
||||||
|
|
||||||
|
var tick;
|
||||||
|
|
||||||
|
if (glucose_status.delta >= 0) {
|
||||||
|
tick = "+" + glucose_status.delta;
|
||||||
|
} else {
|
||||||
|
tick = glucose_status.delta;
|
||||||
|
}
|
||||||
|
var minDelta = Math.min(glucose_status.delta, glucose_status.avgdelta);
|
||||||
|
//var maxDelta = Math.max(glucose_status.delta, glucose_status.avgdelta);
|
||||||
|
|
||||||
|
|
||||||
|
//calculate BG impact: the amount BG "should" be rising or falling based on insulin activity alone
|
||||||
|
var bgi = Math.round(( -iob_data.activity * profile.sens * 5 )*100)/100;
|
||||||
|
// project positive deviations for 15 minutes
|
||||||
|
var deviation = Math.round( 15 / 5 * ( glucose_status.avgdelta - bgi ) );
|
||||||
|
// project negative deviations for 30 minutes
|
||||||
|
if (deviation < 0) {
|
||||||
|
deviation = Math.round( 30 / 5 * ( glucose_status.avgdelta - bgi ) );
|
||||||
|
}
|
||||||
|
//console.log("Avg.Delta: " + glucose_status.avgdelta.toFixed(1) + ", BGI: " + bgi.toFixed(1) + " 15m activity projection: " + deviation.toFixed(0));
|
||||||
|
|
||||||
|
// calculate the naive (bolus calculator math) eventual BG based on net IOB and sensitivity
|
||||||
|
var naive_eventualBG = Math.round( bg - (iob_data.iob * profile.sens) );
|
||||||
|
// and adjust it for the deviation above
|
||||||
|
var eventualBG = naive_eventualBG + deviation;
|
||||||
|
// calculate what portion of that is due to bolussnooze
|
||||||
|
var bolusContrib = iob_data.bolussnooze * profile.sens;
|
||||||
|
// and add it back in to get snoozeBG, plus another 50% to avoid low-temping at mealtime
|
||||||
|
var naive_snoozeBG = Math.round( naive_eventualBG + 1.5 * bolusContrib );
|
||||||
|
// adjust that for deviation like we did eventualBG
|
||||||
|
var snoozeBG = naive_snoozeBG + deviation;
|
||||||
|
|
||||||
|
//console.log("BG: " + bg +"(" + tick + ","+glucose_status.avgdelta.toFixed(1)+")"+ " -> " + eventualBG + "-" + snoozeBG + " (Unadjusted: " + naive_eventualBG + "-" + naive_snoozeBG + "), BGI: " + bgi);
|
||||||
|
|
||||||
|
var expectedDelta = Math.round(( bgi + ( target_bg - eventualBG ) / ( profile.dia * 60 / 5 ) )*10)/10;
|
||||||
|
//console.log("expectedDelta: " + expectedDelta);
|
||||||
|
|
||||||
|
if (typeof eventualBG === 'undefined' || isNaN(eventualBG)) {
|
||||||
|
rT.error ='Error: could not calculate eventualBG';
|
||||||
|
return rT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// min_bg of 90 -> threshold of 70, 110 -> 80, and 130 -> 90
|
||||||
|
var threshold = profile.min_bg - 0.5*(profile.min_bg-50);
|
||||||
|
|
||||||
|
rT = {
|
||||||
|
'temp': 'absolute'
|
||||||
|
, 'bg': bg
|
||||||
|
, 'tick': tick
|
||||||
|
, 'eventualBG': eventualBG
|
||||||
|
, 'snoozeBG': snoozeBG
|
||||||
|
};
|
||||||
|
|
||||||
|
var basaliob;
|
||||||
|
if (iob_data.basaliob) { basaliob = iob_data.basaliob; }
|
||||||
|
else { basaliob = iob_data.iob - iob_data.bolussnooze; }
|
||||||
|
// allow meal assist to run when carbs are just barely covered
|
||||||
|
if (minDelta > Math.max(3, bgi) && ( (meal_data.carbs > 0 && (1.1 * meal_data.carbs/profile.carb_ratio > meal_data.boluses + basaliob)) || ( deviation > 25 && minDelta > 7 ) ) ) {
|
||||||
|
// ignore all covered IOB, and just set eventualBG to the current bg
|
||||||
|
eventualBG = Math.max(bg,eventualBG) + deviation;
|
||||||
|
rT.eventualBG = eventualBG;
|
||||||
|
profile.min_bg = 80;
|
||||||
|
target_bg = (profile.min_bg + profile.max_bg) / 2;
|
||||||
|
expectedDelta = Math.round(( bgi + ( target_bg - eventualBG ) / ( profile.dia * 60 / 5 ) )*10)/10;
|
||||||
|
rT.mealAssist = "On: Carbs: " + meal_data.carbs + " Boluses: " + meal_data.boluses + " Target: " + target_bg + " Deviation: " + deviation + " BGI: " + bgi;
|
||||||
|
} else {
|
||||||
|
rT.mealAssist = "Off: Carbs: " + meal_data.carbs + " Boluses: " + meal_data.boluses + " Target: " + target_bg + " Deviation: " + deviation + " BGI: " + bgi;
|
||||||
|
}
|
||||||
|
if (bg < threshold) { // low glucose suspend mode: BG is < ~80
|
||||||
|
rT.reason = "BG " + bg + "<" + threshold;
|
||||||
|
if ((glucose_status.delta <= 0 && glucose_status.avgdelta <= 0) || (glucose_status.delta < expectedDelta && glucose_status.avgdelta < expectedDelta)) {
|
||||||
|
// BG is still falling / rising slower than predicted
|
||||||
|
return setTempBasal(0, 30, profile, rT, offline);
|
||||||
|
}
|
||||||
|
if (glucose_status.delta > glucose_status.avgdelta) {
|
||||||
|
rT.reason += ", delta " + glucose_status.delta + ">0";
|
||||||
|
} else {
|
||||||
|
rT.reason += ", avg delta " + glucose_status.avgdelta.toFixed(2) + ">0";
|
||||||
|
}
|
||||||
|
if (currenttemp.rate > profile.current_basal) { // if a high-temp is running
|
||||||
|
rT.reason += ", cancel high temp";
|
||||||
|
return setTempBasal(0, 0, profile, rT, offline); // cancel high temp
|
||||||
|
} else if (currenttemp.duration && eventualBG > profile.max_bg) { // if low-temped and predicted to go high from negative IOB
|
||||||
|
rT.reason += ", cancel low temp";
|
||||||
|
return setTempBasal(0, 0, profile, rT, offline); // cancel low temp
|
||||||
|
}
|
||||||
|
rT.reason += "; no high-temp to cancel";
|
||||||
|
return rT;
|
||||||
|
}
|
||||||
|
if (eventualBG < profile.min_bg) { // if eventual BG is below target:
|
||||||
|
if (rT.mealAssist.indexOf("On") == 0) {
|
||||||
|
rT.reason = "Meal assist: " + meal_data.carbs + "g, " + meal_data.boluses + "U";
|
||||||
|
} else {
|
||||||
|
rT.reason = "Eventual BG " + eventualBG + "<" + profile.min_bg;
|
||||||
|
// if 5m or 15m avg BG is rising faster than expected delta
|
||||||
|
if (minDelta > expectedDelta && minDelta > 0) {
|
||||||
|
if (glucose_status.delta > glucose_status.avgdelta) {
|
||||||
|
rT.reason += ", but Delta " + tick + " > Exp. Delta " + expectedDelta;
|
||||||
|
} else {
|
||||||
|
rT.reason += ", but Avg. Delta " + glucose_status.avgdelta.toFixed(2) + " > Exp. Delta " + expectedDelta;
|
||||||
|
}
|
||||||
|
if (currenttemp.duration > 0) { // if there is currently any temp basal running
|
||||||
|
rT.reason = rT.reason += "; cancel";
|
||||||
|
return setTempBasal(0, 0, profile, rT, offline); // cancel temp
|
||||||
|
} else {
|
||||||
|
rT.reason = rT.reason += "; no temp to cancel";
|
||||||
|
return rT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (eventualBG < profile.min_bg) {
|
||||||
|
// if this is just due to boluses, we can snooze until the bolus IOB decays (at double speed)
|
||||||
|
if (snoozeBG > profile.min_bg) { // if adding back in the bolus contribution BG would be above min
|
||||||
|
// if BG is falling and high-temped, or rising and low-temped, cancel
|
||||||
|
// compare against zero here, not BGI, because BGI will be highly negative from boluses and no carbs
|
||||||
|
if (glucose_status.delta < 0 && currenttemp.duration > 0 && currenttemp.rate > profile.current_basal) {
|
||||||
|
rT.reason += tick + ", and temp " + currenttemp.rate + " > basal " + profile.current_basal;
|
||||||
|
return setTempBasal(0, 0, profile, rT, offline); // cancel temp
|
||||||
|
} else if (glucose_status.delta > 0 && currenttemp.duration > 0 && currenttemp.rate < profile.current_basal) {
|
||||||
|
rT.reason += tick + ", and temp " + currenttemp.rate + " < basal " + profile.current_basal;
|
||||||
|
return setTempBasal(0, 0, profile, rT, offline); // cancel temp
|
||||||
|
}
|
||||||
|
|
||||||
|
rT.reason += ", bolus snooze: eventual BG range " + eventualBG + "-" + snoozeBG;
|
||||||
|
return rT;
|
||||||
|
} else {
|
||||||
|
// calculate 30m low-temp required to get projected BG up to target
|
||||||
|
// use snoozeBG to more gradually ramp in any counteraction of the user's boluses
|
||||||
|
// multiply by 2 to low-temp faster for increased hypo safety
|
||||||
|
var insulinReq = 2 * Math.min(0, (snoozeBG - target_bg) / profile.sens);
|
||||||
|
if (minDelta < 0 && minDelta > expectedDelta) {
|
||||||
|
// if we're barely falling, newinsulinReq should be barely negative
|
||||||
|
rT.reason += ", Snooze BG " + snoozeBG;
|
||||||
|
var newinsulinReq = Math.round(( insulinReq * (minDelta / expectedDelta) ) * 100)/100;
|
||||||
|
//console.log("Increasing insulinReq from " + insulinReq + " to " + newinsulinReq);
|
||||||
|
insulinReq = newinsulinReq;
|
||||||
|
}
|
||||||
|
// rate required to deliver insulinReq less insulin over 30m:
|
||||||
|
var rate = profile.current_basal + (2 * insulinReq);
|
||||||
|
rate = Math.round( rate * 1000 ) / 1000;
|
||||||
|
// if required temp < existing temp basal
|
||||||
|
var insulinScheduled = currenttemp.duration * (currenttemp.rate - profile.current_basal) / 60;
|
||||||
|
if (insulinScheduled < insulinReq - 0.2) { // if current temp would deliver >0.2U less than the required insulin, raise the rate
|
||||||
|
rT.reason = currenttemp.duration + "m@" + (currenttemp.rate - profile.current_basal).toFixed(3) + " = " + insulinScheduled.toFixed(3) + " < req " + insulinReq + "-0.2U";
|
||||||
|
return setTempBasal(rate, 30, profile, rT, offline);
|
||||||
|
}
|
||||||
|
if (typeof currenttemp.rate !== 'undefined' && (currenttemp.duration > 5 && rate > currenttemp.rate - 0.1)) {
|
||||||
|
rT.reason += ", temp " + currenttemp.rate + " ~< req " + rate + "U/hr";
|
||||||
|
return rT;
|
||||||
|
} else {
|
||||||
|
rT.reason += ", setting " + rate + "U/hr";
|
||||||
|
return setTempBasal(rate, 30, profile, rT, offline);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if eventual BG is above min but BG is falling faster than expected Delta
|
||||||
|
if (minDelta < expectedDelta) {
|
||||||
|
if (glucose_status.delta < glucose_status.avgdelta) {
|
||||||
|
rT.reason = "Eventual BG " + eventualBG + ">" + profile.min_bg + " but Delta " + tick + " < Exp. Delta " + expectedDelta;
|
||||||
|
} else {
|
||||||
|
rT.reason = "Eventual BG " + eventualBG + ">" + profile.min_bg + " but Avg. Delta " + glucose_status.avgdelta.toFixed(2) + " < Exp. Delta " + expectedDelta;
|
||||||
|
}
|
||||||
|
if (currenttemp.duration > 0) { // if there is currently any temp basal running
|
||||||
|
rT.reason = rT.reason += "; cancel";
|
||||||
|
return setTempBasal(0, 0, profile, rT, offline); // cancel temp
|
||||||
|
} else {
|
||||||
|
rT.reason = rT.reason += "; no temp to cancel";
|
||||||
|
return rT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (eventualBG < profile.max_bg) {
|
||||||
|
rT.reason = eventualBG + " is in range. No temp required";
|
||||||
|
if (currenttemp.duration > 0) { // if there is currently any temp basal running
|
||||||
|
rT.reason = rT.reason += "; cancel";
|
||||||
|
return setTempBasal(0, 0, profile, rT, offline); // cancel temp
|
||||||
|
}
|
||||||
|
if (offline == 'Offline') {
|
||||||
|
// if no temp is running or required, set the current basal as a temp, so you can see on the pump that the loop is working
|
||||||
|
if ((!currenttemp.duration || (currenttemp.rate == profile.current_basal)) && !rT.duration) {
|
||||||
|
rT.reason = rT.reason + "; setting current basal of " + profile.current_basal + " as temp";
|
||||||
|
return setTempBasal(profile.current_basal, 30, profile, rT, offline);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (snoozeBG < profile.max_bg) {
|
||||||
|
rT.reason = snoozeBG + " < " + profile.max_bg;
|
||||||
|
if (currenttemp.duration > 0) { // if there is currently any temp basal running
|
||||||
|
rT.reason = rT.reason += "; cancel";
|
||||||
|
return setTempBasal(0, 0, profile, rT, offline); // cancel temp
|
||||||
|
} else {
|
||||||
|
rT.reason = rT.reason += "; no temp to cancel";
|
||||||
|
return rT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// eventual BG is at/above target:
|
||||||
|
// if iob is over max, just cancel any temps
|
||||||
|
var basaliob;
|
||||||
|
if (iob_data.basaliob) { basaliob = iob_data.basaliob; }
|
||||||
|
else { basaliob = iob_data.iob - iob_data.bolussnooze; }
|
||||||
|
rT.reason = "Eventual BG " + eventualBG + ">=" + profile.max_bg + ", ";
|
||||||
|
if (basaliob > max_iob) {
|
||||||
|
rT.reason = "basaliob " + basaliob + " > max_iob " + max_iob;
|
||||||
|
return setTempBasal(0, 0, profile, rT, offline);
|
||||||
|
} else { // otherwise, calculate 30m high-temp required to get projected BG down to target
|
||||||
|
|
||||||
|
// insulinReq is the additional insulin required to get down to max bg:
|
||||||
|
// if in meal assist mode, check if snoozeBG is lower, as eventualBG is not dependent on IOB
|
||||||
|
var insulinReq = (Math.min(snoozeBG,eventualBG) - target_bg) / profile.sens;
|
||||||
|
if (minDelta < 0 && minDelta > expectedDelta) {
|
||||||
|
var newinsulinReq = Math.round(( insulinReq * (1 - (minDelta / expectedDelta)) ) * 100)/100;
|
||||||
|
//console.log("Reducing insulinReq from " + insulinReq + " to " + newinsulinReq);
|
||||||
|
insulinReq = newinsulinReq;
|
||||||
|
}
|
||||||
|
// if that would put us over max_iob, then reduce accordingly
|
||||||
|
if (insulinReq > max_iob-basaliob) {
|
||||||
|
rT.reason = "max_iob " + max_iob + ", ";
|
||||||
|
insulinReq = max_iob-basaliob;
|
||||||
|
}
|
||||||
|
|
||||||
|
// rate required to deliver insulinReq more insulin over 30m:
|
||||||
|
var rate = profile.current_basal + (2 * insulinReq);
|
||||||
|
rate = Math.round( rate * 1000 ) / 1000;
|
||||||
|
|
||||||
|
var maxSafeBasal = Math.min(profile.max_basal, 3 * profile.max_daily_basal, 4 * profile.current_basal);
|
||||||
|
if (rate > maxSafeBasal) {
|
||||||
|
rT.reason += "adj. req. rate:"+rate.toFixed(1) +" to maxSafeBasal:"+maxSafeBasal.toFixed(1)+", ";
|
||||||
|
rate = maxSafeBasal;
|
||||||
|
}
|
||||||
|
|
||||||
|
var insulinScheduled = currenttemp.duration * (currenttemp.rate - profile.current_basal) / 60;
|
||||||
|
if (insulinScheduled > insulinReq + 0.2) { // if current temp would deliver >0.2U more than the required insulin, lower the rate
|
||||||
|
rT.reason = currenttemp.duration + "m@" + (currenttemp.rate - profile.current_basal).toFixed(3) + " = " + insulinScheduled.toFixed(3) + " > req " + insulinReq + "+0.2U";
|
||||||
|
return setTempBasal(rate, 30, profile, rT, offline);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof currenttemp.duration == 'undefined' || currenttemp.duration == 0) { // no temp is set
|
||||||
|
rT.reason += "no temp, setting " + rate + "U/hr";
|
||||||
|
return setTempBasal(rate, 30, profile, rT, offline);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currenttemp.duration > 5 && rate < currenttemp.rate + 0.1) { // if required temp <~ existing temp basal
|
||||||
|
rT.reason += "temp " + currenttemp.rate + " >~ req " + rate + "U/hr";
|
||||||
|
return rT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// required temp > existing temp basal
|
||||||
|
rT.reason += "temp " + currenttemp.rate + "<" + rate + "U/hr";
|
||||||
|
return setTempBasal(rate, 30, profile, rT, offline);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = determine_basal;
|
36
app/src/main/assets/logback.xml
Normal file
36
app/src/main/assets/logback.xml
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
<configuration>
|
||||||
|
<!-- Create a file appender for a log in the application's data directory -->
|
||||||
|
<property name="EXT_FILES_DIR" value="${EXT_DIR:-/sdcard}/Android/data/${PACKAGE_NAME}/files"/>
|
||||||
|
<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||||
|
<file>${EXT_FILES_DIR}/AndroidAPS.log</file>
|
||||||
|
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||||
|
<!-- daily rollover. Make sure the path matches the one in the file element or else
|
||||||
|
the rollover logs are placed in the working directory. -->
|
||||||
|
<fileNamePattern>${EXT_FILES_DIR}/AndroidAPS._%d{yyyy-MM-dd}.%i.log</fileNamePattern>
|
||||||
|
|
||||||
|
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
|
||||||
|
<maxFileSize>5MB</maxFileSize>
|
||||||
|
</timeBasedFileNamingAndTriggeringPolicy>
|
||||||
|
<!-- keep 30 days' worth of history -->
|
||||||
|
<maxHistory>120</maxHistory>
|
||||||
|
</rollingPolicy>
|
||||||
|
<encoder>
|
||||||
|
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<appender name="logcat" class="ch.qos.logback.classic.android.LogcatAppender">
|
||||||
|
<tagEncoder>
|
||||||
|
<pattern>%logger{0}</pattern>
|
||||||
|
</tagEncoder>
|
||||||
|
<encoder>
|
||||||
|
<pattern>[%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<!-- Write INFO (and higher-level) messages to the log file -->
|
||||||
|
<root level="DEBUG">
|
||||||
|
<appender-ref ref="file" />
|
||||||
|
<appender-ref ref="logcat" />
|
||||||
|
</root>
|
||||||
|
</configuration>
|
|
@ -0,0 +1,44 @@
|
||||||
|
package info.nightscout.androidaps;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.CheckBox;
|
||||||
|
|
||||||
|
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);
|
||||||
|
setContentView(R.layout.activity_agreement);
|
||||||
|
agreeCheckBox = (CheckBox)findViewById(R.id.agreementCheckBox);
|
||||||
|
agreeCheckBox.setChecked(IUnderstand);
|
||||||
|
saveButton = (Button)findViewById(R.id.agreementSaveButton);
|
||||||
|
addListenerOnButton();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addListenerOnButton() {
|
||||||
|
saveButton.setOnClickListener(new View.OnClickListener() {
|
||||||
|
public void onClick(View v) {
|
||||||
|
|
||||||
|
prefs.edit().putBoolean("I_understand", agreeCheckBox.isChecked()).apply();
|
||||||
|
|
||||||
|
Intent intent = new Intent(getApplicationContext(), MainActivity.class);
|
||||||
|
startActivity(intent);
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
38
app/src/main/java/info/nightscout/androidaps/Config.java
Normal file
38
app/src/main/java/info/nightscout/androidaps/Config.java
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
package info.nightscout.androidaps;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 07.06.2016.
|
||||||
|
*/
|
||||||
|
public class Config {
|
||||||
|
// MAIN FUCTIONALITY
|
||||||
|
public static final boolean APS = BuildConfig.APS;
|
||||||
|
// PLUGINS
|
||||||
|
public static final boolean OPENAPSMAENABLED = APS;
|
||||||
|
public static final boolean LOOPENABLED = APS;
|
||||||
|
|
||||||
|
public static final boolean CAREPORTALENABLED = true;
|
||||||
|
public static final boolean SMSCOMMUNICATORENABLED = true;
|
||||||
|
|
||||||
|
public static final boolean DANAR = true && BuildConfig.PUMPDRIVERS;
|
||||||
|
public static final boolean MM640G = false && BuildConfig.PUMPDRIVERS;
|
||||||
|
|
||||||
|
public static final boolean detailedLog = true;
|
||||||
|
public static final boolean logFunctionCalls = true;
|
||||||
|
public static final boolean logIncommingBG = true;
|
||||||
|
public static final boolean logIncommingData = true;
|
||||||
|
public static final boolean logAPSResult = true;
|
||||||
|
public static final boolean logPumpComm = true;
|
||||||
|
public static final boolean logPrefsChange = true;
|
||||||
|
public static final boolean logConfigBuilder = true;
|
||||||
|
public static final boolean logConstraintsChanges = true;
|
||||||
|
public static final boolean logTempBasalsCut = true;
|
||||||
|
public static final boolean logNSUpload = true;
|
||||||
|
public static final boolean logPumpActions = true;
|
||||||
|
public static final boolean logSMSComm = true;
|
||||||
|
public static final boolean logCongigBuilderActions = true;
|
||||||
|
|
||||||
|
// DanaR specific
|
||||||
|
public static final boolean logDanaBTComm = true;
|
||||||
|
public static final boolean logDanaMessageDetail = true;
|
||||||
|
public static final boolean logDanaSerialEngine = true;
|
||||||
|
}
|
28
app/src/main/java/info/nightscout/androidaps/Constants.java
Normal file
28
app/src/main/java/info/nightscout/androidaps/Constants.java
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
package info.nightscout.androidaps;
|
||||||
|
|
||||||
|
import com.j256.ormlite.stmt.query.In;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 07.06.2016.
|
||||||
|
*/
|
||||||
|
public class Constants {
|
||||||
|
public static final String MGDL = "mg/dl"; // This is Nightscout representation
|
||||||
|
public static final String MMOL = "mmol";
|
||||||
|
|
||||||
|
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 basalAbsoluteOnlyForCheckLimit = 10101010d;
|
||||||
|
public static final Integer basalPercentOnlyForCheckLimit = 10101010;
|
||||||
|
public static final double bolusOnlyForCheckLimit = 10101010d;
|
||||||
|
public static final Integer carbsOnlyForCheckLimit = 10101010;
|
||||||
|
|
||||||
|
public static final Integer notificationID = 556677;
|
||||||
|
|
||||||
|
public static final int hoursToKeepInDatabase = 72;
|
||||||
|
public static final int daysToKeepHistoryInDatabase = 30;
|
||||||
|
|
||||||
|
public static final long keepAliveMsecs = 5 * 60 * 1000L;
|
||||||
|
|
||||||
|
public static final long remoteBolusMinDistance = 15 * 60 * 1000L;
|
||||||
|
}
|
|
@ -1,40 +1,100 @@
|
||||||
package info.nightscout.androidaps;
|
package info.nightscout.androidaps;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
|
import android.support.v4.app.Fragment;
|
||||||
import android.support.v4.view.ViewPager;
|
import android.support.v4.view.ViewPager;
|
||||||
import android.support.v7.app.AppCompatActivity;
|
import android.support.v7.app.AppCompatActivity;
|
||||||
import android.os.Bundle;
|
|
||||||
import android.support.v7.widget.Toolbar;
|
import android.support.v7.widget.Toolbar;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
|
|
||||||
import info.nightscout.androidaps.tabs.*;
|
import com.joanzapata.iconify.Iconify;
|
||||||
import info.nightscout.androidaps.plugins.Objectives.ObjectivesFragment;
|
import com.joanzapata.iconify.fonts.FontAwesomeModule;
|
||||||
import info.nightscout.androidaps.plugins.Test.TestFragment;
|
import com.squareup.otto.Subscribe;
|
||||||
|
|
||||||
public class MainActivity extends AppCompatActivity implements ObjectivesFragment.OnFragmentInteractionListener {
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
private Toolbar toolbar;
|
import info.nightscout.androidaps.events.EventAppExit;
|
||||||
private SlidingTabLayout mTabs;
|
import info.nightscout.androidaps.events.EventRefreshGui;
|
||||||
private ViewPager mPager;
|
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||||
private TabPageAdapter mAdapter;
|
import info.nightscout.androidaps.plugins.DanaR.Services.ExecutionService;
|
||||||
|
import info.nightscout.androidaps.receivers.KeepAliveReceiver;
|
||||||
|
import info.nightscout.androidaps.tabs.SlidingTabLayout;
|
||||||
|
import info.nightscout.androidaps.tabs.TabPageAdapter;
|
||||||
|
import info.nightscout.utils.ImportExportPrefs;
|
||||||
|
import info.nightscout.utils.LocaleHelper;
|
||||||
|
|
||||||
|
public class MainActivity extends AppCompatActivity {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(MainActivity.class);
|
||||||
|
|
||||||
|
private static KeepAliveReceiver keepAliveReceiver;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
Iconify.with(new FontAwesomeModule());
|
||||||
|
LocaleHelper.onCreate(this, "en");
|
||||||
setContentView(R.layout.activity_main);
|
setContentView(R.layout.activity_main);
|
||||||
|
checkEula();
|
||||||
|
if (Config.logFunctionCalls)
|
||||||
|
log.debug("onCreate");
|
||||||
|
|
||||||
// Register all tabs in app here
|
// show version in toolbar
|
||||||
mAdapter = new TabPageAdapter(getSupportFragmentManager());
|
try {
|
||||||
mAdapter.registerNewFragment("Test", TestFragment.newInstance());
|
setTitle(getString(R.string.app_name) + " " + getPackageManager().getPackageInfo(getPackageName(), 0).versionName);
|
||||||
mAdapter.registerNewFragment("Objectives", ObjectivesFragment.newInstance());
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
toolbar = (Toolbar) findViewById(R.id.toolbar);
|
|
||||||
setSupportActionBar(toolbar);
|
|
||||||
mPager = (ViewPager) findViewById(R.id.pager);
|
|
||||||
mPager.setAdapter(mAdapter);
|
|
||||||
mTabs = (SlidingTabLayout) findViewById(R.id.tabs);
|
|
||||||
mTabs.setViewPager(mPager);
|
|
||||||
}
|
}
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keepAliveReceiver == null) {
|
||||||
|
keepAliveReceiver = new KeepAliveReceiver();
|
||||||
|
startService(new Intent(this, ExecutionService.class));
|
||||||
|
keepAliveReceiver.setAlarm(this);
|
||||||
|
}
|
||||||
|
setUpTabs(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onStatusEvent(final EventRefreshGui ev) {
|
||||||
|
SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
|
||||||
|
String lang = SP.getString("language", "en");
|
||||||
|
LocaleHelper.setLocale(getApplicationContext(), lang);
|
||||||
|
recreate();
|
||||||
|
try { // activity may be destroyed
|
||||||
|
setUpTabs(true);
|
||||||
|
} catch (IllegalStateException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setUpTabs(boolean switchToLast) {
|
||||||
|
TabPageAdapter pageAdapter = new TabPageAdapter(getSupportFragmentManager(), this);
|
||||||
|
for (PluginBase p : MainApp.getPluginsList()) {
|
||||||
|
pageAdapter.registerNewFragment(p);
|
||||||
|
}
|
||||||
|
ViewPager mPager = (ViewPager) findViewById(R.id.pager);
|
||||||
|
mPager.setAdapter(pageAdapter);
|
||||||
|
SlidingTabLayout mTabs = (SlidingTabLayout) findViewById(R.id.tabs);
|
||||||
|
mTabs.setViewPager(mPager);
|
||||||
|
if (switchToLast)
|
||||||
|
mPager.setCurrentItem(pageAdapter.getCount() - 1, false);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCreateOptionsMenu(Menu menu) {
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
getMenuInflater().inflate(R.menu.menu_main, menu);
|
getMenuInflater().inflate(R.menu.menu_main, menu);
|
||||||
|
@ -44,13 +104,69 @@ public class MainActivity extends AppCompatActivity implements ObjectivesFragmen
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
int id = item.getItemId();
|
int id = item.getItemId();
|
||||||
|
switch (id) {
|
||||||
|
case R.id.nav_preferences:
|
||||||
|
Intent i = new Intent(getApplicationContext(), PreferencesActivity.class);
|
||||||
|
startActivity(i);
|
||||||
|
break;
|
||||||
|
case R.id.nav_resetdb:
|
||||||
|
MainApp.getDbHelper().resetDatabases();
|
||||||
|
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_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");
|
||||||
|
keepAliveReceiver.cancelAlarm(this);
|
||||||
|
|
||||||
|
MainApp.bus().post(new EventAppExit());
|
||||||
|
MainApp.closeDbHelper();
|
||||||
|
finish();
|
||||||
|
System.runFinalization();
|
||||||
|
System.exit(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
private void registerBus() {
|
||||||
public void onFragmentInteraction(String param) {
|
try {
|
||||||
|
MainApp.bus().unregister(this);
|
||||||
|
} catch (RuntimeException x) {
|
||||||
|
// Ignore
|
||||||
}
|
}
|
||||||
|
MainApp.bus().register(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkEula() {
|
||||||
|
boolean IUnderstand = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).getBoolean("I_understand", false);
|
||||||
|
if (!IUnderstand) {
|
||||||
|
Intent intent = new Intent(getApplicationContext(), AgreementActivity.class);
|
||||||
|
startActivity(intent);
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
163
app/src/main/java/info/nightscout/androidaps/MainApp.java
Normal file
163
app/src/main/java/info/nightscout/androidaps/MainApp.java
Normal file
|
@ -0,0 +1,163 @@
|
||||||
|
package info.nightscout.androidaps;
|
||||||
|
|
||||||
|
import android.app.Application;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.crashlytics.android.Crashlytics;
|
||||||
|
import com.j256.ormlite.android.apptools.OpenHelperManager;
|
||||||
|
import com.squareup.otto.Bus;
|
||||||
|
import com.squareup.otto.ThreadEnforcer;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.db.DatabaseHelper;
|
||||||
|
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||||
|
import info.nightscout.androidaps.plugins.Careportal.CareportalFragment;
|
||||||
|
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.Loop.LoopFragment;
|
||||||
|
import info.nightscout.androidaps.plugins.MM640g.MM640gFragment;
|
||||||
|
import info.nightscout.androidaps.plugins.NSProfileViewer.NSProfileViewerFragment;
|
||||||
|
import info.nightscout.androidaps.plugins.Objectives.ObjectivesFragment;
|
||||||
|
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.SmsCommunicator.SmsCommunicatorFragment;
|
||||||
|
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.Treatments.TreatmentsFragment;
|
||||||
|
import info.nightscout.androidaps.plugins.VirtualPump.VirtualPumpFragment;
|
||||||
|
import io.fabric.sdk.android.Fabric;
|
||||||
|
|
||||||
|
|
||||||
|
public class MainApp extends Application {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(MainApp.class);
|
||||||
|
|
||||||
|
private static Bus sBus;
|
||||||
|
private static MainApp sInstance;
|
||||||
|
public static Resources sResources;
|
||||||
|
|
||||||
|
private static DatabaseHelper sDatabaseHelper = null;
|
||||||
|
private static ConfigBuilderPlugin sConfigBuilder = null;
|
||||||
|
|
||||||
|
private static ArrayList<PluginBase> pluginsList = null;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate() {
|
||||||
|
super.onCreate();
|
||||||
|
Fabric.with(this, new Crashlytics());
|
||||||
|
|
||||||
|
sBus = new Bus(ThreadEnforcer.ANY);
|
||||||
|
sInstance = this;
|
||||||
|
sResources = getResources();
|
||||||
|
|
||||||
|
if (pluginsList == null) {
|
||||||
|
pluginsList = new ArrayList<>();
|
||||||
|
// Register all tabs in app here
|
||||||
|
pluginsList.add(OverviewFragment.getPlugin());
|
||||||
|
if (Config.DANAR) pluginsList.add(DanaRFragment.getPlugin());
|
||||||
|
if (Config.MM640G) pluginsList.add(MM640gFragment.getPlugin());
|
||||||
|
if (Config.CAREPORTALENABLED) pluginsList.add(CareportalFragment.getPlugin());
|
||||||
|
pluginsList.add(VirtualPumpFragment.getPlugin());
|
||||||
|
if (Config.LOOPENABLED) pluginsList.add(LoopFragment.getPlugin());
|
||||||
|
if (Config.OPENAPSMAENABLED) pluginsList.add(OpenAPSMAFragment.getPlugin());
|
||||||
|
pluginsList.add(NSProfileViewerFragment.getPlugin());
|
||||||
|
pluginsList.add(SimpleProfileFragment.getPlugin());
|
||||||
|
pluginsList.add(TreatmentsFragment.getPlugin());
|
||||||
|
pluginsList.add(TempBasalsFragment.getPlugin());
|
||||||
|
pluginsList.add(SafetyFragment.getPlugin());
|
||||||
|
if (Config.APS) pluginsList.add(ObjectivesFragment.getPlugin());
|
||||||
|
pluginsList.add(SourceXdripFragment.getPlugin());
|
||||||
|
pluginsList.add(SourceNSClientFragment.getPlugin());
|
||||||
|
if (Config.SMSCOMMUNICATORENABLED)
|
||||||
|
pluginsList.add(SmsCommunicatorFragment.getPlugin());
|
||||||
|
pluginsList.add(sConfigBuilder = ConfigBuilderFragment.getPlugin());
|
||||||
|
|
||||||
|
MainApp.getConfigBuilder().initialize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bus bus() {
|
||||||
|
return sBus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MainApp instance() {
|
||||||
|
return sInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DatabaseHelper getDbHelper() {
|
||||||
|
if (sDatabaseHelper == null) {
|
||||||
|
sDatabaseHelper = OpenHelperManager.getHelper(sInstance, DatabaseHelper.class);
|
||||||
|
}
|
||||||
|
return sDatabaseHelper;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void closeDbHelper() {
|
||||||
|
if (sDatabaseHelper != null) {
|
||||||
|
sDatabaseHelper.close();
|
||||||
|
sDatabaseHelper = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ConfigBuilderPlugin getConfigBuilder() {
|
||||||
|
return sConfigBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ArrayList<PluginBase> getPluginsList() {
|
||||||
|
return pluginsList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ArrayList<PluginBase> getSpecificPluginsList(int type) {
|
||||||
|
ArrayList<PluginBase> newList = new ArrayList<>();
|
||||||
|
|
||||||
|
if (pluginsList != null) {
|
||||||
|
for (PluginBase p : pluginsList) {
|
||||||
|
if (p.getType() == type)
|
||||||
|
newList.add(p);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.error("pluginsList=null");
|
||||||
|
}
|
||||||
|
return newList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ArrayList<PluginBase> getSpecificPluginsListByInterface(Class interfaceClass) {
|
||||||
|
ArrayList<PluginBase> newList = new ArrayList<>();
|
||||||
|
|
||||||
|
if (pluginsList != null) {
|
||||||
|
for (PluginBase p : pluginsList) {
|
||||||
|
if (p.getClass() != ConfigBuilderPlugin.class && interfaceClass.isAssignableFrom(p.getClass()))
|
||||||
|
newList.add(p);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.error("pluginsList=null");
|
||||||
|
}
|
||||||
|
return newList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static PluginBase getSpecificPlugin(Class pluginClass) {
|
||||||
|
if (pluginsList != null) {
|
||||||
|
for (PluginBase p : pluginsList) {
|
||||||
|
if (p.getClass() == pluginClass)
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.error("pluginsList=null");
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTerminate() {
|
||||||
|
super.onTerminate();
|
||||||
|
sDatabaseHelper.close();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,108 @@
|
||||||
|
package info.nightscout.androidaps;
|
||||||
|
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.preference.EditTextPreference;
|
||||||
|
import android.preference.ListPreference;
|
||||||
|
import android.preference.MultiSelectListPreference;
|
||||||
|
import android.preference.Preference;
|
||||||
|
import android.preference.PreferenceActivity;
|
||||||
|
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.DanaRFragment;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin;
|
||||||
|
import info.nightscout.utils.LocaleHelper;
|
||||||
|
|
||||||
|
public class PreferencesActivity extends PreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||||
|
MyPreferenceFragment myPreferenceFragment;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
myPreferenceFragment = new MyPreferenceFragment();
|
||||||
|
getFragmentManager().beginTransaction().replace(android.R.id.content, myPreferenceFragment).commit();
|
||||||
|
PreferenceManager.getDefaultSharedPreferences(this).registerOnSharedPreferenceChangeListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
||||||
|
MainApp.bus().post(new EventPreferenceChange());
|
||||||
|
if (key.equals("language")) {
|
||||||
|
String lang = sharedPreferences.getString("language", "en");
|
||||||
|
LocaleHelper.setLocale(getApplicationContext(), lang);
|
||||||
|
recreate();
|
||||||
|
MainApp.bus().post(new EventRefreshGui());
|
||||||
|
}
|
||||||
|
updatePrefSummary(myPreferenceFragment.getPreference(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
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.getTitle().toString().toLowerCase().contains("password"))
|
||||||
|
{
|
||||||
|
pref.setSummary("******");
|
||||||
|
} else if (editTextPref.getText() != null && !editTextPref.getText().equals("")){
|
||||||
|
pref.setSummary(editTextPref.getText());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pref instanceof MultiSelectListPreference) {
|
||||||
|
EditTextPreference editTextPref = (EditTextPreference) pref;
|
||||||
|
pref.setSummary(editTextPref.getText());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void initSummary(Preference p) {
|
||||||
|
if (p instanceof PreferenceGroup) {
|
||||||
|
PreferenceGroup pGrp = (PreferenceGroup) p;
|
||||||
|
for (int i = 0; i < pGrp.getPreferenceCount(); i++) {
|
||||||
|
initSummary(pGrp.getPreference(i));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
updatePrefSummary(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class MyPreferenceFragment extends PreferenceFragment {
|
||||||
|
@Override
|
||||||
|
public void onCreate(final Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
addPreferencesFromResource(R.xml.pref_quickwizard);
|
||||||
|
addPreferencesFromResource(R.xml.pref_language);
|
||||||
|
if (Config.CAREPORTALENABLED)
|
||||||
|
addPreferencesFromResource(R.xml.pref_careportal);
|
||||||
|
addPreferencesFromResource(R.xml.pref_treatments);
|
||||||
|
if (Config.APS)
|
||||||
|
addPreferencesFromResource(R.xml.pref_closedmode);
|
||||||
|
if (Config.OPENAPSMAENABLED)
|
||||||
|
addPreferencesFromResource(R.xml.pref_openapsma);
|
||||||
|
addPreferencesFromResource(R.xml.pref_nightscout);
|
||||||
|
if (Config.DANAR) {
|
||||||
|
DanaRPlugin danaRPlugin = (DanaRPlugin) MainApp.getSpecificPlugin(DanaRPlugin.class);
|
||||||
|
if (danaRPlugin.isEnabled(PluginBase.PUMP)) {
|
||||||
|
addPreferencesFromResource(R.xml.pref_danar);
|
||||||
|
addPreferencesFromResource(R.xml.pref_danarprofile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Config.MM640G)
|
||||||
|
addPreferencesFromResource(R.xml.pref_mm640g);
|
||||||
|
if (Config.SMSCOMMUNICATORENABLED)
|
||||||
|
addPreferencesFromResource(R.xml.pref_smscommunicator);
|
||||||
|
initSummary(getPreferenceScreen());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Preference getPreference (String key) {
|
||||||
|
return findPreference(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,569 @@
|
||||||
|
package info.nightscout.androidaps.Services;
|
||||||
|
|
||||||
|
import android.app.IntentService;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
|
import android.provider.Telephony;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.j256.ormlite.dao.Dao;
|
||||||
|
import com.j256.ormlite.stmt.PreparedQuery;
|
||||||
|
import com.j256.ormlite.stmt.QueryBuilder;
|
||||||
|
import com.j256.ormlite.stmt.Where;
|
||||||
|
|
||||||
|
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.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.ScheduledFuture;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.Config;
|
||||||
|
import info.nightscout.androidaps.Constants;
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
import info.nightscout.androidaps.R;
|
||||||
|
import info.nightscout.androidaps.db.BgReading;
|
||||||
|
import info.nightscout.androidaps.db.DanaRHistoryRecord;
|
||||||
|
import info.nightscout.androidaps.db.Treatment;
|
||||||
|
import info.nightscout.androidaps.events.EventNewBG;
|
||||||
|
import info.nightscout.androidaps.events.EventNewBasalProfile;
|
||||||
|
import info.nightscout.androidaps.events.EventTreatmentChange;
|
||||||
|
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.Objectives.ObjectivesPlugin;
|
||||||
|
import info.nightscout.androidaps.plugins.Overview.OverviewPlugin;
|
||||||
|
import info.nightscout.androidaps.plugins.SmsCommunicator.SmsCommunicatorPlugin;
|
||||||
|
import info.nightscout.androidaps.plugins.SmsCommunicator.events.EventNewSMS;
|
||||||
|
import info.nightscout.androidaps.plugins.SourceNSClient.SourceNSClientPlugin;
|
||||||
|
import info.nightscout.androidaps.plugins.SourceXdrip.SourceXdripPlugin;
|
||||||
|
import info.nightscout.androidaps.receivers.DataReceiver;
|
||||||
|
import info.nightscout.client.data.NSProfile;
|
||||||
|
import info.nightscout.client.data.NSSgv;
|
||||||
|
import info.nightscout.utils.ToastUtils;
|
||||||
|
|
||||||
|
|
||||||
|
public class DataService extends IntentService {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(DataService.class);
|
||||||
|
|
||||||
|
boolean xDripEnabled = false;
|
||||||
|
boolean nsClientEnabled = true;
|
||||||
|
|
||||||
|
public DataService() {
|
||||||
|
super("DataService");
|
||||||
|
registerBus();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onHandleIntent(final Intent intent) {
|
||||||
|
if (Config.logFunctionCalls)
|
||||||
|
log.debug("onHandleIntent " + intent);
|
||||||
|
|
||||||
|
if (ConfigBuilderPlugin.getActiveBgSource().getClass().equals(SourceXdripPlugin.class)) {
|
||||||
|
xDripEnabled = true;
|
||||||
|
nsClientEnabled = false;
|
||||||
|
}
|
||||||
|
if (ConfigBuilderPlugin.getActiveBgSource().getClass().equals(SourceNSClientPlugin.class)) {
|
||||||
|
xDripEnabled = false;
|
||||||
|
nsClientEnabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (intent != null) {
|
||||||
|
final String action = intent.getAction();
|
||||||
|
if (Intents.ACTION_NEW_BG_ESTIMATE.equals(action)) {
|
||||||
|
if (xDripEnabled)
|
||||||
|
handleNewDataFromXDrip(intent);
|
||||||
|
} else if (Intents.ACTION_NEW_PROFILE.equals(action) ||
|
||||||
|
Intents.ACTION_NEW_TREATMENT.equals(action) ||
|
||||||
|
Intents.ACTION_CHANGED_TREATMENT.equals(action) ||
|
||||||
|
Intents.ACTION_REMOVED_TREATMENT.equals(action) ||
|
||||||
|
Intents.ACTION_NEW_SGV.equals(action) ||
|
||||||
|
Intents.ACTION_NEW_STATUS.equals(action) ||
|
||||||
|
Intents.ACTION_NEW_DEVICESTATUS.equals(action) ||
|
||||||
|
Intents.ACTION_NEW_CAL.equals(action) ||
|
||||||
|
Intents.ACTION_NEW_MBG.equals(action)
|
||||||
|
) {
|
||||||
|
handleNewDataFromNSClient(intent);
|
||||||
|
} else if (Telephony.Sms.Intents.SMS_RECEIVED_ACTION.equals(action)) {
|
||||||
|
handleNewSMS(intent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Config.logFunctionCalls)
|
||||||
|
log.debug("onHandleIntent exit " + intent);
|
||||||
|
DataReceiver.completeWakefulIntent(intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@Override
|
||||||
|
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||||
|
super.onStartCommand(intent, flags, startId);
|
||||||
|
|
||||||
|
if (Config.logFunctionCalls)
|
||||||
|
log.debug("onStartCommand");
|
||||||
|
|
||||||
|
return START_STICKY;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
MainApp.bus().unregister(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void registerBus() {
|
||||||
|
try {
|
||||||
|
MainApp.bus().unregister(this);
|
||||||
|
} catch (RuntimeException x) {
|
||||||
|
// Ignore
|
||||||
|
}
|
||||||
|
MainApp.bus().register(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleNewDataFromXDrip(Intent intent) {
|
||||||
|
Bundle bundle = intent.getExtras();
|
||||||
|
if (bundle == null) return;
|
||||||
|
|
||||||
|
BgReading bgReading = new BgReading();
|
||||||
|
|
||||||
|
bgReading.value = bundle.getDouble(Intents.EXTRA_BG_ESTIMATE);
|
||||||
|
bgReading.slope = bundle.getDouble(Intents.EXTRA_BG_SLOPE);
|
||||||
|
bgReading.battery_level = bundle.getInt(Intents.EXTRA_SENSOR_BATTERY);
|
||||||
|
bgReading.timeIndex = bundle.getLong(Intents.EXTRA_TIMESTAMP);
|
||||||
|
bgReading.raw = bundle.getDouble(Intents.EXTRA_RAW);
|
||||||
|
|
||||||
|
if (bgReading.timeIndex < new Date().getTime() - Constants.hoursToKeepInDatabase * 60 * 60 * 1000L) {
|
||||||
|
if (Config.logIncommingBG)
|
||||||
|
log.debug("Ignoring old XDRIPREC BG " + bgReading.toString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.logIncommingBG)
|
||||||
|
log.debug("XDRIPREC BG " + bgReading.toString());
|
||||||
|
|
||||||
|
try {
|
||||||
|
MainApp.getDbHelper().getDaoBgReadings().createIfNotExists(bgReading);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
MainApp.bus().post(new EventNewBG());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleNewDataFromNSClient(Intent intent) {
|
||||||
|
Bundle bundles = intent.getExtras();
|
||||||
|
if (bundles == null) return;
|
||||||
|
if (Config.logIncommingData)
|
||||||
|
log.debug("Got intent: " + intent.getAction());
|
||||||
|
|
||||||
|
|
||||||
|
if (intent.getAction().equals(Intents.ACTION_NEW_STATUS)) {
|
||||||
|
if (Config.logIncommingData)
|
||||||
|
log.debug("Received status: " + bundles);
|
||||||
|
if (bundles.containsKey("nsclientversioncode")) {
|
||||||
|
ConfigBuilderPlugin.nightscoutVersionCode = bundles.getInt("nightscoutversioncode"); // for ver 1.2.3 contains 10203
|
||||||
|
ConfigBuilderPlugin.nightscoutVersionName = bundles.getString("nightscoutversionname");
|
||||||
|
ConfigBuilderPlugin.nsClientVersionCode = bundles.getInt("nsclientversioncode"); // for ver 1.17 contains 117
|
||||||
|
ConfigBuilderPlugin.nsClientVersionName = bundles.getString("nsclientversionname");
|
||||||
|
log.debug("Got versions: NSClient: " + ConfigBuilderPlugin.nsClientVersionName + " Nightscout: " + ConfigBuilderPlugin.nightscoutVersionName);
|
||||||
|
if (ConfigBuilderPlugin.nsClientVersionCode < 118)
|
||||||
|
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.unsupportedclientver));
|
||||||
|
} else {
|
||||||
|
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.unsupportedclientver));
|
||||||
|
}
|
||||||
|
if (bundles.containsKey("status")) {
|
||||||
|
try {
|
||||||
|
JSONObject statusJson = new JSONObject(bundles.getString("status"));
|
||||||
|
if (statusJson.has("settings")) {
|
||||||
|
JSONObject settings = statusJson.getJSONObject("settings");
|
||||||
|
if (settings.has("thresholds")) {
|
||||||
|
JSONObject thresholds = settings.getJSONObject("thresholds");
|
||||||
|
if (thresholds.has("bgTargetTop")) {
|
||||||
|
OverviewPlugin.bgTargetHigh = thresholds.getDouble("bgTargetTop");
|
||||||
|
}
|
||||||
|
if (thresholds.has("bgTargetBottom")) {
|
||||||
|
OverviewPlugin.bgTargetLow = thresholds.getDouble("bgTargetBottom");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (intent.getAction().equals(Intents.ACTION_NEW_DEVICESTATUS)) {
|
||||||
|
try {
|
||||||
|
if (bundles.containsKey("devicestatus")) {
|
||||||
|
String devicestatusesstring = bundles.getString("devicestatus");
|
||||||
|
JSONObject devicestatusJson = new JSONObject(bundles.getString("devicestatus"));
|
||||||
|
if (devicestatusJson.has("pump")) {
|
||||||
|
// Objectives 0
|
||||||
|
ObjectivesPlugin.pumpStatusIsAvailableInNS = true;
|
||||||
|
ObjectivesPlugin.saveProgress();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (bundles.containsKey("devicestatuses")) {
|
||||||
|
String devicestatusesstring = bundles.getString("devicestatuses");
|
||||||
|
JSONArray jsonArray = new JSONArray(devicestatusesstring);
|
||||||
|
if (jsonArray.length() > 0) {
|
||||||
|
JSONObject devicestatusJson = jsonArray.getJSONObject(0);
|
||||||
|
if (devicestatusJson.has("pump")) {
|
||||||
|
// Objectives 0
|
||||||
|
ObjectivesPlugin.pumpStatusIsAvailableInNS = true;
|
||||||
|
ObjectivesPlugin.saveProgress();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Handle profile
|
||||||
|
if (intent.getAction().equals(Intents.ACTION_NEW_PROFILE)) {
|
||||||
|
try {
|
||||||
|
String activeProfile = bundles.getString("activeprofile");
|
||||||
|
String profile = bundles.getString("profile");
|
||||||
|
NSProfile nsProfile = new NSProfile(new JSONObject(profile), activeProfile);
|
||||||
|
if (MainApp.getConfigBuilder() == null) {
|
||||||
|
log.error("Config builder not ready on receive profile");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
PumpInterface pump = MainApp.getConfigBuilder();
|
||||||
|
if (pump != null) {
|
||||||
|
SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
|
||||||
|
if (SP.getBoolean("syncprofiletopump", false))
|
||||||
|
pump.setNewBasalProfile(nsProfile);
|
||||||
|
} else {
|
||||||
|
log.error("No active pump selected");
|
||||||
|
}
|
||||||
|
if (Config.logIncommingData)
|
||||||
|
log.debug("Received profile: " + activeProfile + " " + profile);
|
||||||
|
MainApp.bus().post(new EventNewBasalProfile(nsProfile));
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (intent.getAction().equals(Intents.ACTION_NEW_TREATMENT)) {
|
||||||
|
try {
|
||||||
|
if (bundles.containsKey("treatment")) {
|
||||||
|
String trstring = bundles.getString("treatment");
|
||||||
|
handleAddedTreatment(trstring);
|
||||||
|
}
|
||||||
|
if (bundles.containsKey("treatments")) {
|
||||||
|
String trstring = bundles.getString("treatments");
|
||||||
|
JSONArray jsonArray = new JSONArray(trstring);
|
||||||
|
for (int i = 0; i < jsonArray.length(); i++) {
|
||||||
|
JSONObject trJson = jsonArray.getJSONObject(i);
|
||||||
|
String trstr = trJson.toString();
|
||||||
|
handleAddedTreatment(trstr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scheduleTreatmentChange();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (intent.getAction().equals(Intents.ACTION_CHANGED_TREATMENT)) {
|
||||||
|
try {
|
||||||
|
if (bundles.containsKey("treatment")) {
|
||||||
|
String trstring = bundles.getString("treatment");
|
||||||
|
handleChangedTreatment(trstring);
|
||||||
|
}
|
||||||
|
if (bundles.containsKey("treatments")) {
|
||||||
|
String trstring = bundles.getString("treatments");
|
||||||
|
JSONArray jsonArray = new JSONArray(trstring);
|
||||||
|
for (int i = 0; i < jsonArray.length(); i++) {
|
||||||
|
JSONObject trJson = jsonArray.getJSONObject(i);
|
||||||
|
String trstr = trJson.toString();
|
||||||
|
handleChangedTreatment(trstr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scheduleTreatmentChange();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (intent.getAction().equals(Intents.ACTION_REMOVED_TREATMENT)) {
|
||||||
|
try {
|
||||||
|
if (bundles.containsKey("treatment")) {
|
||||||
|
String trstring = bundles.getString("treatment");
|
||||||
|
JSONObject trJson = new JSONObject(trstring);
|
||||||
|
String _id = trJson.getString("_id");
|
||||||
|
removeTreatmentFromDb(_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bundles.containsKey("treatments")) {
|
||||||
|
String trstring = bundles.getString("treatments");
|
||||||
|
JSONArray jsonArray = new JSONArray(trstring);
|
||||||
|
for (int i = 0; i < jsonArray.length(); i++) {
|
||||||
|
JSONObject trJson = jsonArray.getJSONObject(i);
|
||||||
|
String _id = trJson.getString("_id");
|
||||||
|
removeTreatmentFromDb(_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scheduleTreatmentChange();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (intent.getAction().equals(Intents.ACTION_NEW_SGV)) {
|
||||||
|
if (nsClientEnabled) {
|
||||||
|
try {
|
||||||
|
if (bundles.containsKey("sgv")) {
|
||||||
|
String sgvstring = bundles.getString("sgv");
|
||||||
|
JSONObject sgvJson = new JSONObject(sgvstring);
|
||||||
|
NSSgv nsSgv = new NSSgv(sgvJson);
|
||||||
|
BgReading bgReading = new BgReading(nsSgv);
|
||||||
|
if (bgReading.timeIndex < new Date().getTime() - Constants.hoursToKeepInDatabase * 60 * 60 * 1000l) {
|
||||||
|
if (Config.logIncommingData)
|
||||||
|
log.debug("Ignoring old BG: " + bgReading.toString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
MainApp.getDbHelper().getDaoBgReadings().createIfNotExists(bgReading);
|
||||||
|
if (Config.logIncommingData)
|
||||||
|
log.debug("ADD: Stored new BG: " + bgReading.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bundles.containsKey("sgvs")) {
|
||||||
|
String sgvstring = bundles.getString("sgvs");
|
||||||
|
JSONArray jsonArray = new JSONArray(sgvstring);
|
||||||
|
for (int i = 0; i < jsonArray.length(); i++) {
|
||||||
|
JSONObject sgvJson = jsonArray.getJSONObject(i);
|
||||||
|
NSSgv nsSgv = new NSSgv(sgvJson);
|
||||||
|
BgReading bgReading = new BgReading(nsSgv);
|
||||||
|
if (bgReading.timeIndex < new Date().getTime() - Constants.hoursToKeepInDatabase * 60 * 60 * 1000l) {
|
||||||
|
if (Config.logIncommingData)
|
||||||
|
log.debug("Ignoring old BG: " + bgReading.toString());
|
||||||
|
} else {
|
||||||
|
MainApp.getDbHelper().getDaoBgReadings().createIfNotExists(bgReading);
|
||||||
|
if (Config.logIncommingData)
|
||||||
|
log.debug("ADD: Stored new BG: " + bgReading.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
MainApp.bus().post(new EventNewBG());
|
||||||
|
}
|
||||||
|
// Objectives 0
|
||||||
|
ObjectivesPlugin.bgIsAvailableInNS = true;
|
||||||
|
ObjectivesPlugin.saveProgress();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (intent.getAction().equals(Intents.ACTION_NEW_MBG)) {
|
||||||
|
log.error("Not implemented yet"); // TODO implemeng MBGS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleAddedTreatment(String trstring) throws JSONException, SQLException {
|
||||||
|
JSONObject trJson = new JSONObject(trstring);
|
||||||
|
handleDanaRHistoryRecords(trJson); // update record _id in history
|
||||||
|
if (!trJson.has("insulin") && !trJson.has("carbs")) {
|
||||||
|
if (Config.logIncommingData)
|
||||||
|
log.debug("ADD: Uninterested treatment: " + trstring);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Treatment stored = null;
|
||||||
|
String _id = trJson.getString("_id");
|
||||||
|
|
||||||
|
if (trJson.has("timeIndex")) {
|
||||||
|
if (Config.logIncommingData)
|
||||||
|
log.debug("ADD: timeIndex found: " + trstring);
|
||||||
|
stored = findByTimeIndex(trJson.getLong("timeIndex"));
|
||||||
|
} else {
|
||||||
|
stored = findById(_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stored != null) {
|
||||||
|
if (Config.logIncommingData)
|
||||||
|
log.debug("ADD: Existing treatment: " + trstring);
|
||||||
|
if (trJson.has("timeIndex")) {
|
||||||
|
stored._id = _id;
|
||||||
|
int updated = MainApp.getDbHelper().getDaoTreatments().update(stored);
|
||||||
|
if (Config.logIncommingData)
|
||||||
|
log.debug("Records updated: " + updated);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (Config.logIncommingData)
|
||||||
|
log.debug("ADD: New treatment: " + trstring);
|
||||||
|
Treatment treatment = new Treatment();
|
||||||
|
treatment._id = _id;
|
||||||
|
treatment.carbs = trJson.has("carbs") ? trJson.getDouble("carbs") : 0;
|
||||||
|
treatment.insulin = trJson.has("insulin") ? trJson.getDouble("insulin") : 0d;
|
||||||
|
treatment.created_at = new Date(trJson.getLong("mills"));
|
||||||
|
if (trJson.has("eventType")) {
|
||||||
|
treatment.mealBolus = true;
|
||||||
|
if (trJson.get("eventType").equals("Correction Bolus")) treatment.mealBolus = false;
|
||||||
|
if (trJson.get("eventType").equals("Bolus Wizard") && treatment.carbs <= 0) treatment.mealBolus = false;
|
||||||
|
}
|
||||||
|
treatment.setTimeIndex(treatment.getTimeIndex());
|
||||||
|
try {
|
||||||
|
MainApp.getDbHelper().getDaoTreatments().createOrUpdate(treatment);
|
||||||
|
if (Config.logIncommingData)
|
||||||
|
log.debug("ADD: Stored treatment: " + treatment.log());
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleChangedTreatment(String trstring) throws JSONException, SQLException {
|
||||||
|
JSONObject trJson = new JSONObject(trstring);
|
||||||
|
handleDanaRHistoryRecords(trJson); // update record _id in history
|
||||||
|
if (!trJson.has("insulin") && !trJson.has("carbs")) {
|
||||||
|
if (Config.logIncommingData)
|
||||||
|
log.debug("CHANGE: Uninterested treatment: " + trstring);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String _id = trJson.getString("_id");
|
||||||
|
|
||||||
|
Treatment stored;
|
||||||
|
|
||||||
|
if (trJson.has("timeIndex")) {
|
||||||
|
if (Config.logIncommingData)
|
||||||
|
log.debug("ADD: timeIndex found: " + trstring);
|
||||||
|
stored = findByTimeIndex(trJson.getLong("timeIndex"));
|
||||||
|
} else {
|
||||||
|
stored = findById(_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stored != null) {
|
||||||
|
if (Config.logIncommingData)
|
||||||
|
log.debug("CHANGE: Removing old: " + trstring);
|
||||||
|
removeTreatmentFromDb(_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.logIncommingData)
|
||||||
|
log.debug("CHANGE: Adding new treatment: " + trstring);
|
||||||
|
Treatment treatment = new Treatment();
|
||||||
|
treatment._id = _id;
|
||||||
|
treatment.carbs = trJson.has("carbs") ? trJson.getDouble("carbs") : 0;
|
||||||
|
treatment.insulin = trJson.has("insulin") ? trJson.getDouble("insulin") : 0d;
|
||||||
|
//treatment.created_at = DateUtil.fromISODateString(trJson.getString("created_at"));
|
||||||
|
treatment.created_at = new Date(trJson.getLong("mills"));
|
||||||
|
if (trJson.has("eventType")) {
|
||||||
|
treatment.mealBolus = true;
|
||||||
|
if (trJson.get("eventType").equals("Correction Bolus")) treatment.mealBolus = false;
|
||||||
|
if (trJson.get("eventType").equals("Bolus Wizard") && treatment.carbs <= 0) treatment.mealBolus = false;
|
||||||
|
}
|
||||||
|
treatment.setTimeIndex(treatment.getTimeIndex());
|
||||||
|
try {
|
||||||
|
Dao.CreateOrUpdateStatus status = MainApp.getDbHelper().getDaoTreatments().createOrUpdate(treatment);
|
||||||
|
if (Config.logIncommingData)
|
||||||
|
log.debug("Records updated: " + status.getNumLinesChanged());
|
||||||
|
if (Config.logIncommingData)
|
||||||
|
log.debug("CHANGE: Stored treatment: " + treatment.log());
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleDanaRHistoryRecords(JSONObject trJson) throws JSONException, SQLException {
|
||||||
|
if (trJson.has(DanaRNSHistorySync.DANARSIGNATURE)) {
|
||||||
|
Dao<DanaRHistoryRecord, String> daoHistoryRecords = MainApp.getDbHelper().getDaoDanaRHistory();
|
||||||
|
QueryBuilder<DanaRHistoryRecord, String> queryBuilder = daoHistoryRecords.queryBuilder();
|
||||||
|
Where where = queryBuilder.where();
|
||||||
|
where.ge("bytes", trJson.get(DanaRNSHistorySync.DANARSIGNATURE));
|
||||||
|
PreparedQuery<DanaRHistoryRecord> preparedQuery = queryBuilder.prepare();
|
||||||
|
List<DanaRHistoryRecord> list = daoHistoryRecords.query(preparedQuery);
|
||||||
|
if (list.size() == 0) {
|
||||||
|
// Record does not exists. Ignore
|
||||||
|
} else if (list.size() == 1) {
|
||||||
|
DanaRHistoryRecord record = list.get(0);
|
||||||
|
if (record.get_id() == null || record.get_id() != trJson.getString("_id")) {
|
||||||
|
if (Config.logIncommingData)
|
||||||
|
log.debug("Updating _id in DanaR history database: " + trJson.getString("_id"));
|
||||||
|
record.set_id(trJson.getString("_id"));
|
||||||
|
daoHistoryRecords.update(record);
|
||||||
|
} else {
|
||||||
|
// already set
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static Treatment findById(String _id) {
|
||||||
|
try {
|
||||||
|
Dao<Treatment, Long> daoTreatments = MainApp.getDbHelper().getDaoTreatments();
|
||||||
|
QueryBuilder<Treatment, Long> queryBuilder = daoTreatments.queryBuilder();
|
||||||
|
Where where = queryBuilder.where();
|
||||||
|
where.eq("_id", _id);
|
||||||
|
queryBuilder.limit(10);
|
||||||
|
PreparedQuery<Treatment> preparedQuery = queryBuilder.prepare();
|
||||||
|
List<Treatment> trList = daoTreatments.query(preparedQuery);
|
||||||
|
if (trList.size() != 1) {
|
||||||
|
//log.debug("Treatment findById query size: " + trList.size());
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
//log.debug("Treatment findById found: " + trList.get(0).log());
|
||||||
|
return trList.get(0);
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static Treatment findByTimeIndex(Long timeIndex) {
|
||||||
|
try {
|
||||||
|
QueryBuilder<Treatment, String> qb = null;
|
||||||
|
Dao<Treatment, Long> daoTreatments = MainApp.getDbHelper().getDaoTreatments();
|
||||||
|
QueryBuilder<Treatment, Long> queryBuilder = daoTreatments.queryBuilder();
|
||||||
|
Where where = queryBuilder.where();
|
||||||
|
where.eq("timeIndex", timeIndex);
|
||||||
|
queryBuilder.limit(10);
|
||||||
|
PreparedQuery<Treatment> preparedQuery = queryBuilder.prepare();
|
||||||
|
List<Treatment> trList = daoTreatments.query(preparedQuery);
|
||||||
|
if (trList.size() != 1) {
|
||||||
|
log.debug("Treatment findByTimeIndex query size: " + trList.size());
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
log.debug("Treatment findByTimeIndex found: " + trList.get(0).log());
|
||||||
|
return trList.get(0);
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeTreatmentFromDb(String _id) throws SQLException {
|
||||||
|
Treatment stored = findById(_id);
|
||||||
|
if (stored != null) {
|
||||||
|
log.debug("REMOVE: Existing treatment (removing): " + _id);
|
||||||
|
int removed = MainApp.getDbHelper().getDaoTreatments().delete(stored);
|
||||||
|
if (Config.logIncommingData)
|
||||||
|
log.debug("Records removed: " + removed);
|
||||||
|
scheduleTreatmentChange();
|
||||||
|
} else {
|
||||||
|
log.debug("REMOVE: Not stored treatment (ignoring): " + _id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleNewSMS(Intent intent) {
|
||||||
|
Bundle bundle = intent.getExtras();
|
||||||
|
if (bundle == null) return;
|
||||||
|
MainApp.bus().post(new EventNewSMS(bundle));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void scheduleTreatmentChange() {
|
||||||
|
MainApp.bus().post(new EventTreatmentChange());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
package info.nightscout.androidaps.Services;
|
||||||
|
|
||||||
|
public interface Intents {
|
||||||
|
// NSClient -> App
|
||||||
|
String ACTION_NEW_TREATMENT = "info.nightscout.client.NEW_TREATMENT";
|
||||||
|
String ACTION_CHANGED_TREATMENT = "info.nightscout.client.CHANGED_TREATMENT";
|
||||||
|
String ACTION_REMOVED_TREATMENT = "info.nightscout.client.REMOVED_TREATMENT";
|
||||||
|
String ACTION_NEW_PROFILE = "info.nightscout.client.NEW_PROFILE";
|
||||||
|
String ACTION_NEW_SGV = "info.nightscout.client.NEW_SGV";
|
||||||
|
String ACTION_NEW_DEVICESTATUS = "info.nightscout.client.NEW_DEVICESTATUS";
|
||||||
|
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";
|
||||||
|
|
||||||
|
|
||||||
|
// App -> NSClient
|
||||||
|
String ACTION_DATABASE = "info.nightscout.client.DBACCESS";
|
||||||
|
String ACTION_RESTART = "info.nightscout.client.RESTART";
|
||||||
|
|
||||||
|
// xDrip -> App
|
||||||
|
String RECEIVER_PERMISSION = "com.eveningoutpost.dexdrip.permissions.RECEIVE_BG_ESTIMATE";
|
||||||
|
|
||||||
|
String ACTION_NEW_BG_ESTIMATE = "com.eveningoutpost.dexdrip.BgEstimate";
|
||||||
|
String EXTRA_BG_ESTIMATE = "com.eveningoutpost.dexdrip.Extras.BgEstimate";
|
||||||
|
String EXTRA_BG_SLOPE = "com.eveningoutpost.dexdrip.Extras.BgSlope";
|
||||||
|
String EXTRA_BG_SLOPE_NAME = "com.eveningoutpost.dexdrip.Extras.BgSlopeName";
|
||||||
|
String EXTRA_SENSOR_BATTERY = "com.eveningoutpost.dexdrip.Extras.SensorBattery";
|
||||||
|
String EXTRA_TIMESTAMP = "com.eveningoutpost.dexdrip.Extras.Time";
|
||||||
|
String EXTRA_RAW = "com.eveningoutpost.dexdrip.Extras.Raw";
|
||||||
|
|
||||||
|
String ACTION_NEW_BG_ESTIMATE_NO_DATA = "com.eveningoutpost.dexdrip.BgEstimateNoData";
|
||||||
|
}
|
15
app/src/main/java/info/nightscout/androidaps/data/Iob.java
Normal file
15
app/src/main/java/info/nightscout/androidaps/data/Iob.java
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
package info.nightscout.androidaps.data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 05.06.2016.
|
||||||
|
*/
|
||||||
|
public class Iob {
|
||||||
|
public double iobContrib = 0d;
|
||||||
|
public double activityContrib = 0d;
|
||||||
|
|
||||||
|
public Iob plus(Iob iob) {
|
||||||
|
iobContrib += iob.iobContrib;
|
||||||
|
activityContrib += iob.activityContrib;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,148 @@
|
||||||
|
package info.nightscout.androidaps.data;
|
||||||
|
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
import android.text.Html;
|
||||||
|
import android.text.Spanned;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
import info.nightscout.androidaps.R;
|
||||||
|
import info.nightscout.client.data.NSProfile;
|
||||||
|
import info.nightscout.utils.DecimalFormatter;
|
||||||
|
import info.nightscout.utils.Round;
|
||||||
|
|
||||||
|
public class PumpEnactResult extends Object implements Parcelable {
|
||||||
|
public boolean success = false; // request was processed successfully (but possible no change was needed)
|
||||||
|
public boolean enacted = false; // request was processed successfully and change has been made
|
||||||
|
public String comment = "";
|
||||||
|
|
||||||
|
// Result of basal change
|
||||||
|
public Integer duration = -1; // duration set [minutes]
|
||||||
|
public Double absolute = -1d; // absolute rate [U/h] , isPercent = false
|
||||||
|
public Integer percent = -1; // percent of current basal [%] (100% = current basal), isPercent = true
|
||||||
|
public boolean isPercent = false; // if true percent is used, otherwise absolute
|
||||||
|
public boolean isTempCancel = false; // if true we are caceling temp basal
|
||||||
|
// Result of treatment delivery
|
||||||
|
public Double bolusDelivered = 0d; // real value of delivered insulin
|
||||||
|
public Integer carbsDelivered = 0; // real value of delivered carbs
|
||||||
|
|
||||||
|
public boolean queued = false;
|
||||||
|
|
||||||
|
public String log() {
|
||||||
|
return "Success: " + success + " Enacted: " + enacted + " Comment: " + comment + " Duration: " + duration + " Absolute: " + absolute + " Percent: " + percent + " IsPercent: " + isPercent + " Queued: " + queued;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
String ret = MainApp.sResources.getString(R.string.success) + ": " + success;
|
||||||
|
if (enacted) {
|
||||||
|
if (isTempCancel) {
|
||||||
|
ret += "\n" + MainApp.sResources.getString(R.string.enacted) + ": " + enacted;
|
||||||
|
ret += "\n" + MainApp.sResources.getString(R.string.comment) + ": " + comment + "\n" +
|
||||||
|
MainApp.sResources.getString(R.string.canceltemp);
|
||||||
|
} else if (isPercent) {
|
||||||
|
ret += "\n" + MainApp.sResources.getString(R.string.enacted) + ": " + enacted;
|
||||||
|
ret += "\n" + MainApp.sResources.getString(R.string.comment) + ": " + comment;
|
||||||
|
ret += "\n" + MainApp.sResources.getString(R.string.duration) + ": " + duration + " min";
|
||||||
|
ret += "\n" + MainApp.sResources.getString(R.string.percent) + ": " + percent + "%";
|
||||||
|
} else {
|
||||||
|
ret += "\n" + MainApp.sResources.getString(R.string.enacted) + ": " + enacted;
|
||||||
|
ret += "\n" + MainApp.sResources.getString(R.string.comment) + ": " + comment;
|
||||||
|
ret += "\n" + MainApp.sResources.getString(R.string.duration) + ": " + duration + " min";
|
||||||
|
ret += "\n" + MainApp.sResources.getString(R.string.absolute) + ": " + absolute + " U/h";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ret += "\n" + MainApp.sResources.getString(R.string.comment) + ": " + comment;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Spanned toSpanned() {
|
||||||
|
String ret = MainApp.sResources.getString(R.string.success) + ": " + success;
|
||||||
|
if (queued) {
|
||||||
|
ret = MainApp.sResources.getString(R.string.waitingforpumpresult);
|
||||||
|
} else if (enacted) {
|
||||||
|
if (isTempCancel) {
|
||||||
|
ret += "<br><b>" + MainApp.sResources.getString(R.string.enacted) + "</b>: " + enacted;
|
||||||
|
ret += "<br><b>" + MainApp.sResources.getString(R.string.comment) + "</b>: " + comment +
|
||||||
|
"<br>" + MainApp.sResources.getString(R.string.canceltemp);
|
||||||
|
} else if (isPercent) {
|
||||||
|
ret += "<br><b>" + MainApp.sResources.getString(R.string.enacted) + "</b>: " + enacted;
|
||||||
|
ret += "<br><b>" + MainApp.sResources.getString(R.string.comment) + "</b>: " + comment;
|
||||||
|
ret += "<br><b>" + MainApp.sResources.getString(R.string.duration) + "</b>: " + duration + " min";
|
||||||
|
ret += "<br><b>" + MainApp.sResources.getString(R.string.percent) + "</b>: " + percent + "%";
|
||||||
|
} else {
|
||||||
|
ret += "<br><b>" + MainApp.sResources.getString(R.string.enacted) + "</b>: " + enacted;
|
||||||
|
ret += "<br><b>" + MainApp.sResources.getString(R.string.comment) + "</b>: " + comment;
|
||||||
|
ret += "<br><b>" + MainApp.sResources.getString(R.string.duration) + "</b>: " + duration + " min";
|
||||||
|
ret += "<br><b>" + MainApp.sResources.getString(R.string.absolute) + "</b>: " + DecimalFormatter.to2Decimal(absolute) + " U/h";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ret += "<br><b>" + MainApp.sResources.getString(R.string.comment) + "</b>: " + comment;
|
||||||
|
}
|
||||||
|
return Html.fromHtml(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int describeContents() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToParcel(Parcel dest, int flags) {
|
||||||
|
dest.writeInt(success ? 1 : 0);
|
||||||
|
dest.writeInt(enacted ? 1 : 0);
|
||||||
|
dest.writeInt(isPercent ? 1 : 0);
|
||||||
|
dest.writeString(comment);
|
||||||
|
dest.writeInt(duration);
|
||||||
|
dest.writeDouble(absolute);
|
||||||
|
dest.writeInt(percent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final Parcelable.Creator<PumpEnactResult> CREATOR = new Parcelable.Creator<PumpEnactResult>() {
|
||||||
|
public PumpEnactResult createFromParcel(Parcel in) {
|
||||||
|
return new PumpEnactResult(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PumpEnactResult[] newArray(int size) {
|
||||||
|
return new PumpEnactResult[size];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
protected PumpEnactResult(Parcel in) {
|
||||||
|
success = in.readInt() == 1 ? true : false;
|
||||||
|
enacted = in.readInt() == 1 ? true : false;
|
||||||
|
isPercent = in.readInt() == 1 ? true : false;
|
||||||
|
duration = in.readInt();
|
||||||
|
comment = in.readString();
|
||||||
|
absolute = in.readDouble();
|
||||||
|
percent = in.readInt();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public PumpEnactResult() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public JSONObject json() {
|
||||||
|
JSONObject result = new JSONObject();
|
||||||
|
try {
|
||||||
|
if (isTempCancel) {
|
||||||
|
result.put("rate", 0);
|
||||||
|
result.put("duration", 0);
|
||||||
|
} else if (isPercent) {
|
||||||
|
// Nightscout is expecting absolute value
|
||||||
|
Double abs = Round.roundTo(MainApp.getConfigBuilder().getActiveProfile().getProfile().getBasal(NSProfile.secondsFromMidnight()) * percent / 100, 0.01);
|
||||||
|
result.put("rate", abs);
|
||||||
|
result.put("duration", duration);
|
||||||
|
} else {
|
||||||
|
result.put("rate", absolute);
|
||||||
|
result.put("duration", duration);
|
||||||
|
}
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,87 @@
|
||||||
|
package info.nightscout.androidaps.db;
|
||||||
|
|
||||||
|
import com.j256.ormlite.field.DatabaseField;
|
||||||
|
import com.j256.ormlite.table.DatabaseTable;
|
||||||
|
import com.jjoe64.graphview.series.DataPointInterface;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.Constants;
|
||||||
|
import info.nightscout.client.data.NSSgv;
|
||||||
|
import info.nightscout.utils.DecimalFormatter;
|
||||||
|
|
||||||
|
@DatabaseTable(tableName = DatabaseHelper.DATABASE_BGREADINGS)
|
||||||
|
public class BgReading implements DataPointInterface {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(BgReading.class);
|
||||||
|
|
||||||
|
public long getTimeIndex() {
|
||||||
|
return timeIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTimeIndex(long timeIndex) {
|
||||||
|
this.timeIndex = timeIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
@DatabaseField(id = true, useGetSet = true)
|
||||||
|
public long timeIndex;
|
||||||
|
|
||||||
|
@DatabaseField
|
||||||
|
public double value;
|
||||||
|
|
||||||
|
@DatabaseField
|
||||||
|
public double slope;
|
||||||
|
|
||||||
|
@DatabaseField
|
||||||
|
public double raw;
|
||||||
|
|
||||||
|
@DatabaseField
|
||||||
|
public int battery_level;
|
||||||
|
|
||||||
|
public static String units = Constants.MGDL;
|
||||||
|
|
||||||
|
public BgReading() {}
|
||||||
|
|
||||||
|
public BgReading(NSSgv sgv) {
|
||||||
|
timeIndex = sgv.getMills();
|
||||||
|
value = sgv.getMgdl();
|
||||||
|
raw = sgv.getFiltered();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Double valueToUnits(String units) {
|
||||||
|
if (units.equals(Constants.MGDL))
|
||||||
|
return value;
|
||||||
|
else
|
||||||
|
return value * Constants.MGDL_TO_MMOLL;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String valueToUnitsToString(String units) {
|
||||||
|
if (units.equals(Constants.MGDL)) return DecimalFormatter.to0Decimal(value);
|
||||||
|
else return DecimalFormatter.to1Decimal(value * Constants.MGDL_TO_MMOLL);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "BgReading{" +
|
||||||
|
"timeIndex=" + timeIndex +
|
||||||
|
", date=" + new Date(timeIndex) +
|
||||||
|
", value=" + value +
|
||||||
|
", slope=" + slope +
|
||||||
|
", raw=" + raw +
|
||||||
|
", battery_level=" + battery_level +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getX() {
|
||||||
|
return timeIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getY() {
|
||||||
|
return valueToUnits(units);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,171 @@
|
||||||
|
package info.nightscout.androidaps.db;
|
||||||
|
|
||||||
|
import com.j256.ormlite.field.DatabaseField;
|
||||||
|
import com.j256.ormlite.table.DatabaseTable;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
@DatabaseTable(tableName = DatabaseHelper.DATABASE_DANARHISTORY)
|
||||||
|
public class DanaRHistoryRecord {
|
||||||
|
|
||||||
|
@DatabaseField(useGetSet = true)
|
||||||
|
private String _id;
|
||||||
|
|
||||||
|
@DatabaseField(useGetSet = true)
|
||||||
|
private byte recordCode;
|
||||||
|
|
||||||
|
@DatabaseField(id = true, useGetSet = true)
|
||||||
|
private String bytes;
|
||||||
|
|
||||||
|
@DatabaseField(useGetSet = true)
|
||||||
|
private long recordDate;
|
||||||
|
|
||||||
|
@DatabaseField(useGetSet = true)
|
||||||
|
private double recordValue;
|
||||||
|
|
||||||
|
@DatabaseField(useGetSet = true)
|
||||||
|
private String bolusType;
|
||||||
|
|
||||||
|
@DatabaseField(useGetSet = true)
|
||||||
|
private String stringRecordValue;
|
||||||
|
|
||||||
|
@DatabaseField(useGetSet = true)
|
||||||
|
private int recordDuration;
|
||||||
|
|
||||||
|
@DatabaseField(useGetSet = true)
|
||||||
|
private double recordDailyBasal;
|
||||||
|
|
||||||
|
@DatabaseField(useGetSet = true)
|
||||||
|
private double recordDailyBolus;
|
||||||
|
|
||||||
|
@DatabaseField(useGetSet = true)
|
||||||
|
private String recordAlarm;
|
||||||
|
|
||||||
|
public DanaRHistoryRecord() {
|
||||||
|
this.recordDate = 0;
|
||||||
|
this.recordValue = 0.0;
|
||||||
|
this.bolusType = "None";
|
||||||
|
this.recordCode = 0x0F;
|
||||||
|
this.bytes = new String();
|
||||||
|
this._id = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRecordDate(Date dtRecordDate) {
|
||||||
|
this.recordDate = dtRecordDate.getTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getRecordDate() {
|
||||||
|
return this.recordDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRecordDate(long dtRecordDate) {
|
||||||
|
this.recordDate = dtRecordDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getRecordValue() {
|
||||||
|
return this.recordValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRecordValue(double dRecordValue) {
|
||||||
|
this.recordValue = dRecordValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBolusType() {
|
||||||
|
return this.bolusType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBolusType(String strRecordType) {
|
||||||
|
this.bolusType = strRecordType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStringRecordValue() {
|
||||||
|
return this.stringRecordValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStringRecordValue(String strRecordValue) {
|
||||||
|
this.stringRecordValue = strRecordValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getRecordCode() {
|
||||||
|
return this.recordCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRecordCode(byte cRecordCode) {
|
||||||
|
this.recordCode = cRecordCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRecordDuration() {
|
||||||
|
return this.recordDuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRecordDuration(int dRecordDuraion) {
|
||||||
|
this.recordDuration = dRecordDuraion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getRecordDailyBasal() {
|
||||||
|
return this.recordDailyBasal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRecordDailyBasal(double dRecordDailyBasal) {
|
||||||
|
this.recordDailyBasal = dRecordDailyBasal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getRecordDailyBolus() {
|
||||||
|
return this.recordDailyBolus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRecordDailyBolus(double dRecordDailyBolus) {
|
||||||
|
this.recordDailyBolus = dRecordDailyBolus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRecordLevel(double dExLow, double dLow, double dHigh, double dExHigh) {
|
||||||
|
if (this.recordValue < dExLow)
|
||||||
|
return 0;
|
||||||
|
if (this.recordValue < dLow)
|
||||||
|
return 1;
|
||||||
|
if (this.recordValue < dHigh)
|
||||||
|
return 2;
|
||||||
|
return this.recordValue < dExHigh ? 3 : 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRecordAlarm() {
|
||||||
|
return this.recordAlarm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRecordAlarm(String strAlarm) {
|
||||||
|
this.recordAlarm = strAlarm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String get_id() {
|
||||||
|
return this._id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set_id(String _id) {
|
||||||
|
this._id = _id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBytes(byte[] raw) {
|
||||||
|
this.bytes = bytesToHex(raw);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBytes(String bytes) {
|
||||||
|
this.bytes = bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBytes() {
|
||||||
|
return this.bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();
|
||||||
|
|
||||||
|
public static String bytesToHex(byte[] bytes) {
|
||||||
|
char[] hexChars = new char[bytes.length * 2];
|
||||||
|
for (int j = 0; j < bytes.length; j++) {
|
||||||
|
int v = bytes[j] & 0xFF;
|
||||||
|
hexChars[j * 2] = hexArray[v >>> 4];
|
||||||
|
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
|
||||||
|
}
|
||||||
|
return new String(hexChars);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,329 @@
|
||||||
|
package info.nightscout.androidaps.db;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.database.DatabaseUtils;
|
||||||
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
import android.text.Html;
|
||||||
|
import android.text.Spanned;
|
||||||
|
|
||||||
|
import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper;
|
||||||
|
import com.j256.ormlite.dao.Dao;
|
||||||
|
import com.j256.ormlite.stmt.PreparedQuery;
|
||||||
|
import com.j256.ormlite.stmt.QueryBuilder;
|
||||||
|
import com.j256.ormlite.stmt.Where;
|
||||||
|
import com.j256.ormlite.support.ConnectionSource;
|
||||||
|
import com.j256.ormlite.table.TableUtils;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.Constants;
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
import info.nightscout.androidaps.R;
|
||||||
|
import info.nightscout.utils.DecimalFormatter;
|
||||||
|
import info.nightscout.utils.Round;
|
||||||
|
|
||||||
|
public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(DatabaseHelper.class);
|
||||||
|
|
||||||
|
public static final String DATABASE_NAME = "AndroidAPSDb";
|
||||||
|
public static final String DATABASE_BGREADINGS = "BgReadings";
|
||||||
|
public static final String DATABASE_TEMPBASALS = "TempBasals";
|
||||||
|
public static final String DATABASE_TREATMENTS = "Treatments";
|
||||||
|
public static final String DATABASE_DANARHISTORY = "DanaRHistory";
|
||||||
|
|
||||||
|
private static final int DATABASE_VERSION = 4;
|
||||||
|
|
||||||
|
public DatabaseHelper(Context context) {
|
||||||
|
super(context, DATABASE_NAME, null, DATABASE_VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(SQLiteDatabase database, ConnectionSource connectionSource) {
|
||||||
|
try {
|
||||||
|
log.info("onCreate");
|
||||||
|
TableUtils.createTableIfNotExists(connectionSource, TempBasal.class);
|
||||||
|
TableUtils.createTableIfNotExists(connectionSource, Treatment.class);
|
||||||
|
TableUtils.createTableIfNotExists(connectionSource, BgReading.class);
|
||||||
|
TableUtils.createTableIfNotExists(connectionSource, DanaRHistoryRecord.class);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
log.error(DatabaseHelper.class.getName(), "Can't create database", e);
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUpgrade(SQLiteDatabase database, ConnectionSource connectionSource, int oldVersion, int newVersion) {
|
||||||
|
try {
|
||||||
|
log.info(DatabaseHelper.class.getName(), "onUpgrade");
|
||||||
|
TableUtils.dropTable(connectionSource, TempBasal.class, true);
|
||||||
|
TableUtils.dropTable(connectionSource, Treatment.class, true);
|
||||||
|
TableUtils.dropTable(connectionSource, BgReading.class, true);
|
||||||
|
TableUtils.dropTable(connectionSource, DanaRHistoryRecord.class, true);
|
||||||
|
onCreate(database, connectionSource);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
log.error(DatabaseHelper.class.getName(), "Can't drop databases", e);
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close the database connections and clear any cached DAOs.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
super.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cleanUpDatabases() {
|
||||||
|
// TODO: call it somewhere
|
||||||
|
log.debug("Before BgReadings size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_BGREADINGS));
|
||||||
|
getWritableDatabase().delete("BgReadings", "timeIndex" + " < '" + (new Date().getTime() - Constants.hoursToKeepInDatabase * 60 * 60 * 1000L) + "'", null);
|
||||||
|
log.debug("After BgReadings size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_BGREADINGS));
|
||||||
|
|
||||||
|
log.debug("Before TempBasals size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_TEMPBASALS));
|
||||||
|
getWritableDatabase().delete("TempBasals", "timeIndex" + " < '" + (new Date().getTime() - Constants.hoursToKeepInDatabase * 60 * 60 * 1000L) + "'", null);
|
||||||
|
log.debug("After TempBasals size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_TEMPBASALS));
|
||||||
|
|
||||||
|
log.debug("Before Treatments size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_TREATMENTS));
|
||||||
|
getWritableDatabase().delete("Treatments", "timeIndex" + " < '" + (new Date().getTime() - Constants.hoursToKeepInDatabase * 60 * 60 * 1000L) + "'", null);
|
||||||
|
log.debug("After Treatments size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_TREATMENTS));
|
||||||
|
|
||||||
|
log.debug("Before History size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), "DanaRHistory"));
|
||||||
|
getWritableDatabase().delete("History", "recordDate" + " < '" + (new Date().getTime() - Constants.daysToKeepHistoryInDatabase * 24 * 60 * 60 * 1000L) + "'", null);
|
||||||
|
log.debug("After History size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), "DanaRHistory"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resetDatabases() {
|
||||||
|
try {
|
||||||
|
TableUtils.dropTable(connectionSource, TempBasal.class, true);
|
||||||
|
TableUtils.dropTable(connectionSource, Treatment.class, true);
|
||||||
|
TableUtils.dropTable(connectionSource, BgReading.class, true);
|
||||||
|
TableUtils.dropTable(connectionSource, DanaRHistoryRecord.class, true);
|
||||||
|
TableUtils.createTableIfNotExists(connectionSource, TempBasal.class);
|
||||||
|
TableUtils.createTableIfNotExists(connectionSource, Treatment.class);
|
||||||
|
TableUtils.createTableIfNotExists(connectionSource, BgReading.class);
|
||||||
|
TableUtils.createTableIfNotExists(connectionSource, DanaRHistoryRecord.class);
|
||||||
|
// MainApp.bus().post(new EventNewBG());
|
||||||
|
// MainApp.bus().post(new EventTreatmentChange());
|
||||||
|
// MainApp.bus().post(new EventTempBasalChange());
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resetTreatments() {
|
||||||
|
try {
|
||||||
|
|
||||||
|
TableUtils.dropTable(connectionSource, Treatment.class, true);
|
||||||
|
TableUtils.createTableIfNotExists(connectionSource, Treatment.class);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Dao<TempBasal, Long> getDaoTempBasals() throws SQLException {
|
||||||
|
return getDao(TempBasal.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Dao<Treatment, Long> getDaoTreatments() throws SQLException {
|
||||||
|
return getDao(Treatment.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Dao<BgReading, Long> getDaoBgReadings() throws SQLException {
|
||||||
|
return getDao(BgReading.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Dao<DanaRHistoryRecord, String> getDaoDanaRHistory() throws SQLException {
|
||||||
|
return getDao(DanaRHistoryRecord.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return last BgReading from database or null if db is empty
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public BgReading lastBg() {
|
||||||
|
List<BgReading> bgList = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
Dao<BgReading, Long> daoBgReadings = MainApp.getDbHelper().getDaoBgReadings();
|
||||||
|
QueryBuilder<BgReading, Long> queryBuilder = daoBgReadings.queryBuilder();
|
||||||
|
queryBuilder.orderBy("timeIndex", false);
|
||||||
|
queryBuilder.limit(1L);
|
||||||
|
PreparedQuery<BgReading> preparedQuery = queryBuilder.prepare();
|
||||||
|
bgList = daoBgReadings.query(preparedQuery);
|
||||||
|
|
||||||
|
} catch (SQLException e) {
|
||||||
|
log.debug(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
if (bgList != null && bgList.size() > 0)
|
||||||
|
return bgList.get(0);
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return bg reading if not old ( <9 min )
|
||||||
|
* or null if older
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public BgReading actualBg() {
|
||||||
|
BgReading lastBg = lastBg();
|
||||||
|
|
||||||
|
if (lastBg == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (lastBg.timeIndex > new Date().getTime() - 9 * 60 * 1000)
|
||||||
|
return lastBg;
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<BgReading> getDataFromTime(long mills) {
|
||||||
|
try {
|
||||||
|
Dao<BgReading, Long> daoBgreadings = getDaoBgReadings();
|
||||||
|
List<BgReading> bgReadings;
|
||||||
|
QueryBuilder<BgReading, Long> queryBuilder = daoBgreadings.queryBuilder();
|
||||||
|
queryBuilder.orderBy("timeIndex", true);
|
||||||
|
Where where = queryBuilder.where();
|
||||||
|
where.ge("timeIndex", mills);
|
||||||
|
PreparedQuery<BgReading> preparedQuery = queryBuilder.prepare();
|
||||||
|
bgReadings = daoBgreadings.query(preparedQuery);
|
||||||
|
return bgReadings;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return new ArrayList<BgReading>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns glucose_status for openAPS or null if no actual data available
|
||||||
|
*/
|
||||||
|
public static class GlucoseStatus implements Parcelable {
|
||||||
|
public double glucose = 0d;
|
||||||
|
public double delta = 0d;
|
||||||
|
public double avgdelta = 0d;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return MainApp.sResources.getString(R.string.glucose) + " " + DecimalFormatter.to0Decimal(glucose) + " mg/dl\n" +
|
||||||
|
MainApp.sResources.getString(R.string.delta) + " " + DecimalFormatter.to0Decimal(delta) + " mg/dl\n" +
|
||||||
|
MainApp.sResources.getString(R.string.avgdelta) + " " + DecimalFormatter.to2Decimal(avgdelta) + " mg/dl";
|
||||||
|
}
|
||||||
|
|
||||||
|
public Spanned toSpanned() {
|
||||||
|
return Html.fromHtml("<b>" + MainApp.sResources.getString(R.string.glucose) + "</b>: " + DecimalFormatter.to0Decimal(glucose) + " mg/dl<br>" +
|
||||||
|
"<b>" + MainApp.sResources.getString(R.string.delta) + "</b>: " + DecimalFormatter.to0Decimal(delta) + " mg/dl<br>" +
|
||||||
|
"<b>" + MainApp.sResources.getString(R.string.avgdelta) + "</b>: " + DecimalFormatter.to2Decimal(avgdelta) + " mg/dl");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int describeContents() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToParcel(Parcel dest, int flags) {
|
||||||
|
dest.writeDouble(avgdelta);
|
||||||
|
dest.writeDouble(delta);
|
||||||
|
dest.writeDouble(glucose);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final Parcelable.Creator<GlucoseStatus> CREATOR = new Parcelable.Creator<GlucoseStatus>() {
|
||||||
|
public GlucoseStatus createFromParcel(Parcel in) {
|
||||||
|
return new GlucoseStatus(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GlucoseStatus[] newArray(int size) {
|
||||||
|
return new GlucoseStatus[size];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private GlucoseStatus(Parcel in) {
|
||||||
|
avgdelta = in.readDouble();
|
||||||
|
delta = in.readDouble();
|
||||||
|
glucose = in.readDouble();
|
||||||
|
}
|
||||||
|
|
||||||
|
public GlucoseStatus() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public GlucoseStatus(Double glucose, Double delta, Double avgdelta) {
|
||||||
|
this.glucose = glucose;
|
||||||
|
this.delta = delta;
|
||||||
|
this.avgdelta = avgdelta;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GlucoseStatus round() {
|
||||||
|
this.glucose = Round.roundTo(this.glucose, 0.1);
|
||||||
|
this.delta = Round.roundTo(this.delta, 0.01);
|
||||||
|
this.avgdelta = Round.roundTo(this.avgdelta, 0.01);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public GlucoseStatus getGlucoseStatusData() {
|
||||||
|
GlucoseStatus result = new GlucoseStatus();
|
||||||
|
try {
|
||||||
|
|
||||||
|
Dao<BgReading, Long> daoBgreadings = null;
|
||||||
|
daoBgreadings = getDaoBgReadings();
|
||||||
|
List<BgReading> bgReadings;
|
||||||
|
QueryBuilder<BgReading, Long> queryBuilder = daoBgreadings.queryBuilder();
|
||||||
|
queryBuilder.orderBy("timeIndex", false);
|
||||||
|
queryBuilder.limit(4l);
|
||||||
|
PreparedQuery<BgReading> preparedQuery = queryBuilder.prepare();
|
||||||
|
bgReadings = daoBgreadings.query(preparedQuery);
|
||||||
|
|
||||||
|
int sizeRecords = bgReadings.size();
|
||||||
|
|
||||||
|
if (sizeRecords < 4 || bgReadings.get(sizeRecords - 4).timeIndex < new Date().getTime() - 7 * 60 * 1000L) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
int minutes = 5;
|
||||||
|
double change;
|
||||||
|
double avg;
|
||||||
|
|
||||||
|
if (bgReadings.size() > 3) {
|
||||||
|
BgReading now = bgReadings.get(sizeRecords - 4);
|
||||||
|
BgReading last = bgReadings.get(sizeRecords - 3);
|
||||||
|
BgReading last1 = bgReadings.get(sizeRecords - 2);
|
||||||
|
BgReading last2 = bgReadings.get(sizeRecords - 1);
|
||||||
|
if (last2.value > 30) {
|
||||||
|
minutes = 3 * 5;
|
||||||
|
change = now.value - last2.value;
|
||||||
|
} else if (last1.value > 30) {
|
||||||
|
minutes = 2 * 5;
|
||||||
|
change = now.value - last1.value;
|
||||||
|
} else if (last.value > 30) {
|
||||||
|
minutes = 5;
|
||||||
|
change = now.value - last.value;
|
||||||
|
} else {
|
||||||
|
change = 0;
|
||||||
|
}
|
||||||
|
//multiply by 5 to get the same unit as delta, i.e. mg/dL/5m
|
||||||
|
avg = change / minutes * 5;
|
||||||
|
|
||||||
|
result.glucose = now.value;
|
||||||
|
result.delta = now.value - last.value;
|
||||||
|
result.avgdelta = avg;
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
result.round();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
206
app/src/main/java/info/nightscout/androidaps/db/TempBasal.java
Normal file
206
app/src/main/java/info/nightscout/androidaps/db/TempBasal.java
Normal file
|
@ -0,0 +1,206 @@
|
||||||
|
package info.nightscout.androidaps.db;
|
||||||
|
|
||||||
|
import com.j256.ormlite.field.DatabaseField;
|
||||||
|
import com.j256.ormlite.table.DatabaseTable;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
import info.nightscout.androidaps.data.Iob;
|
||||||
|
import info.nightscout.androidaps.plugins.OpenAPSMA.IobTotal;
|
||||||
|
import info.nightscout.client.data.NSProfile;
|
||||||
|
import info.nightscout.utils.DecimalFormatter;
|
||||||
|
|
||||||
|
@DatabaseTable(tableName = DatabaseHelper.DATABASE_TEMPBASALS)
|
||||||
|
public class TempBasal {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(TempBasal.class);
|
||||||
|
|
||||||
|
public long getTimeIndex() {
|
||||||
|
return timeStart.getTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTimeIndex(long timeIndex) {
|
||||||
|
this.timeIndex = timeIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
@DatabaseField(id = true, useGetSet = true)
|
||||||
|
public long timeIndex;
|
||||||
|
|
||||||
|
@DatabaseField
|
||||||
|
public Date timeStart;
|
||||||
|
|
||||||
|
@DatabaseField
|
||||||
|
public Date timeEnd;
|
||||||
|
|
||||||
|
@DatabaseField
|
||||||
|
public int percent; // In % of current basal. 100% == current basal
|
||||||
|
|
||||||
|
@DatabaseField
|
||||||
|
public Double absolute; // Absolute value in U
|
||||||
|
|
||||||
|
@DatabaseField
|
||||||
|
public int duration; // in minutes
|
||||||
|
|
||||||
|
@DatabaseField
|
||||||
|
public boolean isExtended = false; // true if set as extended bolus
|
||||||
|
|
||||||
|
@DatabaseField
|
||||||
|
public boolean isAbsolute = false; // true if if set as absolute value in U
|
||||||
|
|
||||||
|
|
||||||
|
public IobTotal iobCalc(Date time) {
|
||||||
|
IobTotal result = new IobTotal();
|
||||||
|
NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile();
|
||||||
|
|
||||||
|
if (profile == null)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
int realDuration = getRealDuration();
|
||||||
|
|
||||||
|
if (realDuration > 0) {
|
||||||
|
Double netBasalRate = 0d;
|
||||||
|
Double basalRate = profile.getBasal(profile.secondsFromMidnight(time));
|
||||||
|
Double tempBolusSize = 0.05;
|
||||||
|
|
||||||
|
if (isExtended) {
|
||||||
|
netBasalRate = this.absolute;
|
||||||
|
} else {
|
||||||
|
if (this.isAbsolute) {
|
||||||
|
netBasalRate = this.absolute - basalRate;
|
||||||
|
} else {
|
||||||
|
netBasalRate = (this.percent - 100) / 100d * basalRate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result.netRatio = netBasalRate;
|
||||||
|
Double netBasalAmount = Math.round(netBasalRate * realDuration * 10 / 6) / 100d;
|
||||||
|
result.netInsulin = netBasalAmount;
|
||||||
|
if (netBasalAmount < 0.1) {
|
||||||
|
tempBolusSize = 0.01;
|
||||||
|
}
|
||||||
|
if (netBasalRate < 0) {
|
||||||
|
tempBolusSize = -tempBolusSize;
|
||||||
|
}
|
||||||
|
Long tempBolusCount = Math.round(netBasalAmount / tempBolusSize);
|
||||||
|
if (tempBolusCount > 0) {
|
||||||
|
Long tempBolusSpacing = realDuration / tempBolusCount;
|
||||||
|
for (Long j = 0l; j < tempBolusCount; j++) {
|
||||||
|
Treatment tempBolusPart = new Treatment();
|
||||||
|
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());
|
||||||
|
result.basaliob += aIOB.iobContrib;
|
||||||
|
Double dia_ago = time.getTime() - profile.getDia() * 60 * 60 * 1000;
|
||||||
|
if (date > dia_ago && date <= time.getTime()) {
|
||||||
|
result.netbasalinsulin += tempBolusPart.insulin;
|
||||||
|
if (tempBolusPart.insulin > 0) {
|
||||||
|
result.hightempinsulin += tempBolusPart.insulin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine end of basal
|
||||||
|
public Date getTimeEnd() {
|
||||||
|
Date tempBasalTimePlannedEnd = getPlannedTimeEnd();
|
||||||
|
Date now = new Date();
|
||||||
|
|
||||||
|
if (timeEnd != null && timeEnd.getTime() < tempBasalTimePlannedEnd.getTime()) {
|
||||||
|
tempBasalTimePlannedEnd = timeEnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (now.getTime() < tempBasalTimePlannedEnd.getTime())
|
||||||
|
tempBasalTimePlannedEnd = now;
|
||||||
|
|
||||||
|
return tempBasalTimePlannedEnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getPlannedTimeEnd() {
|
||||||
|
return new Date(timeStart.getTime() + 60 * 1_000 * duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRealDuration() {
|
||||||
|
Long msecs = getTimeEnd().getTime() - timeStart.getTime();
|
||||||
|
return (int) (msecs / 60 / 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getMillisecondsFromStart() {
|
||||||
|
return new Date().getTime() - timeStart.getTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPlannedRemainingMinutes() {
|
||||||
|
if (timeEnd != null) return 0;
|
||||||
|
long remainingMin = (getPlannedTimeEnd().getTime() - new Date().getTime()) / 1000 / 60;
|
||||||
|
return (remainingMin < 0) ? 0 : (int) remainingMin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isInProgress() {
|
||||||
|
return isInProgress(new Date());
|
||||||
|
}
|
||||||
|
|
||||||
|
public double tempBasalConvertedToAbsolute(Date time) {
|
||||||
|
if (isExtended) {
|
||||||
|
NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile();
|
||||||
|
double absval = profile.getBasal(NSProfile.secondsFromMidnight(time)) + absolute;
|
||||||
|
return absval;
|
||||||
|
} else {
|
||||||
|
if (isAbsolute) return absolute;
|
||||||
|
else {
|
||||||
|
NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile();
|
||||||
|
double absval = profile.getBasal(NSProfile.secondsFromMidnight(time)) * percent / 100;
|
||||||
|
return absval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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())
|
||||||
|
return true; // in interval
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// closed end
|
||||||
|
if (timeStart.getTime() < time.getTime() && timeEnd.getTime() > time.getTime()) return true; // in interval
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String log() {
|
||||||
|
return "TempBasal{" +
|
||||||
|
"timeIndex=" + timeIndex +
|
||||||
|
", timeStart=" + timeStart +
|
||||||
|
", timeEnd=" + timeEnd +
|
||||||
|
", percent=" + percent +
|
||||||
|
", absolute=" + absolute +
|
||||||
|
", duration=" + duration +
|
||||||
|
", isAbsolute=" + isAbsolute +
|
||||||
|
", isExtended=" + isExtended +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
DateFormat formatDateToJustTime = new SimpleDateFormat("HH:mm");
|
||||||
|
String extended = isExtended ? "E " : "";
|
||||||
|
|
||||||
|
if (isAbsolute) {
|
||||||
|
return extended + DecimalFormatter.to2Decimal(absolute) + "U/h @" +
|
||||||
|
formatDateToJustTime.format(timeStart) +
|
||||||
|
" " + getRealDuration() + "/" + duration + "min";
|
||||||
|
} else { // percent
|
||||||
|
return percent + "% @" +
|
||||||
|
formatDateToJustTime.format(timeStart) +
|
||||||
|
" " + getRealDuration() + "/" + duration + "min";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
153
app/src/main/java/info/nightscout/androidaps/db/Treatment.java
Normal file
153
app/src/main/java/info/nightscout/androidaps/db/Treatment.java
Normal file
|
@ -0,0 +1,153 @@
|
||||||
|
package info.nightscout.androidaps.db;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
import info.nightscout.androidaps.data.Iob;
|
||||||
|
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment;
|
||||||
|
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||||
|
import info.nightscout.androidaps.plugins.Overview.GraphSeriesExtension.DataPointWithLabelInterface;
|
||||||
|
import info.nightscout.client.data.NSProfile;
|
||||||
|
import info.nightscout.utils.DateUtil;
|
||||||
|
import info.nightscout.utils.DecimalFormatter;
|
||||||
|
|
||||||
|
@DatabaseTable(tableName = DatabaseHelper.DATABASE_TREATMENTS)
|
||||||
|
public class Treatment implements DataPointWithLabelInterface {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(Treatment.class);
|
||||||
|
|
||||||
|
public long getTimeIndex() {
|
||||||
|
return created_at.getTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTimeIndex(long timeIndex) {
|
||||||
|
this.timeIndex = timeIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
@DatabaseField(id = true, useGetSet = true)
|
||||||
|
public long timeIndex;
|
||||||
|
|
||||||
|
@DatabaseField
|
||||||
|
public String _id;
|
||||||
|
|
||||||
|
@DatabaseField
|
||||||
|
public Date created_at;
|
||||||
|
|
||||||
|
@DatabaseField
|
||||||
|
public Double insulin = 0d;
|
||||||
|
|
||||||
|
@DatabaseField
|
||||||
|
public Double carbs = 0d;
|
||||||
|
|
||||||
|
@DatabaseField
|
||||||
|
public boolean mealBolus = true; // true for meal bolus , false for correction bolus
|
||||||
|
|
||||||
|
public void copyFrom(Treatment t) {
|
||||||
|
this._id = t._id;
|
||||||
|
this.created_at = t.created_at;
|
||||||
|
this.insulin = t.insulin;
|
||||||
|
this.carbs = t.carbs;
|
||||||
|
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 * dia - peak));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getMillisecondsFromStart() {
|
||||||
|
return new Date().getTime() - created_at.getTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String log() {
|
||||||
|
return "Treatment{" +
|
||||||
|
"timeIndex: " + timeIndex +
|
||||||
|
", _id: " + _id +
|
||||||
|
", insulin: " + insulin +
|
||||||
|
", carbs: " + carbs +
|
||||||
|
", mealBolus: " + mealBolus +
|
||||||
|
", created_at: " +
|
||||||
|
"}";
|
||||||
|
}
|
||||||
|
|
||||||
|
// DataPointInterface
|
||||||
|
@Override
|
||||||
|
public double getX() {
|
||||||
|
return timeIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
// default when no sgv around available
|
||||||
|
private double yValue = 0;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getY() {
|
||||||
|
return yValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getLabel() {
|
||||||
|
String label = "";
|
||||||
|
if (insulin > 0) label += DecimalFormatter.to2Decimal(insulin) + "U";
|
||||||
|
if (carbs > 0)
|
||||||
|
label += (label.equals("") ? "" : " ") + DecimalFormatter.to0Decimal(carbs) + "g";
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setYValue(List<BgReading> bgReadingsArray) {
|
||||||
|
NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile();
|
||||||
|
if (profile == null) return;
|
||||||
|
for (int r = bgReadingsArray.size() - 1; r >= 0; r--) {
|
||||||
|
BgReading reading = bgReadingsArray.get(r);
|
||||||
|
if (reading.timeIndex > timeIndex) continue;
|
||||||
|
yValue = NSProfile.fromMgdlToUnits(reading.value, profile.getUnits());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendToNSClient() {
|
||||||
|
JSONObject data = new JSONObject();
|
||||||
|
try {
|
||||||
|
if (mealBolus)
|
||||||
|
data.put("eventType", "Meal Bolus");
|
||||||
|
else
|
||||||
|
data.put("eventType", "Correction Bolus");
|
||||||
|
if (insulin != 0d) data.put("insulin", insulin);
|
||||||
|
if (carbs != 0d) data.put("carbs", carbs.intValue());
|
||||||
|
data.put("created_at", DateUtil.toISOString(created_at));
|
||||||
|
data.put("timeIndex", timeIndex);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
ConfigBuilderPlugin.uploadCareportalEntryToNS(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package info.nightscout.androidaps.events;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 07.07.2016.
|
||||||
|
*/
|
||||||
|
public class EventAppExit {
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package info.nightscout.androidaps.events;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 05.06.2016.
|
||||||
|
*/
|
||||||
|
public class EventNewBG {
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
package info.nightscout.androidaps.events;
|
||||||
|
|
||||||
|
import info.nightscout.client.data.NSProfile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 04.06.2016.
|
||||||
|
*/
|
||||||
|
public class EventNewBasalProfile {
|
||||||
|
public NSProfile newNSProfile = null;
|
||||||
|
|
||||||
|
public EventNewBasalProfile(NSProfile newProfile) {
|
||||||
|
newNSProfile = newProfile;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package info.nightscout.androidaps.events;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 19.06.2016.
|
||||||
|
*/
|
||||||
|
public class EventPreferenceChange {
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package info.nightscout.androidaps.events;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 13.06.2016.
|
||||||
|
*/
|
||||||
|
public class EventRefreshGui {
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package info.nightscout.androidaps.events;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 05.06.2016.
|
||||||
|
*/
|
||||||
|
public class EventTempBasalChange {
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package info.nightscout.androidaps.events;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 04.06.2016.
|
||||||
|
*/
|
||||||
|
public class EventTreatmentChange {
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package info.nightscout.androidaps.interfaces;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.plugins.Loop.APSResult;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 10.06.2016.
|
||||||
|
*/
|
||||||
|
public interface APSInterface {
|
||||||
|
public APSResult getLastAPSResult();
|
||||||
|
public Date getLastAPSRun();
|
||||||
|
|
||||||
|
public void invoke();
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package info.nightscout.androidaps.interfaces;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 20.06.2016.
|
||||||
|
*/
|
||||||
|
public interface BgSourceInterface {
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package info.nightscout.androidaps.interfaces;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.plugins.Loop.APSResult;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 15.06.2016.
|
||||||
|
*/
|
||||||
|
public interface ConstraintsInterface {
|
||||||
|
|
||||||
|
boolean isLoopEnabled();
|
||||||
|
|
||||||
|
boolean isClosedModeEnabled();
|
||||||
|
|
||||||
|
boolean isAutosensModeEnabled();
|
||||||
|
|
||||||
|
boolean isAMAModeEnabled();
|
||||||
|
|
||||||
|
Double applyBasalConstraints(Double absoluteRate);
|
||||||
|
|
||||||
|
Integer applyBasalConstraints(Integer percentRate);
|
||||||
|
|
||||||
|
Double applyBolusConstraints(Double insulin);
|
||||||
|
|
||||||
|
Integer applyCarbsConstraints(Integer carbs);
|
||||||
|
|
||||||
|
Double applyMaxIOBConstraints(Double maxIob);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package info.nightscout.androidaps.interfaces;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 05.08.2016.
|
||||||
|
*/
|
||||||
|
public interface FragmentBase {
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package info.nightscout.androidaps.interfaces;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 09.06.2016.
|
||||||
|
*/
|
||||||
|
public interface PluginBase {
|
||||||
|
int GENERAL = 1;
|
||||||
|
int TREATMENT = 2;
|
||||||
|
int TEMPBASAL = 3;
|
||||||
|
int PROFILE = 4;
|
||||||
|
int APS = 5;
|
||||||
|
int PUMP = 6;
|
||||||
|
int CONSTRAINTS = 7;
|
||||||
|
int LOOP = 8;
|
||||||
|
int BGSOURCE = 9;
|
||||||
|
int LAST = 10; // keep always highest number
|
||||||
|
|
||||||
|
int getType();
|
||||||
|
String getFragmentClass();
|
||||||
|
|
||||||
|
String getName();
|
||||||
|
boolean isEnabled(int type);
|
||||||
|
boolean isVisibleInTabs(int type);
|
||||||
|
boolean canBeHidden(int type);
|
||||||
|
void setFragmentEnabled(int type, boolean fragmentEnabled);
|
||||||
|
void setFragmentVisible(int type, boolean fragmentVisible);
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
package info.nightscout.androidaps.interfaces;
|
||||||
|
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
|
import info.nightscout.client.data.NSProfile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 14.06.2016.
|
||||||
|
*/
|
||||||
|
public interface ProfileInterface {
|
||||||
|
@Nullable
|
||||||
|
NSProfile getProfile();
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
package info.nightscout.androidaps.interfaces;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 04.06.2016.
|
||||||
|
*/
|
||||||
|
public interface PumpInterface {
|
||||||
|
|
||||||
|
boolean isTempBasalInProgress();
|
||||||
|
boolean isExtendedBoluslInProgress();
|
||||||
|
|
||||||
|
// Upload to pump new basal profile
|
||||||
|
void setNewBasalProfile(NSProfile profile);
|
||||||
|
|
||||||
|
double getBaseBasalRate(); // base basal rate, not temp basal
|
||||||
|
double getTempBasalAbsoluteRate();
|
||||||
|
double getTempBasalRemainingMinutes();
|
||||||
|
TempBasal getTempBasal(Date time);
|
||||||
|
TempBasal getTempBasal();
|
||||||
|
TempBasal getExtendedBolus();
|
||||||
|
|
||||||
|
PumpEnactResult deliverTreatment(Double insulin, Integer carbs, Context context);
|
||||||
|
void stopBolusDelivering();
|
||||||
|
PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes);
|
||||||
|
PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes);
|
||||||
|
PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes);
|
||||||
|
PumpEnactResult cancelTempBasal();
|
||||||
|
PumpEnactResult cancelExtendedBolus();
|
||||||
|
|
||||||
|
// Status to be passed to NS
|
||||||
|
JSONObject getJSONStatus();
|
||||||
|
String deviceID();
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
package info.nightscout.androidaps.interfaces;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.db.TempBasal;
|
||||||
|
import info.nightscout.androidaps.plugins.OpenAPSMA.IobTotal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 14.06.2016.
|
||||||
|
*/
|
||||||
|
public interface TempBasalsInterface {
|
||||||
|
void updateTotalIOB();
|
||||||
|
IobTotal getLastCalculation();
|
||||||
|
|
||||||
|
TempBasal getTempBasal (Date time);
|
||||||
|
TempBasal getExtendedBolus (Date time);
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package info.nightscout.androidaps.interfaces;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.db.Treatment;
|
||||||
|
import info.nightscout.androidaps.plugins.OpenAPSMA.IobTotal;
|
||||||
|
import info.nightscout.androidaps.plugins.Treatments.TreatmentsFragment;
|
||||||
|
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 14.06.2016.
|
||||||
|
*/
|
||||||
|
public interface TreatmentsInterface {
|
||||||
|
|
||||||
|
void updateTotalIOB();
|
||||||
|
IobTotal getLastCalculation();
|
||||||
|
TreatmentsPlugin.MealData getMealData();
|
||||||
|
List<Treatment> getTreatments();
|
||||||
|
}
|
|
@ -0,0 +1,175 @@
|
||||||
|
package info.nightscout.androidaps.plugins.Careportal;
|
||||||
|
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v4.app.Fragment;
|
||||||
|
import android.support.v4.app.FragmentManager;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
import info.nightscout.androidaps.R;
|
||||||
|
import info.nightscout.androidaps.interfaces.FragmentBase;
|
||||||
|
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||||
|
import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog;
|
||||||
|
|
||||||
|
public class CareportalFragment extends Fragment implements FragmentBase, View.OnClickListener {
|
||||||
|
|
||||||
|
static CareportalPlugin careportalPlugin = new CareportalPlugin();
|
||||||
|
|
||||||
|
static public CareportalPlugin getPlugin() {
|
||||||
|
return careportalPlugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class OptionsToShow {
|
||||||
|
public int eventType;
|
||||||
|
public int eventName;
|
||||||
|
public boolean bg;
|
||||||
|
public boolean insulin;
|
||||||
|
public boolean carbs;
|
||||||
|
public boolean prebolus;
|
||||||
|
public boolean duration;
|
||||||
|
public boolean percent;
|
||||||
|
public boolean absolute;
|
||||||
|
public boolean profile;
|
||||||
|
public boolean split;
|
||||||
|
|
||||||
|
public OptionsToShow(int eventType,
|
||||||
|
int eventName,
|
||||||
|
boolean bg,
|
||||||
|
boolean insulin,
|
||||||
|
boolean carbs,
|
||||||
|
boolean prebolus,
|
||||||
|
boolean duration,
|
||||||
|
boolean percent,
|
||||||
|
boolean absolute,
|
||||||
|
boolean profile,
|
||||||
|
boolean split) {
|
||||||
|
this.eventType = eventType;
|
||||||
|
this.eventName = eventName;
|
||||||
|
this.bg = bg;
|
||||||
|
this.insulin = insulin;
|
||||||
|
this.carbs = carbs;
|
||||||
|
this.prebolus = prebolus;
|
||||||
|
this.duration = duration;
|
||||||
|
this.percent = percent;
|
||||||
|
this.absolute = absolute;
|
||||||
|
this.profile = profile;
|
||||||
|
this.split = split;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// bg,insulin,carbs,prebolus,duration,percent,absolute,profile,split
|
||||||
|
final OptionsToShow bgcheck = new OptionsToShow(R.id.careportal_bgcheck, R.string.careportal_bgcheck, true, true, true, false, false, false, false, false, false);
|
||||||
|
final OptionsToShow snackbolus = new OptionsToShow(R.id.careportal_snackbolus, R.string.careportal_snackbolus, true, true, true, true, false, false, false, false, false);
|
||||||
|
final OptionsToShow mealbolus = new OptionsToShow(R.id.careportal_mealbolus, R.string.careportal_mealbolus, true, true, true, true, false, false, false, false, false);
|
||||||
|
final OptionsToShow correctionbolus = new OptionsToShow(R.id.careportal_correctionbolus, R.string.careportal_correctionbolus, true, true, true, true, false, false, false, false, false);
|
||||||
|
final OptionsToShow carbcorrection = new OptionsToShow(R.id.careportal_carbscorrection, R.string.careportal_carbscorrection, true, false, true, false, false, false, false, false, false);
|
||||||
|
final OptionsToShow combobolus = new OptionsToShow(R.id.careportal_combobolus, R.string.careportal_combobolus, true, true, true, true, true, false, false, false, true);
|
||||||
|
final OptionsToShow announcement = new OptionsToShow(R.id.careportal_announcement, R.string.careportal_announcement, true, false, false, false, false, false, false, false, false);
|
||||||
|
final OptionsToShow note = new OptionsToShow(R.id.careportal_note, R.string.careportal_note, true, false, false, false, true, false, false, false, false);
|
||||||
|
final OptionsToShow question = new OptionsToShow(R.id.careportal_question, R.string.careportal_question, true, false, false, false, false, false, false, false, false);
|
||||||
|
final OptionsToShow exercise = new OptionsToShow(R.id.careportal_exercise, R.string.careportal_exercise, false, false, false, false, true, false, false, false, false);
|
||||||
|
final OptionsToShow sitechange = new OptionsToShow(R.id.careportal_pumpsitechange, R.string.careportal_pumpsitechange, true, true, false, false, false, false, false, false, false);
|
||||||
|
final OptionsToShow sensorstart = new OptionsToShow(R.id.careportal_cgmsensorstart, R.string.careportal_cgmsensorstart, true, false, false, false, false, false, false, false, false);
|
||||||
|
final OptionsToShow sensorchange = new OptionsToShow(R.id.careportal_cgmsensorinsert, R.string.careportal_cgmsensorinsert, true, false, false, false, false, false, false, false, false);
|
||||||
|
final OptionsToShow insulinchange = new OptionsToShow(R.id.careportal_insulincartridgechange, R.string.careportal_insulincartridgechange, true, false, false, false, false, false, false, false, false);
|
||||||
|
final OptionsToShow tempbasalstart = new OptionsToShow(R.id.careportal_tempbasalstart, R.string.careportal_tempbasalstart, true, false, false, false, true, true, true, false, false);
|
||||||
|
final OptionsToShow tempbasalend = new OptionsToShow(R.id.careportal_tempbasalend, R.string.careportal_tempbasalend, true, false, false, false, false, false, false, false, false);
|
||||||
|
final OptionsToShow profileswitch = new OptionsToShow(R.id.careportal_profileswitch, R.string.careportal_profileswitch, true, false, false, false, false, false, false, true, false);
|
||||||
|
final OptionsToShow openapsoffline = new OptionsToShow(R.id.careportal_openapsoffline, R.string.careportal_openapsoffline, false, false, false, false, true, false, false, false, false);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
|
Bundle savedInstanceState) {
|
||||||
|
View view = inflater.inflate(R.layout.careportal_fragment, container, false);
|
||||||
|
|
||||||
|
view.findViewById(R.id.careportal_bgcheck).setOnClickListener(this);
|
||||||
|
view.findViewById(R.id.careportal_announcement).setOnClickListener(this);
|
||||||
|
view.findViewById(R.id.careportal_cgmsensorinsert).setOnClickListener(this);
|
||||||
|
view.findViewById(R.id.careportal_cgmsensorstart).setOnClickListener(this);
|
||||||
|
view.findViewById(R.id.careportal_combobolus).setOnClickListener(this);
|
||||||
|
view.findViewById(R.id.careportal_correctionbolus).setOnClickListener(this);
|
||||||
|
view.findViewById(R.id.careportal_carbscorrection).setOnClickListener(this);
|
||||||
|
view.findViewById(R.id.careportal_exercise).setOnClickListener(this);
|
||||||
|
view.findViewById(R.id.careportal_insulincartridgechange).setOnClickListener(this);
|
||||||
|
view.findViewById(R.id.careportal_mealbolus).setOnClickListener(this);
|
||||||
|
view.findViewById(R.id.careportal_note).setOnClickListener(this);
|
||||||
|
view.findViewById(R.id.careportal_profileswitch).setOnClickListener(this);
|
||||||
|
view.findViewById(R.id.careportal_pumpsitechange).setOnClickListener(this);
|
||||||
|
view.findViewById(R.id.careportal_question).setOnClickListener(this);
|
||||||
|
view.findViewById(R.id.careportal_snackbolus).setOnClickListener(this);
|
||||||
|
view.findViewById(R.id.careportal_tempbasalend).setOnClickListener(this);
|
||||||
|
view.findViewById(R.id.careportal_tempbasalstart).setOnClickListener(this);
|
||||||
|
view.findViewById(R.id.careportal_openapsoffline).setOnClickListener(this);
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
FragmentManager manager = getFragmentManager();
|
||||||
|
NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog();
|
||||||
|
switch (view.getId()) {
|
||||||
|
case R.id.careportal_bgcheck:
|
||||||
|
newDialog.setOptions(bgcheck);
|
||||||
|
break;
|
||||||
|
case R.id.careportal_announcement:
|
||||||
|
newDialog.setOptions(announcement);
|
||||||
|
break;
|
||||||
|
case R.id.careportal_cgmsensorinsert:
|
||||||
|
newDialog.setOptions(sensorchange);
|
||||||
|
break;
|
||||||
|
case R.id.careportal_cgmsensorstart:
|
||||||
|
newDialog.setOptions(sensorstart);
|
||||||
|
break;
|
||||||
|
case R.id.careportal_combobolus:
|
||||||
|
newDialog.setOptions(combobolus);
|
||||||
|
break;
|
||||||
|
case R.id.careportal_correctionbolus:
|
||||||
|
newDialog.setOptions(correctionbolus);
|
||||||
|
break;
|
||||||
|
case R.id.careportal_carbscorrection:
|
||||||
|
newDialog.setOptions(carbcorrection);
|
||||||
|
break;
|
||||||
|
case R.id.careportal_exercise:
|
||||||
|
newDialog.setOptions(exercise);
|
||||||
|
break;
|
||||||
|
case R.id.careportal_insulincartridgechange:
|
||||||
|
newDialog.setOptions(insulinchange);
|
||||||
|
break;
|
||||||
|
case R.id.careportal_mealbolus:
|
||||||
|
newDialog.setOptions(mealbolus);
|
||||||
|
break;
|
||||||
|
case R.id.careportal_note:
|
||||||
|
newDialog.setOptions(note);
|
||||||
|
break;
|
||||||
|
case R.id.careportal_profileswitch:
|
||||||
|
newDialog.setOptions(profileswitch);
|
||||||
|
break;
|
||||||
|
case R.id.careportal_pumpsitechange:
|
||||||
|
newDialog.setOptions(sitechange);
|
||||||
|
break;
|
||||||
|
case R.id.careportal_question:
|
||||||
|
newDialog.setOptions(question);
|
||||||
|
break;
|
||||||
|
case R.id.careportal_snackbolus:
|
||||||
|
newDialog.setOptions(snackbolus);
|
||||||
|
break;
|
||||||
|
case R.id.careportal_tempbasalstart:
|
||||||
|
newDialog.setOptions(tempbasalstart);
|
||||||
|
break;
|
||||||
|
case R.id.careportal_tempbasalend:
|
||||||
|
newDialog.setOptions(tempbasalend);
|
||||||
|
break;
|
||||||
|
case R.id.careportal_openapsoffline:
|
||||||
|
newDialog.setOptions(openapsoffline);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
newDialog = null;
|
||||||
|
}
|
||||||
|
if (newDialog != null)
|
||||||
|
newDialog.show(manager, "NewNSTreatmentDialog");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
package info.nightscout.androidaps.plugins.Careportal;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
import info.nightscout.androidaps.R;
|
||||||
|
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||||
|
|
||||||
|
public class CareportalPlugin implements PluginBase {
|
||||||
|
|
||||||
|
boolean fragmentEnabled = true;
|
||||||
|
boolean fragmentVisible = true;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getType() {
|
||||||
|
return PluginBase.GENERAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getFragmentClass() {
|
||||||
|
return CareportalFragment.class.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return MainApp.sResources.getString(R.string.careportal);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEnabled(int type) {
|
||||||
|
return fragmentEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isVisibleInTabs(int type) {
|
||||||
|
return fragmentVisible;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canBeHidden(int type) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
|
||||||
|
this.fragmentEnabled = fragmentEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFragmentVisible(int type, boolean fragmentVisible) {
|
||||||
|
this.fragmentVisible = fragmentVisible;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,541 @@
|
||||||
|
package info.nightscout.androidaps.plugins.Careportal.Dialogs;
|
||||||
|
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
|
import android.support.v4.app.DialogFragment;
|
||||||
|
import android.support.v4.app.FragmentActivity;
|
||||||
|
import android.support.v7.app.AlertDialog;
|
||||||
|
import android.text.Editable;
|
||||||
|
import android.text.TextWatcher;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ArrayAdapter;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.EditText;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.RadioButton;
|
||||||
|
import android.widget.Spinner;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.wdullaer.materialdatetimepicker.date.DatePickerDialog;
|
||||||
|
import com.wdullaer.materialdatetimepicker.time.RadialPickerLayout;
|
||||||
|
import com.wdullaer.materialdatetimepicker.time.TimePickerDialog;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.text.DecimalFormat;
|
||||||
|
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;
|
||||||
|
import info.nightscout.androidaps.Services.Intents;
|
||||||
|
import info.nightscout.androidaps.db.BgReading;
|
||||||
|
import info.nightscout.androidaps.plugins.Careportal.CareportalFragment;
|
||||||
|
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment;
|
||||||
|
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||||
|
import info.nightscout.androidaps.plugins.Overview.Dialogs.NewExtendedBolusDialog;
|
||||||
|
import info.nightscout.client.data.DbLogger;
|
||||||
|
import info.nightscout.client.data.NSProfile;
|
||||||
|
import info.nightscout.utils.DateUtil;
|
||||||
|
import info.nightscout.utils.PlusMinusEditText;
|
||||||
|
import info.nightscout.utils.SafeParse;
|
||||||
|
import info.nightscout.utils.ToastUtils;
|
||||||
|
import info.nightscout.utils.Translator;
|
||||||
|
|
||||||
|
public class NewNSTreatmentDialog extends DialogFragment implements View.OnClickListener, DatePickerDialog.OnDateSetListener, TimePickerDialog.OnTimeSetListener {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(NewNSTreatmentDialog.class);
|
||||||
|
|
||||||
|
private FragmentActivity context;
|
||||||
|
|
||||||
|
private static CareportalFragment.OptionsToShow options;
|
||||||
|
|
||||||
|
NSProfile profile;
|
||||||
|
String units;
|
||||||
|
|
||||||
|
LinearLayout layoutBg;
|
||||||
|
LinearLayout layoutBgSource;
|
||||||
|
LinearLayout layoutInsulin;
|
||||||
|
LinearLayout layoutCarbs;
|
||||||
|
LinearLayout layoutSplit;
|
||||||
|
LinearLayout layoutDuration;
|
||||||
|
LinearLayout layoutPercent;
|
||||||
|
LinearLayout layoutAbsolute;
|
||||||
|
LinearLayout layoutCarbTime;
|
||||||
|
LinearLayout layoutProfile;
|
||||||
|
Button dateButton;
|
||||||
|
Button timeButton;
|
||||||
|
Button okButton;
|
||||||
|
|
||||||
|
TextView bgUnitsView;
|
||||||
|
RadioButton meterRadioButton;
|
||||||
|
RadioButton sensorRadioButton;
|
||||||
|
RadioButton otherRadioButton;
|
||||||
|
EditText notesEdit;
|
||||||
|
EditText bgInputEdit;
|
||||||
|
EditText insulinEdit;
|
||||||
|
EditText carbsEdit;
|
||||||
|
EditText percentEdit;
|
||||||
|
EditText absoluteEdit;
|
||||||
|
EditText durationeEdit;
|
||||||
|
EditText carbTimeEdit;
|
||||||
|
EditText splitEdit;
|
||||||
|
Spinner profileSpinner;
|
||||||
|
|
||||||
|
PlusMinusEditText editBg;
|
||||||
|
PlusMinusEditText editCarbs;
|
||||||
|
PlusMinusEditText editInsulin;
|
||||||
|
PlusMinusEditText editSplit;
|
||||||
|
PlusMinusEditText editDuration;
|
||||||
|
PlusMinusEditText editPercent;
|
||||||
|
PlusMinusEditText editAbsolute;
|
||||||
|
PlusMinusEditText editCarbTime;
|
||||||
|
|
||||||
|
Date eventTime;
|
||||||
|
|
||||||
|
public void setOptions(CareportalFragment.OptionsToShow options) {
|
||||||
|
this.options = options;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAttach(Activity activity) {
|
||||||
|
context = (FragmentActivity) activity;
|
||||||
|
super.onAttach(activity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
|
Bundle savedInstanceState) {
|
||||||
|
getDialog().setTitle(getString(options.eventName));
|
||||||
|
View view = inflater.inflate(R.layout.careportal_newnstreatment_dialog, container, false);
|
||||||
|
|
||||||
|
layoutBg = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_bg_layout);
|
||||||
|
layoutBgSource = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_bgsource_layout);
|
||||||
|
layoutInsulin = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_insulin_layout);
|
||||||
|
layoutCarbs = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_carbs_layout);
|
||||||
|
layoutSplit = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_split_layout);
|
||||||
|
layoutDuration = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_duration_layout);
|
||||||
|
layoutPercent = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_percent_layout);
|
||||||
|
layoutAbsolute = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_absolute_layout);
|
||||||
|
layoutCarbTime = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_carbtime_layout);
|
||||||
|
layoutProfile = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_profile_layout);
|
||||||
|
|
||||||
|
bgUnitsView = (TextView) view.findViewById(R.id.careportal_newnstreatment_bgunits);
|
||||||
|
meterRadioButton = (RadioButton) view.findViewById(R.id.careportal_newnstreatment_meter);
|
||||||
|
sensorRadioButton = (RadioButton) view.findViewById(R.id.careportal_newnstreatment_sensor);
|
||||||
|
otherRadioButton = (RadioButton) view.findViewById(R.id.careportal_newnstreatment_other);
|
||||||
|
profileSpinner = (Spinner) view.findViewById(R.id.careportal_newnstreatment_profile);
|
||||||
|
|
||||||
|
bgInputEdit = (EditText) view.findViewById(R.id.careportal_newnstreatment_bginput);
|
||||||
|
insulinEdit = (EditText) view.findViewById(R.id.careportal_newnstreatment_insulininput);
|
||||||
|
carbsEdit = (EditText) view.findViewById(R.id.careportal_newnstreatment_carbsinput);
|
||||||
|
percentEdit = (EditText) view.findViewById(R.id.careportal_newnstreatment_percentinput);
|
||||||
|
percentEdit.addTextChangedListener(new TextWatcher() {
|
||||||
|
@Override
|
||||||
|
public void afterTextChanged(Editable s) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void beforeTextChanged(CharSequence s, int start,
|
||||||
|
int count, int after) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTextChanged(CharSequence s, int start,
|
||||||
|
int before, int count) {
|
||||||
|
layoutPercent.setVisibility(View.VISIBLE);
|
||||||
|
layoutAbsolute.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
absoluteEdit = (EditText) view.findViewById(R.id.careportal_newnstreatment_absoluteinput);
|
||||||
|
absoluteEdit.addTextChangedListener(new TextWatcher() {
|
||||||
|
@Override
|
||||||
|
public void afterTextChanged(Editable s) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void beforeTextChanged(CharSequence s, int start,
|
||||||
|
int count, int after) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTextChanged(CharSequence s, int start,
|
||||||
|
int before, int count) {
|
||||||
|
layoutPercent.setVisibility(View.GONE);
|
||||||
|
layoutAbsolute.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
durationeEdit = (EditText) view.findViewById(R.id.careportal_newnstreatment_durationinput);
|
||||||
|
carbTimeEdit = (EditText) view.findViewById(R.id.careportal_newnstreatment_carbtimeinput);
|
||||||
|
notesEdit = (EditText) view.findViewById(R.id.careportal_newnstreatment_notes);
|
||||||
|
splitEdit = (EditText) view.findViewById(R.id.careportal_newnstreatment_splitinput);
|
||||||
|
|
||||||
|
eventTime = new Date();
|
||||||
|
dateButton = (Button) view.findViewById(R.id.careportal_newnstreatment_eventdate);
|
||||||
|
timeButton = (Button) view.findViewById(R.id.careportal_newnstreatment_eventtime);
|
||||||
|
DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT);
|
||||||
|
DateFormat tf = DateFormat.getTimeInstance(DateFormat.SHORT);
|
||||||
|
dateButton.setText(df.format(eventTime));
|
||||||
|
timeButton.setText(tf.format(eventTime));
|
||||||
|
dateButton.setOnClickListener(this);
|
||||||
|
timeButton.setOnClickListener(this);
|
||||||
|
|
||||||
|
okButton = (Button) view.findViewById(R.id.careportal_newnstreatment_ok);
|
||||||
|
okButton.setOnClickListener(this);
|
||||||
|
|
||||||
|
// BG
|
||||||
|
profile = MainApp.getConfigBuilder().getActiveProfile().getProfile();
|
||||||
|
ArrayList<CharSequence> profileList;
|
||||||
|
units = Constants.MGDL;
|
||||||
|
if (profile == null) {
|
||||||
|
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), context.getString(R.string.noprofile));
|
||||||
|
profileList = new ArrayList<CharSequence>();
|
||||||
|
} else {
|
||||||
|
units = profile.getUnits();
|
||||||
|
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);
|
||||||
|
profileSpinner.setAdapter(adapter);
|
||||||
|
if (profile != null) {
|
||||||
|
// set selected to actual profile
|
||||||
|
for (int p = 0; p < profileList.size(); p++) {
|
||||||
|
if (profileList.get(p).equals(profile.getActiveProfile()))
|
||||||
|
profileSpinner.setSelection(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bgUnitsView.setText(units);
|
||||||
|
|
||||||
|
// Set BG if not old
|
||||||
|
// BgReading lastBg = MainApp.getDbHelper().lastBg();
|
||||||
|
// Double lastBgValue = 0d;
|
||||||
|
// if (lastBg != null) {
|
||||||
|
// lastBgValue = lastBg.valueToUnits(units);
|
||||||
|
// sensorRadioButton.setChecked(true);
|
||||||
|
// } else {
|
||||||
|
// meterRadioButton.setChecked(true);
|
||||||
|
// }
|
||||||
|
|
||||||
|
if (units.equals(Constants.MMOL))
|
||||||
|
editBg = new PlusMinusEditText(view, R.id.careportal_newnstreatment_bginput, R.id.careportal_newnstreatment_bg_plus, R.id.careportal_newnstreatment_bg_minus, 0d, 0d, 40d, 0.1d, new DecimalFormat("0.0"), false);
|
||||||
|
else
|
||||||
|
editBg = new PlusMinusEditText(view, R.id.careportal_newnstreatment_bginput, R.id.careportal_newnstreatment_bg_plus, R.id.careportal_newnstreatment_bg_minus, 0d, 0d, 500d, 1d, new DecimalFormat("0"), false);
|
||||||
|
|
||||||
|
Integer maxCarbs = MainApp.getConfigBuilder().applyCarbsConstraints(Constants.carbsOnlyForCheckLimit);
|
||||||
|
editCarbs = new PlusMinusEditText(view, R.id.careportal_newnstreatment_carbsinput, R.id.careportal_newnstreatment_carbs_plus, R.id.careportal_newnstreatment_carbs_minus, 0d, 0d, (double) maxCarbs, 1d, new DecimalFormat("0"), false);
|
||||||
|
|
||||||
|
Double maxInsulin = MainApp.getConfigBuilder().applyBolusConstraints(Constants.bolusOnlyForCheckLimit);
|
||||||
|
editInsulin = new PlusMinusEditText(view, R.id.careportal_newnstreatment_insulininput, R.id.careportal_newnstreatment_insulin_plus, R.id.careportal_newnstreatment_insulin_minus, 0d, 0d, maxInsulin, 0.05d, new DecimalFormat("0.00"), false);
|
||||||
|
|
||||||
|
editSplit = new PlusMinusEditText(view, R.id.careportal_newnstreatment_splitinput, R.id.careportal_newnstreatment_split_plus, R.id.careportal_newnstreatment_split_minus, 100d, 0d, 100d, 5d, new DecimalFormat("0"), true);
|
||||||
|
editDuration = new PlusMinusEditText(view, R.id.careportal_newnstreatment_durationinput, R.id.careportal_newnstreatment_duration_plus, R.id.careportal_newnstreatment_duration_minus, 0d, 0d, 24 * 60d, 10d, new DecimalFormat("0"), false);
|
||||||
|
|
||||||
|
Integer maxPercent = MainApp.getConfigBuilder().applyBasalConstraints(Constants.basalPercentOnlyForCheckLimit);
|
||||||
|
editPercent = new PlusMinusEditText(view, R.id.careportal_newnstreatment_percentinput, R.id.careportal_newnstreatment_percent_plus, R.id.careportal_newnstreatment_percent_minus, 0d, 0d, (double) maxPercent, 5d, new DecimalFormat("0"), true);
|
||||||
|
|
||||||
|
Double maxAbsolute = MainApp.getConfigBuilder().applyBasalConstraints(Constants.basalAbsoluteOnlyForCheckLimit);
|
||||||
|
editAbsolute = new PlusMinusEditText(view, R.id.careportal_newnstreatment_absoluteinput, R.id.careportal_newnstreatment_absolute_plus, R.id.careportal_newnstreatment_absolute_minus, 0d, 0d, maxAbsolute, 0.05d, new DecimalFormat("0.00"), true);
|
||||||
|
|
||||||
|
editCarbTime = new PlusMinusEditText(view, R.id.careportal_newnstreatment_carbtimeinput, R.id.careportal_newnstreatment_carbtime_plus, R.id.careportal_newnstreatment_carbtime_minus, 0d, -60d, 60d, 5d, new DecimalFormat("0"), false);
|
||||||
|
|
||||||
|
showOrHide(layoutBg, options.bg);
|
||||||
|
showOrHide(layoutBgSource, options.bg);
|
||||||
|
showOrHide(layoutInsulin, options.insulin);
|
||||||
|
showOrHide(layoutCarbs, options.carbs);
|
||||||
|
showOrHide(layoutSplit, options.split);
|
||||||
|
showOrHide(layoutDuration, options.duration);
|
||||||
|
showOrHide(layoutPercent, options.percent);
|
||||||
|
showOrHide(layoutAbsolute, options.absolute);
|
||||||
|
showOrHide(layoutCarbTime, options.prebolus);
|
||||||
|
showOrHide(layoutProfile, options.profile);
|
||||||
|
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
if (getDialog() != null)
|
||||||
|
getDialog().getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
Calendar calendar = Calendar.getInstance();
|
||||||
|
calendar.setTime(eventTime);
|
||||||
|
switch (view.getId()) {
|
||||||
|
case R.id.careportal_newnstreatment_eventdate:
|
||||||
|
DatePickerDialog dpd = DatePickerDialog.newInstance(
|
||||||
|
this,
|
||||||
|
calendar.get(Calendar.YEAR),
|
||||||
|
calendar.get(Calendar.MONTH),
|
||||||
|
calendar.get(Calendar.DAY_OF_MONTH)
|
||||||
|
);
|
||||||
|
dpd.setThemeDark(true);
|
||||||
|
dpd.dismissOnPause(true);
|
||||||
|
dpd.show(context.getFragmentManager(), "Datepickerdialog");
|
||||||
|
break;
|
||||||
|
case R.id.careportal_newnstreatment_eventtime:
|
||||||
|
android.text.format.DateFormat df = new android.text.format.DateFormat();
|
||||||
|
TimePickerDialog tpd = TimePickerDialog.newInstance(
|
||||||
|
this,
|
||||||
|
calendar.get(Calendar.HOUR_OF_DAY),
|
||||||
|
calendar.get(Calendar.MINUTE),
|
||||||
|
df.is24HourFormat(context)
|
||||||
|
);
|
||||||
|
tpd.setThemeDark(true);
|
||||||
|
tpd.dismissOnPause(true);
|
||||||
|
tpd.show(context.getFragmentManager(), "Timepickerdialog");
|
||||||
|
break;
|
||||||
|
case R.id.careportal_newnstreatment_ok:
|
||||||
|
createNSTreatment();
|
||||||
|
dismiss();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showOrHide(LinearLayout layout, boolean visible) {
|
||||||
|
if (visible) layout.setVisibility(View.VISIBLE);
|
||||||
|
else layout.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDateSet(DatePickerDialog view, int year, int monthOfYear, int dayOfMonth) {
|
||||||
|
eventTime.setYear(year - 1900);
|
||||||
|
eventTime.setMonth(monthOfYear);
|
||||||
|
eventTime.setDate(dayOfMonth);
|
||||||
|
DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT);
|
||||||
|
dateButton.setText(df.format(eventTime));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTimeSet(RadialPickerLayout view, int hourOfDay, int minute, int second) {
|
||||||
|
eventTime.setHours(hourOfDay);
|
||||||
|
eventTime.setMinutes(minute);
|
||||||
|
eventTime.setSeconds(second);
|
||||||
|
DateFormat tf = DateFormat.getTimeInstance(DateFormat.SHORT);
|
||||||
|
timeButton.setText(tf.format(eventTime));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
JSONObject gatherData() {
|
||||||
|
SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
|
||||||
|
String enteredBy = SP.getString("careportal_enteredby", "");
|
||||||
|
JSONObject data = new JSONObject();
|
||||||
|
try {
|
||||||
|
data.put("created_at", DateUtil.toISOString(eventTime));
|
||||||
|
switch (options.eventType) {
|
||||||
|
case R.id.careportal_bgcheck:
|
||||||
|
data.put("eventType", "BG Check");
|
||||||
|
break;
|
||||||
|
case R.id.careportal_announcement:
|
||||||
|
data.put("eventType", "Announcement");
|
||||||
|
data.put("isAnnouncement", true);
|
||||||
|
break;
|
||||||
|
case R.id.careportal_cgmsensorinsert:
|
||||||
|
data.put("eventType", "Sensor Change");
|
||||||
|
break;
|
||||||
|
case R.id.careportal_cgmsensorstart:
|
||||||
|
data.put("eventType", "Sensor Start");
|
||||||
|
break;
|
||||||
|
case R.id.careportal_combobolus:
|
||||||
|
data.put("splitNow", SafeParse.stringToDouble(splitEdit.getText().toString()));
|
||||||
|
data.put("splitExt", 100 - SafeParse.stringToDouble(splitEdit.getText().toString()));
|
||||||
|
data.put("eventType", "Combo Bolus");
|
||||||
|
break;
|
||||||
|
case R.id.careportal_correctionbolus:
|
||||||
|
data.put("eventType", "Correction Bolus");
|
||||||
|
break;
|
||||||
|
case R.id.careportal_carbscorrection:
|
||||||
|
data.put("eventType", "Carb Correction");
|
||||||
|
break;
|
||||||
|
case R.id.careportal_exercise:
|
||||||
|
data.put("eventType", "Exercise");
|
||||||
|
break;
|
||||||
|
case R.id.careportal_insulincartridgechange:
|
||||||
|
data.put("eventType", "Insulin Change");
|
||||||
|
break;
|
||||||
|
case R.id.careportal_mealbolus:
|
||||||
|
data.put("eventType", "Meal Bolus");
|
||||||
|
break;
|
||||||
|
case R.id.careportal_note:
|
||||||
|
data.put("eventType", "Note");
|
||||||
|
break;
|
||||||
|
case R.id.careportal_profileswitch:
|
||||||
|
data.put("eventType", "Profile Switch");
|
||||||
|
break;
|
||||||
|
case R.id.careportal_pumpsitechange:
|
||||||
|
data.put("eventType", "Site Change");
|
||||||
|
break;
|
||||||
|
case R.id.careportal_question:
|
||||||
|
data.put("eventType", "Question");
|
||||||
|
break;
|
||||||
|
case R.id.careportal_snackbolus:
|
||||||
|
data.put("eventType", "Snack Bolus");
|
||||||
|
break;
|
||||||
|
case R.id.careportal_tempbasalstart:
|
||||||
|
data.put("eventType", "Temp Basal");
|
||||||
|
break;
|
||||||
|
case R.id.careportal_tempbasalend:
|
||||||
|
data.put("eventType", "Temp Basal");
|
||||||
|
break;
|
||||||
|
case R.id.careportal_openapsoffline:
|
||||||
|
data.put("eventType", "OpenAPS Offline");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (SafeParse.stringToDouble(bgInputEdit.getText().toString()) != 0d) {
|
||||||
|
data.put("glucose", SafeParse.stringToDouble(bgInputEdit.getText().toString()));
|
||||||
|
if (meterRadioButton.isChecked()) data.put("glucoseType", "Finger");
|
||||||
|
if (sensorRadioButton.isChecked()) data.put("glucoseType", "Sensor");
|
||||||
|
if (otherRadioButton.isChecked()) data.put("glucoseType", "Manual");
|
||||||
|
}
|
||||||
|
if (SafeParse.stringToDouble(carbsEdit.getText().toString()) != 0d)
|
||||||
|
data.put("carbs", SafeParse.stringToDouble(carbsEdit.getText().toString()));
|
||||||
|
if (SafeParse.stringToDouble(insulinEdit.getText().toString()) != 0d)
|
||||||
|
data.put("insulin", SafeParse.stringToDouble(insulinEdit.getText().toString()));
|
||||||
|
if (SafeParse.stringToDouble(durationeEdit.getText().toString()) != 0d)
|
||||||
|
data.put("duration", SafeParse.stringToDouble(durationeEdit.getText().toString()));
|
||||||
|
if (layoutPercent.getVisibility() != View.GONE)
|
||||||
|
data.put("percent", SafeParse.stringToDouble(percentEdit.getText().toString()));
|
||||||
|
if (layoutAbsolute.getVisibility() != View.GONE)
|
||||||
|
data.put("absolute", SafeParse.stringToDouble(absoluteEdit.getText().toString()));
|
||||||
|
if (options.profile && profileSpinner.getSelectedItem() != null)
|
||||||
|
data.put("profile", profileSpinner.getSelectedItem().toString());
|
||||||
|
if (SafeParse.stringToDouble(carbTimeEdit.getText().toString()) != 0d)
|
||||||
|
data.put("preBolus", SafeParse.stringToDouble(carbTimeEdit.getText().toString()));
|
||||||
|
if (!notesEdit.getText().toString().equals(""))
|
||||||
|
data.put("notes", notesEdit.getText().toString());
|
||||||
|
data.put("units", units);
|
||||||
|
if (!enteredBy.equals("")) data.put("enteredBy", enteredBy);
|
||||||
|
if (options.eventType == R.id.careportal_combobolus) {
|
||||||
|
Double enteredInsulin = SafeParse.stringToDouble(insulinEdit.getText().toString());
|
||||||
|
data.put("enteredinsulin", enteredInsulin);
|
||||||
|
data.put("insulin", enteredInsulin * SafeParse.stringToDouble(splitEdit.getText().toString()) / 100);
|
||||||
|
data.put("relative", enteredInsulin * (100 - SafeParse.stringToDouble(splitEdit.getText().toString())) / 100 / SafeParse.stringToDouble(durationeEdit.getText().toString()) * 60);
|
||||||
|
}
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
String buildConfirmText(JSONObject data) {
|
||||||
|
String ret = "";
|
||||||
|
try {
|
||||||
|
if (data.has("eventType")) {
|
||||||
|
ret += getString(R.string.careportal_newnstreatment_eventtype);
|
||||||
|
ret += ": ";
|
||||||
|
ret += Translator.translate(data.getString("eventType"));
|
||||||
|
ret += "\n";
|
||||||
|
}
|
||||||
|
if (data.has("glucose")) {
|
||||||
|
ret += getString(R.string.treatments_wizard_bg_label);
|
||||||
|
ret += ": ";
|
||||||
|
ret += data.get("glucose");
|
||||||
|
ret += " " + units + "\n";
|
||||||
|
}
|
||||||
|
if (data.has("glucoseType")) {
|
||||||
|
ret += getString(R.string.careportal_newnstreatment_glucosetype);
|
||||||
|
ret += ": ";
|
||||||
|
ret += Translator.translate(data.getString("glucoseType"));
|
||||||
|
ret += "\n";
|
||||||
|
}
|
||||||
|
if (data.has("carbs")) {
|
||||||
|
ret += getString(R.string.careportal_newnstreatment_carbs_label);
|
||||||
|
ret += ": ";
|
||||||
|
ret += data.get("carbs");
|
||||||
|
ret += " g\n";
|
||||||
|
}
|
||||||
|
if (data.has("insulin")) {
|
||||||
|
ret += getString(R.string.careportal_newnstreatment_insulin_label);
|
||||||
|
ret += ": ";
|
||||||
|
ret += data.get("insulin");
|
||||||
|
ret += " U\n";
|
||||||
|
}
|
||||||
|
if (data.has("duration")) {
|
||||||
|
ret += getString(R.string.careportal_newnstreatment_duration_label);
|
||||||
|
ret += ": ";
|
||||||
|
ret += data.get("duration");
|
||||||
|
ret += " min\n";
|
||||||
|
}
|
||||||
|
if (data.has("percent")) {
|
||||||
|
ret += getString(R.string.careportal_newnstreatment_percent_label);
|
||||||
|
ret += ": ";
|
||||||
|
ret += data.get("percent");
|
||||||
|
ret += " %\n";
|
||||||
|
}
|
||||||
|
if (data.has("absolute")) {
|
||||||
|
ret += getString(R.string.careportal_newnstreatment_absolute_label);
|
||||||
|
ret += ": ";
|
||||||
|
ret += data.get("absolute");
|
||||||
|
ret += " U/h\n";
|
||||||
|
}
|
||||||
|
if (data.has("preBolus")) {
|
||||||
|
ret += getString(R.string.careportal_newnstreatment_carbtime_label);
|
||||||
|
ret += ": ";
|
||||||
|
ret += data.get("preBolus");
|
||||||
|
ret += " min\n";
|
||||||
|
}
|
||||||
|
if (data.has("notes")) {
|
||||||
|
ret += getString(R.string.careportal_newnstreatment_notes_label);
|
||||||
|
ret += ": ";
|
||||||
|
ret += data.get("notes");
|
||||||
|
ret += "\n";
|
||||||
|
}
|
||||||
|
if (data.has("profile")) {
|
||||||
|
ret += getString(R.string.careportal_newnstreatment_profile_label);
|
||||||
|
ret += ": ";
|
||||||
|
ret += data.get("profile");
|
||||||
|
ret += "\n";
|
||||||
|
}
|
||||||
|
if (data.has("created_at")) {
|
||||||
|
ret += getString(R.string.careportal_newnstreatment_eventtime_label);
|
||||||
|
ret += ": ";
|
||||||
|
ret += eventTime.toLocaleString();
|
||||||
|
ret += "\n";
|
||||||
|
}
|
||||||
|
if (data.has("enteredBy")) {
|
||||||
|
ret += getString(R.string.careportal_newnstreatment_enteredby_title);
|
||||||
|
ret += ": ";
|
||||||
|
ret += data.get("enteredBy");
|
||||||
|
ret += "\n";
|
||||||
|
}
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void createNSTreatment() {
|
||||||
|
final JSONObject data = gatherData();
|
||||||
|
String confirmText = buildConfirmText(data);
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
|
||||||
|
builder.setTitle(getContext().getString(R.string.confirmation));
|
||||||
|
builder.setMessage(confirmText);
|
||||||
|
builder.setPositiveButton(getContext().getString(R.string.ok), new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
|
ConfigBuilderPlugin.uploadCareportalEntryToNS(data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
builder.setNegativeButton(getContext().getString(R.string.cancel), null);
|
||||||
|
builder.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,306 @@
|
||||||
|
package info.nightscout.androidaps.plugins.ConfigBuilder;
|
||||||
|
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
import android.support.v4.app.Fragment;
|
||||||
|
import android.support.v7.app.AppCompatActivity;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ArrayAdapter;
|
||||||
|
import android.widget.CheckBox;
|
||||||
|
import android.widget.ListAdapter;
|
||||||
|
import android.widget.ListView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
import info.nightscout.androidaps.R;
|
||||||
|
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.PluginBase;
|
||||||
|
import info.nightscout.androidaps.interfaces.ProfileInterface;
|
||||||
|
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||||
|
import info.nightscout.androidaps.interfaces.TempBasalsInterface;
|
||||||
|
import info.nightscout.androidaps.interfaces.TreatmentsInterface;
|
||||||
|
import info.nightscout.androidaps.plugins.Loop.LoopFragment;
|
||||||
|
|
||||||
|
|
||||||
|
public class ConfigBuilderFragment extends Fragment implements FragmentBase {
|
||||||
|
|
||||||
|
static ConfigBuilderPlugin configBuilderPlugin = new ConfigBuilderPlugin();
|
||||||
|
|
||||||
|
static public ConfigBuilderPlugin getPlugin() {
|
||||||
|
return configBuilderPlugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
ListView bgsourceListView;
|
||||||
|
ListView pumpListView;
|
||||||
|
ListView loopListView;
|
||||||
|
TextView loopLabel;
|
||||||
|
ListView treatmentsListView;
|
||||||
|
ListView tempsListView;
|
||||||
|
ListView profileListView;
|
||||||
|
ListView apsListView;
|
||||||
|
TextView apsLabel;
|
||||||
|
ListView constraintsListView;
|
||||||
|
ListView generalListView;
|
||||||
|
TextView nsclientVerView;
|
||||||
|
TextView nightscoutVerView;
|
||||||
|
|
||||||
|
PluginCustomAdapter bgsourceDataAdapter = null;
|
||||||
|
PluginCustomAdapter pumpDataAdapter = null;
|
||||||
|
PluginCustomAdapter loopDataAdapter = null;
|
||||||
|
PluginCustomAdapter treatmentsDataAdapter = null;
|
||||||
|
PluginCustomAdapter tempsDataAdapter = null;
|
||||||
|
PluginCustomAdapter profileDataAdapter = null;
|
||||||
|
PluginCustomAdapter apsDataAdapter = null;
|
||||||
|
PluginCustomAdapter constraintsDataAdapter = null;
|
||||||
|
PluginCustomAdapter generalDataAdapter = null;
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: sorting
|
||||||
|
// TODO: Toast and sound when command failed
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
|
Bundle savedInstanceState) {
|
||||||
|
View view = inflater.inflate(R.layout.configbuilder_fragment, container, false);
|
||||||
|
bgsourceListView = (ListView) view.findViewById(R.id.configbuilder_bgsourcelistview);
|
||||||
|
pumpListView = (ListView) view.findViewById(R.id.configbuilder_pumplistview);
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
generalListView = (ListView) view.findViewById(R.id.configbuilder_generallistview);
|
||||||
|
nsclientVerView = (TextView) view.findViewById(R.id.configbuilder_nsclientversion);
|
||||||
|
nightscoutVerView = (TextView) view.findViewById(R.id.configbuilder_nightscoutversion);
|
||||||
|
|
||||||
|
nsclientVerView.setText(ConfigBuilderPlugin.nsClientVersionName);
|
||||||
|
nightscoutVerView.setText(ConfigBuilderPlugin.nightscoutVersionName);
|
||||||
|
if (ConfigBuilderPlugin.nsClientVersionCode < 117) nsclientVerView.setTextColor(Color.RED);
|
||||||
|
if (ConfigBuilderPlugin.nightscoutVersionCode < 900) nightscoutVerView.setTextColor(Color.RED);
|
||||||
|
setViews();
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setViews() {
|
||||||
|
bgsourceDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsListByInterface(BgSourceInterface.class), PluginBase.BGSOURCE);
|
||||||
|
bgsourceListView.setAdapter(bgsourceDataAdapter);
|
||||||
|
setListViewHeightBasedOnChildren(bgsourceListView);
|
||||||
|
pumpDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsList(PluginBase.PUMP), PluginBase.PUMP);
|
||||||
|
pumpListView.setAdapter(pumpDataAdapter);
|
||||||
|
setListViewHeightBasedOnChildren(pumpListView);
|
||||||
|
loopDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsList(PluginBase.LOOP), PluginBase.LOOP);
|
||||||
|
loopListView.setAdapter(loopDataAdapter);
|
||||||
|
setListViewHeightBasedOnChildren(loopListView);
|
||||||
|
if (MainApp.getSpecificPluginsList(PluginBase.LOOP).size() == 0)
|
||||||
|
loopLabel.setVisibility(View.GONE);
|
||||||
|
treatmentsDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsList(PluginBase.TREATMENT), PluginBase.TREATMENT);
|
||||||
|
treatmentsListView.setAdapter(treatmentsDataAdapter);
|
||||||
|
setListViewHeightBasedOnChildren(treatmentsListView);
|
||||||
|
tempsDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsList(PluginBase.TEMPBASAL), PluginBase.TEMPBASAL);
|
||||||
|
tempsListView.setAdapter(tempsDataAdapter);
|
||||||
|
setListViewHeightBasedOnChildren(tempsListView);
|
||||||
|
profileDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsListByInterface(ProfileInterface.class), PluginBase.PROFILE);
|
||||||
|
profileListView.setAdapter(profileDataAdapter);
|
||||||
|
setListViewHeightBasedOnChildren(profileListView);
|
||||||
|
apsDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsList(PluginBase.APS), PluginBase.APS);
|
||||||
|
apsListView.setAdapter(apsDataAdapter);
|
||||||
|
setListViewHeightBasedOnChildren(apsListView);
|
||||||
|
if (MainApp.getSpecificPluginsList(PluginBase.APS).size() == 0)
|
||||||
|
apsLabel.setVisibility(View.GONE);
|
||||||
|
constraintsDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class), PluginBase.CONSTRAINTS);
|
||||||
|
constraintsListView.setAdapter(constraintsDataAdapter);
|
||||||
|
setListViewHeightBasedOnChildren(constraintsListView);
|
||||||
|
generalDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsList(PluginBase.GENERAL), PluginBase.GENERAL);
|
||||||
|
generalListView.setAdapter(generalDataAdapter);
|
||||||
|
setListViewHeightBasedOnChildren(generalListView);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ConfigBuilderFragment code
|
||||||
|
*/
|
||||||
|
|
||||||
|
private class PluginCustomAdapter extends ArrayAdapter<PluginBase> {
|
||||||
|
|
||||||
|
private ArrayList<PluginBase> pluginList;
|
||||||
|
final private int type;
|
||||||
|
|
||||||
|
public PluginCustomAdapter(Context context, int textViewResourceId,
|
||||||
|
ArrayList<PluginBase> pluginList, int type) {
|
||||||
|
super(context, textViewResourceId, pluginList);
|
||||||
|
this.pluginList = new ArrayList<PluginBase>();
|
||||||
|
this.pluginList.addAll(pluginList);
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class PluginViewHolder {
|
||||||
|
TextView name;
|
||||||
|
CheckBox checkboxEnabled;
|
||||||
|
CheckBox checkboxVisible;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View getView(int position, View convertView, ViewGroup parent) {
|
||||||
|
|
||||||
|
PluginViewHolder holder = null;
|
||||||
|
|
||||||
|
if (convertView == null) {
|
||||||
|
convertView = 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.checkboxEnabled.setOnClickListener(new View.OnClickListener() {
|
||||||
|
public void onClick(View v) {
|
||||||
|
CheckBox cb = (CheckBox) v;
|
||||||
|
PluginBase plugin = (PluginBase) cb.getTag();
|
||||||
|
plugin.setFragmentEnabled(type, cb.isChecked());
|
||||||
|
plugin.setFragmentVisible(type, cb.isChecked());
|
||||||
|
onEnabledCategoryChanged(plugin, type);
|
||||||
|
configBuilderPlugin.storeSettings();
|
||||||
|
MainApp.bus().post(new EventRefreshGui());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
holder.checkboxVisible.setOnClickListener(new View.OnClickListener() {
|
||||||
|
public void onClick(View v) {
|
||||||
|
CheckBox cb = (CheckBox) v;
|
||||||
|
PluginBase plugin = (PluginBase) cb.getTag();
|
||||||
|
plugin.setFragmentVisible(type, cb.isChecked());
|
||||||
|
configBuilderPlugin.storeSettings();
|
||||||
|
MainApp.bus().post(new EventRefreshGui());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
holder = (PluginViewHolder) convertView.getTag();
|
||||||
|
}
|
||||||
|
|
||||||
|
PluginBase plugin = pluginList.get(position);
|
||||||
|
holder.name.setText(plugin.getName());
|
||||||
|
holder.checkboxEnabled.setChecked(plugin.isEnabled(type));
|
||||||
|
holder.checkboxVisible.setChecked(plugin.isVisibleInTabs(type));
|
||||||
|
holder.name.setTag(plugin);
|
||||||
|
holder.checkboxEnabled.setTag(plugin);
|
||||||
|
holder.checkboxVisible.setTag(plugin);
|
||||||
|
|
||||||
|
if (!plugin.canBeHidden(type)) {
|
||||||
|
holder.checkboxEnabled.setEnabled(false);
|
||||||
|
holder.checkboxVisible.setEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
int type = plugin.getType();
|
||||||
|
// Force enabled if there is only one plugin
|
||||||
|
if (type == PluginBase.PUMP || type == PluginBase.TREATMENT || type == PluginBase.TEMPBASAL || type == PluginBase.PROFILE)
|
||||||
|
if (pluginList.size() < 2)
|
||||||
|
holder.checkboxEnabled.setEnabled(false);
|
||||||
|
|
||||||
|
// Constraints cannot be disabled
|
||||||
|
if (type == PluginBase.CONSTRAINTS)
|
||||||
|
holder.checkboxEnabled.setEnabled(false);
|
||||||
|
|
||||||
|
// Hide disabled profiles by default
|
||||||
|
if (type == PluginBase.PROFILE) {
|
||||||
|
if (!plugin.isEnabled(type)) {
|
||||||
|
holder.checkboxVisible.setEnabled(false);
|
||||||
|
holder.checkboxVisible.setChecked(false);
|
||||||
|
} else {
|
||||||
|
holder.checkboxVisible.setEnabled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return convertView;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void onEnabledCategoryChanged(PluginBase changedPlugin, int type) {
|
||||||
|
int category = changedPlugin.getType();
|
||||||
|
ArrayList<PluginBase> pluginsInCategory = null;
|
||||||
|
switch (category) {
|
||||||
|
// Multiple selection allowed
|
||||||
|
case PluginBase.GENERAL:
|
||||||
|
case PluginBase.CONSTRAINTS:
|
||||||
|
case PluginBase.LOOP:
|
||||||
|
break;
|
||||||
|
// Single selection allowed
|
||||||
|
case PluginBase.APS:
|
||||||
|
pluginsInCategory = MainApp.getSpecificPluginsListByInterface(APSInterface.class);
|
||||||
|
break;
|
||||||
|
case PluginBase.PROFILE:
|
||||||
|
pluginsInCategory = MainApp.getSpecificPluginsListByInterface(ProfileInterface.class);
|
||||||
|
break;
|
||||||
|
case PluginBase.BGSOURCE:
|
||||||
|
pluginsInCategory = MainApp.getSpecificPluginsListByInterface(BgSourceInterface.class);
|
||||||
|
break;
|
||||||
|
case PluginBase.TEMPBASAL:
|
||||||
|
case PluginBase.TREATMENT:
|
||||||
|
case PluginBase.PUMP:
|
||||||
|
pluginsInCategory = MainApp.getSpecificPluginsList(category);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (pluginsInCategory != null) {
|
||||||
|
boolean newSelection = changedPlugin.isEnabled(type);
|
||||||
|
if (newSelection) { // new plugin selected -> disable others
|
||||||
|
for (PluginBase p : pluginsInCategory) {
|
||||||
|
if (p.getName().equals(changedPlugin.getName())) {
|
||||||
|
// this is new selected
|
||||||
|
} else {
|
||||||
|
p.setFragmentEnabled(type, false);
|
||||||
|
p.setFragmentVisible(type, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else { // enable first plugin in list
|
||||||
|
pluginsInCategory.get(0).setFragmentEnabled(type, true);
|
||||||
|
}
|
||||||
|
setViews();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/****
|
||||||
|
* Method for Setting the Height of the ListView dynamically.
|
||||||
|
* *** Hack to fix the issue of not showing all the items of the ListView
|
||||||
|
* *** when placed inside a ScrollView
|
||||||
|
****/
|
||||||
|
public static void setListViewHeightBasedOnChildren(ListView listView) {
|
||||||
|
ListAdapter listAdapter = listView.getAdapter();
|
||||||
|
if (listAdapter == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int desiredWidth = View.MeasureSpec.makeMeasureSpec(listView.getWidth(), View.MeasureSpec.UNSPECIFIED);
|
||||||
|
int totalHeight = 0;
|
||||||
|
View view = null;
|
||||||
|
for (int i = 0; i < listAdapter.getCount(); i++) {
|
||||||
|
view = listAdapter.getView(i, view, listView);
|
||||||
|
if (i == 0)
|
||||||
|
view.setLayoutParams(new ViewGroup.LayoutParams(desiredWidth, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||||
|
|
||||||
|
view.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED);
|
||||||
|
totalHeight += view.getMeasuredHeight();
|
||||||
|
}
|
||||||
|
ViewGroup.LayoutParams params = listView.getLayoutParams();
|
||||||
|
params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
|
||||||
|
listView.setLayoutParams(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,903 @@
|
||||||
|
package info.nightscout.androidaps.plugins.ConfigBuilder;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.PowerManager;
|
||||||
|
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;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.Config;
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
import info.nightscout.androidaps.R;
|
||||||
|
import info.nightscout.androidaps.Services.Intents;
|
||||||
|
import info.nightscout.androidaps.data.PumpEnactResult;
|
||||||
|
import info.nightscout.androidaps.db.TempBasal;
|
||||||
|
import info.nightscout.androidaps.db.Treatment;
|
||||||
|
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.PluginBase;
|
||||||
|
import info.nightscout.androidaps.interfaces.ProfileInterface;
|
||||||
|
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||||
|
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.DeviceStatus;
|
||||||
|
import info.nightscout.androidaps.plugins.Loop.LoopPlugin;
|
||||||
|
import info.nightscout.androidaps.plugins.OpenAPSMA.DetermineBasalResult;
|
||||||
|
import info.nightscout.androidaps.plugins.Overview.Dialogs.BolusProgressDialog;
|
||||||
|
import info.nightscout.androidaps.plugins.Overview.Dialogs.NewExtendedBolusDialog;
|
||||||
|
import info.nightscout.client.data.DbLogger;
|
||||||
|
import info.nightscout.client.data.NSProfile;
|
||||||
|
import info.nightscout.utils.DateUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 05.08.2016.
|
||||||
|
*/
|
||||||
|
public class ConfigBuilderPlugin implements PluginBase, PumpInterface, ConstraintsInterface {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(ConfigBuilderPlugin.class);
|
||||||
|
|
||||||
|
static BgSourceInterface activeBgSource;
|
||||||
|
static PumpInterface activePump;
|
||||||
|
static ProfileInterface activeProfile;
|
||||||
|
static TreatmentsInterface activeTreatments;
|
||||||
|
static TempBasalsInterface activeTempBasals;
|
||||||
|
static APSInterface activeAPS;
|
||||||
|
static LoopPlugin activeLoop;
|
||||||
|
|
||||||
|
static public String nightscoutVersionName = "";
|
||||||
|
static public Integer nightscoutVersionCode = 0;
|
||||||
|
static public String nsClientVersionName = "";
|
||||||
|
static public Integer nsClientVersionCode = 0;
|
||||||
|
|
||||||
|
static ArrayList<PluginBase> pluginList;
|
||||||
|
|
||||||
|
static Date lastDeviceStatusUpload = new Date(0);
|
||||||
|
|
||||||
|
PowerManager.WakeLock mWakeLock;
|
||||||
|
|
||||||
|
public ConfigBuilderPlugin() {
|
||||||
|
MainApp.bus().register(this);
|
||||||
|
PowerManager powerManager = (PowerManager) MainApp.instance().getApplicationContext().getSystemService(Context.POWER_SERVICE);
|
||||||
|
mWakeLock = powerManager.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "ConfigBuilderPlugin");;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getType() {
|
||||||
|
return PluginBase.GENERAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getFragmentClass() {
|
||||||
|
return ConfigBuilderFragment.class.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return MainApp.instance().getString(R.string.configbuilder);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEnabled(int type) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isVisibleInTabs(int type) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canBeHidden(int type) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
|
||||||
|
// Always enabled
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFragmentVisible(int type, boolean fragmentVisible) {
|
||||||
|
// Always visible
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initialize() {
|
||||||
|
pluginList = MainApp.getPluginsList();
|
||||||
|
loadSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void storeSettings() {
|
||||||
|
if (pluginList != null) {
|
||||||
|
if (Config.logPrefsChange)
|
||||||
|
log.debug("Storing settings");
|
||||||
|
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
|
||||||
|
SharedPreferences.Editor editor = settings.edit();
|
||||||
|
|
||||||
|
for (int type = 1; type < PluginBase.LAST; type++) {
|
||||||
|
for (PluginBase p : pluginList) {
|
||||||
|
String settingEnabled = "ConfigBuilder_" + type + "_" + p.getClass().getSimpleName() + "_Enabled";
|
||||||
|
String settingVisible = "ConfigBuilder_" + type + "_" + p.getClass().getSimpleName() + "_Visible";
|
||||||
|
editor.putBoolean(settingEnabled, p.isEnabled(type));
|
||||||
|
editor.putBoolean(settingVisible, p.isVisibleInTabs(type));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
editor.apply();
|
||||||
|
verifySelectionInCategories();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadSettings() {
|
||||||
|
if (Config.logPrefsChange)
|
||||||
|
log.debug("Loading stored settings");
|
||||||
|
SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
|
||||||
|
for (int type = 1; type < PluginBase.LAST; type++) {
|
||||||
|
for (PluginBase p : pluginList) {
|
||||||
|
try {
|
||||||
|
String settingEnabled = "ConfigBuilder_" + type + "_" + p.getClass().getSimpleName() + "_Enabled";
|
||||||
|
String settingVisible = "ConfigBuilder_" + type + "_" + p.getClass().getSimpleName() + "_Visible";
|
||||||
|
if (SP.contains(settingEnabled))
|
||||||
|
p.setFragmentEnabled(type, SP.getBoolean(settingEnabled, true));
|
||||||
|
if (SP.contains(settingVisible))
|
||||||
|
p.setFragmentVisible(type, SP.getBoolean(settingVisible, true));
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
verifySelectionInCategories();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BgSourceInterface getActiveBgSource() {
|
||||||
|
return activeBgSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static ProfileInterface getActiveProfile() {
|
||||||
|
return activeProfile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TreatmentsInterface getActiveTreatments() {
|
||||||
|
return activeTreatments;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TempBasalsInterface getActiveTempBasals() {
|
||||||
|
return activeTempBasals;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static APSInterface getActiveAPS() {
|
||||||
|
return activeAPS;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LoopPlugin getActiveLoop() {
|
||||||
|
return activeLoop;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void verifySelectionInCategories() {
|
||||||
|
ArrayList<PluginBase> pluginsInCategory;
|
||||||
|
|
||||||
|
// PluginBase.APS
|
||||||
|
pluginsInCategory = MainApp.getSpecificPluginsListByInterface(APSInterface.class);
|
||||||
|
activeAPS = (APSInterface) getTheOneEnabledInArray(pluginsInCategory, PluginBase.APS);
|
||||||
|
if (activeAPS != null) {
|
||||||
|
if (Config.logConfigBuilder)
|
||||||
|
log.debug("Selected APS interface: " + ((PluginBase) activeAPS).getName());
|
||||||
|
for (PluginBase p : pluginsInCategory) {
|
||||||
|
if (!p.getName().equals(((PluginBase) activeAPS).getName())) {
|
||||||
|
p.setFragmentVisible(PluginBase.APS, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PluginBase.PROFILE
|
||||||
|
pluginsInCategory = MainApp.getSpecificPluginsListByInterface(ProfileInterface.class);
|
||||||
|
activeProfile = (ProfileInterface) getTheOneEnabledInArray(pluginsInCategory, PluginBase.PROFILE);
|
||||||
|
if (Config.logConfigBuilder)
|
||||||
|
log.debug("Selected profile interface: " + ((PluginBase) activeProfile).getName());
|
||||||
|
for (PluginBase p : pluginsInCategory) {
|
||||||
|
if (!p.getName().equals(((PluginBase) activeProfile).getName())) {
|
||||||
|
p.setFragmentVisible(PluginBase.PROFILE, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PluginBase.BGSOURCE
|
||||||
|
pluginsInCategory = MainApp.getSpecificPluginsListByInterface(BgSourceInterface.class);
|
||||||
|
activeBgSource = (BgSourceInterface) getTheOneEnabledInArray(pluginsInCategory, PluginBase.BGSOURCE);
|
||||||
|
if (Config.logConfigBuilder)
|
||||||
|
log.debug("Selected bgSource interface: " + ((PluginBase) activeBgSource).getName());
|
||||||
|
for (PluginBase p : pluginsInCategory) {
|
||||||
|
if (!p.getName().equals(((PluginBase) activeBgSource).getName())) {
|
||||||
|
p.setFragmentVisible(PluginBase.BGSOURCE, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PluginBase.PUMP
|
||||||
|
pluginsInCategory = MainApp.getSpecificPluginsList(PluginBase.PUMP);
|
||||||
|
activePump = (PumpInterface) getTheOneEnabledInArray(pluginsInCategory, PluginBase.PUMP);
|
||||||
|
if (Config.logConfigBuilder)
|
||||||
|
log.debug("Selected pump interface: " + ((PluginBase) activePump).getName());
|
||||||
|
for (PluginBase p : pluginsInCategory) {
|
||||||
|
if (!p.getName().equals(((PluginBase) activePump).getName())) {
|
||||||
|
p.setFragmentVisible(PluginBase.PUMP, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PluginBase.LOOP
|
||||||
|
pluginsInCategory = MainApp.getSpecificPluginsList(PluginBase.LOOP);
|
||||||
|
activeLoop = (LoopPlugin) getTheOneEnabledInArray(pluginsInCategory, PluginBase.LOOP);
|
||||||
|
if (activeLoop != null) {
|
||||||
|
if (Config.logConfigBuilder)
|
||||||
|
log.debug("Selected loop interface: " + activeLoop.getName());
|
||||||
|
for (PluginBase p : pluginsInCategory) {
|
||||||
|
if (!p.getName().equals(activeLoop.getName())) {
|
||||||
|
p.setFragmentVisible(PluginBase.LOOP, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PluginBase.TEMPBASAL
|
||||||
|
pluginsInCategory = MainApp.getSpecificPluginsList(PluginBase.TEMPBASAL);
|
||||||
|
activeTempBasals = (TempBasalsInterface) getTheOneEnabledInArray(pluginsInCategory, PluginBase.TEMPBASAL);
|
||||||
|
if (Config.logConfigBuilder)
|
||||||
|
log.debug("Selected tempbasal interface: " + ((PluginBase) activeTempBasals).getName());
|
||||||
|
for (PluginBase p : pluginsInCategory) {
|
||||||
|
if (!p.getName().equals(((PluginBase) activeTempBasals).getName())) {
|
||||||
|
p.setFragmentVisible(PluginBase.TEMPBASAL, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PluginBase.TREATMENT
|
||||||
|
pluginsInCategory = MainApp.getSpecificPluginsList(PluginBase.TREATMENT);
|
||||||
|
activeTreatments = (TreatmentsInterface) getTheOneEnabledInArray(pluginsInCategory, PluginBase.TREATMENT);
|
||||||
|
if (Config.logConfigBuilder)
|
||||||
|
log.debug("Selected treatment interface: " + ((PluginBase) activeTreatments).getName());
|
||||||
|
for (PluginBase p : pluginsInCategory) {
|
||||||
|
if (!p.getName().equals(((PluginBase) activeTreatments).getName())) {
|
||||||
|
p.setFragmentVisible(PluginBase.TREATMENT, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private PluginBase getTheOneEnabledInArray(ArrayList<PluginBase> pluginsInCategory, int type) {
|
||||||
|
PluginBase found = null;
|
||||||
|
for (PluginBase p : pluginsInCategory) {
|
||||||
|
if (p.isEnabled(type) && found == null) {
|
||||||
|
found = p;
|
||||||
|
} else if (p.isEnabled(type)) {
|
||||||
|
// set others disabled
|
||||||
|
p.setFragmentEnabled(type, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If none enabled, enable first one
|
||||||
|
if (found == null && pluginsInCategory.size() > 0)
|
||||||
|
found = pluginsInCategory.get(0);
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pump interface
|
||||||
|
*
|
||||||
|
* Config builder return itself as a pump and check constraints before it passes command to pump driver
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean isTempBasalInProgress() {
|
||||||
|
return activePump.isTempBasalInProgress();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isExtendedBoluslInProgress() {
|
||||||
|
return activePump.isExtendedBoluslInProgress();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setNewBasalProfile(NSProfile profile) {
|
||||||
|
activePump.setNewBasalProfile(profile);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getBaseBasalRate() {
|
||||||
|
return activePump.getBaseBasalRate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getTempBasalAbsoluteRate() {
|
||||||
|
return activePump.getTempBasalAbsoluteRate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getTempBasalRemainingMinutes() {
|
||||||
|
return activePump.getTempBasalRemainingMinutes();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TempBasal getTempBasal(Date time) {
|
||||||
|
return activePump.getTempBasal(time);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TempBasal getTempBasal() {
|
||||||
|
return activePump.getTempBasal();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TempBasal getExtendedBolus() {
|
||||||
|
return activePump.getExtendedBolus();
|
||||||
|
}
|
||||||
|
|
||||||
|
public PumpEnactResult deliverTreatmentFromBolusWizard(Context context, Double insulin, Integer carbs, Double glucose, String glucoseType, int carbTime, JSONObject boluscalc) {
|
||||||
|
mWakeLock.acquire();
|
||||||
|
insulin = applyBolusConstraints(insulin);
|
||||||
|
carbs = applyCarbsConstraints(carbs);
|
||||||
|
|
||||||
|
BolusProgressDialog bolusProgressDialog = null;
|
||||||
|
if (context != null) {
|
||||||
|
bolusProgressDialog = new BolusProgressDialog();
|
||||||
|
bolusProgressDialog.setInsulin(insulin);
|
||||||
|
bolusProgressDialog.show(((AppCompatActivity) context).getSupportFragmentManager(), "BolusProgress");
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
t.created_at = new Date();
|
||||||
|
t.mealBolus = result.carbsDelivered > 0;
|
||||||
|
try {
|
||||||
|
MainApp.getDbHelper().getDaoTreatments().create(t);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
t.setTimeIndex(t.getTimeIndex());
|
||||||
|
t.carbs = (double) result.carbsDelivered;
|
||||||
|
uploadBolusWizardRecord(t, glucose, glucoseType, carbTime, boluscalc);
|
||||||
|
MainApp.bus().post(new EventTreatmentChange());
|
||||||
|
}
|
||||||
|
mWakeLock.release();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PumpEnactResult deliverTreatment(Double insulin, Integer carbs, Context context) {
|
||||||
|
mWakeLock.acquire();
|
||||||
|
insulin = applyBolusConstraints(insulin);
|
||||||
|
carbs = applyCarbsConstraints(carbs);
|
||||||
|
|
||||||
|
BolusProgressDialog bolusProgressDialog = null;
|
||||||
|
if (context != null) {
|
||||||
|
bolusProgressDialog = new BolusProgressDialog();
|
||||||
|
bolusProgressDialog.setInsulin(insulin);
|
||||||
|
bolusProgressDialog.show(((AppCompatActivity) context).getSupportFragmentManager(), "BolusProgress");
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.logCongigBuilderActions)
|
||||||
|
log.debug("deliverTreatment insulin: " + insulin + " carbs: " + carbs + " success: " + result.success + " enacted: " + result.enacted + " bolusDelivered: " + result.bolusDelivered);
|
||||||
|
|
||||||
|
if (result.success) {
|
||||||
|
Treatment t = new Treatment();
|
||||||
|
t.insulin = result.bolusDelivered;
|
||||||
|
t.carbs = (double) result.carbsDelivered;
|
||||||
|
t.created_at = new Date();
|
||||||
|
t.mealBolus = t.carbs > 0;
|
||||||
|
try {
|
||||||
|
MainApp.getDbHelper().getDaoTreatments().create(t);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
t.setTimeIndex(t.getTimeIndex());
|
||||||
|
t.sendToNSClient();
|
||||||
|
MainApp.bus().post(new EventTreatmentChange());
|
||||||
|
}
|
||||||
|
mWakeLock.release();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stopBolusDelivering() {
|
||||||
|
activePump.stopBolusDelivering();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* apply constraints, set temp based on absolute valus and expecting absolute result
|
||||||
|
*
|
||||||
|
* @param absoluteRate
|
||||||
|
* @param durationInMinutes
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes) {
|
||||||
|
Double rateAfterConstraints = applyBasalConstraints(absoluteRate);
|
||||||
|
PumpEnactResult result = activePump.setTempBasalAbsolute(rateAfterConstraints, durationInMinutes);
|
||||||
|
if (Config.logCongigBuilderActions)
|
||||||
|
log.debug("setTempBasalAbsolute rate: " + rateAfterConstraints + " durationInMinutes: " + durationInMinutes + " success: " + result.success + " enacted: " + result.enacted);
|
||||||
|
if (result.enacted && result.success) {
|
||||||
|
if (result.isPercent) {
|
||||||
|
uploadTempBasalStartPercent(result.percent, result.duration);
|
||||||
|
} else {
|
||||||
|
uploadTempBasalStartAbsolute(result.absolute, result.duration);
|
||||||
|
}
|
||||||
|
MainApp.bus().post(new EventTempBasalChange());
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* apply constraints, set temp based on percent and expecting result in percent
|
||||||
|
*
|
||||||
|
* @param percent 0 ... 100 ...
|
||||||
|
* @param durationInMinutes
|
||||||
|
* @return result
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes) {
|
||||||
|
Integer percentAfterConstraints = applyBasalConstraints(percent);
|
||||||
|
PumpEnactResult result = activePump.setTempBasalPercent(percentAfterConstraints, durationInMinutes);
|
||||||
|
if (Config.logCongigBuilderActions)
|
||||||
|
log.debug("setTempBasalPercent percent: " + percentAfterConstraints + " durationInMinutes: " + durationInMinutes + " success: " + result.success + " enacted: " + result.enacted);
|
||||||
|
if (result.enacted && result.success) {
|
||||||
|
uploadTempBasalStartPercent(result.percent, result.duration);
|
||||||
|
MainApp.bus().post(new EventTempBasalChange());
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes) {
|
||||||
|
Double rateAfterConstraints = applyBolusConstraints(insulin);
|
||||||
|
PumpEnactResult result = activePump.setExtendedBolus(rateAfterConstraints, durationInMinutes);
|
||||||
|
if (Config.logCongigBuilderActions)
|
||||||
|
log.debug("setExtendedBolus rate: " + rateAfterConstraints + " durationInMinutes: " + durationInMinutes + " success: " + result.success + " enacted: " + result.enacted);
|
||||||
|
if (result.enacted && result.success) {
|
||||||
|
uploadExtendedBolus(result.bolusDelivered, result.duration);
|
||||||
|
MainApp.bus().post(new EventTreatmentChange());
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PumpEnactResult cancelTempBasal() {
|
||||||
|
PumpEnactResult result = activePump.cancelTempBasal();
|
||||||
|
if (Config.logCongigBuilderActions)
|
||||||
|
log.debug("cancelTempBasal success: " + result.success + " enacted: " + result.enacted);
|
||||||
|
if (result.enacted && result.success) {
|
||||||
|
uploadTempBasalEnd();
|
||||||
|
MainApp.bus().post(new EventTempBasalChange());
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PumpEnactResult cancelExtendedBolus() {
|
||||||
|
PumpEnactResult result = activePump.cancelExtendedBolus();
|
||||||
|
if (Config.logCongigBuilderActions)
|
||||||
|
log.debug("cancelExtendedBolus success: " + result.success + " enacted: " + result.enacted);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* expect absolute request and allow both absolute and percent response based on pump capabilities
|
||||||
|
*
|
||||||
|
* @param request
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public PumpEnactResult applyAPSRequest(APSResult request) {
|
||||||
|
request.rate = applyBasalConstraints(request.rate);
|
||||||
|
PumpEnactResult result;
|
||||||
|
|
||||||
|
if (Config.logCongigBuilderActions)
|
||||||
|
log.debug("applyAPSRequest: " + request.toString());
|
||||||
|
if ((request.rate == 0 && request.duration == 0) || Math.abs(request.rate - getBaseBasalRate()) < 0.1) {
|
||||||
|
if (isTempBasalInProgress()) {
|
||||||
|
if (Config.logCongigBuilderActions)
|
||||||
|
log.debug("applyAPSRequest: cancelTempBasal()");
|
||||||
|
result = cancelTempBasal();
|
||||||
|
} else {
|
||||||
|
result = new PumpEnactResult();
|
||||||
|
result.absolute = request.rate;
|
||||||
|
result.duration = 0;
|
||||||
|
result.enacted = false;
|
||||||
|
result.comment = "Basal set correctly";
|
||||||
|
result.success = true;
|
||||||
|
if (Config.logCongigBuilderActions)
|
||||||
|
log.debug("applyAPSRequest: Basal set correctly");
|
||||||
|
}
|
||||||
|
} else if (isTempBasalInProgress() && Math.abs(request.rate - getTempBasalAbsoluteRate()) < 0.1) {
|
||||||
|
result = new PumpEnactResult();
|
||||||
|
result.absolute = getTempBasalAbsoluteRate();
|
||||||
|
result.duration = activePump.getTempBasal().getPlannedRemainingMinutes();
|
||||||
|
result.enacted = false;
|
||||||
|
result.comment = "Temp basal set correctly";
|
||||||
|
result.success = true;
|
||||||
|
if (Config.logCongigBuilderActions)
|
||||||
|
log.debug("applyAPSRequest: Temp basal set correctly");
|
||||||
|
} else {
|
||||||
|
if (Config.logCongigBuilderActions)
|
||||||
|
log.debug("applyAPSRequest: setTempBasalAbsolute()");
|
||||||
|
result = setTempBasalAbsolute(request.rate, request.duration);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public JSONObject getJSONStatus() {
|
||||||
|
if (activePump != null)
|
||||||
|
return activePump.getJSONStatus();
|
||||||
|
else return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String deviceID() {
|
||||||
|
if (activePump != null)
|
||||||
|
return activePump.deviceID();
|
||||||
|
else return "Unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constraints interface
|
||||||
|
**/
|
||||||
|
@Override
|
||||||
|
public boolean isLoopEnabled() {
|
||||||
|
boolean result = true;
|
||||||
|
|
||||||
|
ArrayList<PluginBase> constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
|
||||||
|
for (PluginBase p : constraintsPlugins) {
|
||||||
|
ConstraintsInterface constrain = (ConstraintsInterface) p;
|
||||||
|
if (!p.isEnabled(PluginBase.CONSTRAINTS)) continue;
|
||||||
|
result = result && constrain.isLoopEnabled();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isClosedModeEnabled() {
|
||||||
|
boolean result = true;
|
||||||
|
|
||||||
|
ArrayList<PluginBase> constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
|
||||||
|
for (PluginBase p : constraintsPlugins) {
|
||||||
|
ConstraintsInterface constrain = (ConstraintsInterface) p;
|
||||||
|
if (!p.isEnabled(PluginBase.CONSTRAINTS)) continue;
|
||||||
|
result = result && constrain.isClosedModeEnabled();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAutosensModeEnabled() {
|
||||||
|
boolean result = true;
|
||||||
|
|
||||||
|
ArrayList<PluginBase> constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
|
||||||
|
for (PluginBase p : constraintsPlugins) {
|
||||||
|
ConstraintsInterface constrain = (ConstraintsInterface) p;
|
||||||
|
if (!p.isEnabled(PluginBase.CONSTRAINTS)) continue;
|
||||||
|
result = result && constrain.isAutosensModeEnabled();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAMAModeEnabled() {
|
||||||
|
boolean result = true;
|
||||||
|
|
||||||
|
ArrayList<PluginBase> constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
|
||||||
|
for (PluginBase p : constraintsPlugins) {
|
||||||
|
ConstraintsInterface constrain = (ConstraintsInterface) p;
|
||||||
|
if (!p.isEnabled(PluginBase.CONSTRAINTS)) continue;
|
||||||
|
result = result && constrain.isAMAModeEnabled();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Double applyBasalConstraints(Double absoluteRate) {
|
||||||
|
Double rateAfterConstrain = absoluteRate;
|
||||||
|
ArrayList<PluginBase> constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
|
||||||
|
for (PluginBase p : constraintsPlugins) {
|
||||||
|
ConstraintsInterface constrain = (ConstraintsInterface) p;
|
||||||
|
if (!p.isEnabled(PluginBase.CONSTRAINTS)) continue;
|
||||||
|
rateAfterConstrain = Math.min(constrain.applyBasalConstraints(absoluteRate), rateAfterConstrain);
|
||||||
|
}
|
||||||
|
return rateAfterConstrain;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer applyBasalConstraints(Integer percentRate) {
|
||||||
|
Integer rateAfterConstrain = percentRate;
|
||||||
|
ArrayList<PluginBase> constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
|
||||||
|
for (PluginBase p : constraintsPlugins) {
|
||||||
|
ConstraintsInterface constrain = (ConstraintsInterface) p;
|
||||||
|
if (!p.isEnabled(PluginBase.CONSTRAINTS)) continue;
|
||||||
|
rateAfterConstrain = Math.min(constrain.applyBasalConstraints(percentRate), rateAfterConstrain);
|
||||||
|
}
|
||||||
|
return rateAfterConstrain;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Double applyBolusConstraints(Double insulin) {
|
||||||
|
Double insulinAfterConstrain = insulin;
|
||||||
|
ArrayList<PluginBase> constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
|
||||||
|
for (PluginBase p : constraintsPlugins) {
|
||||||
|
ConstraintsInterface constrain = (ConstraintsInterface) p;
|
||||||
|
if (!p.isEnabled(PluginBase.CONSTRAINTS)) continue;
|
||||||
|
insulinAfterConstrain = Math.min(constrain.applyBolusConstraints(insulin), insulinAfterConstrain);
|
||||||
|
}
|
||||||
|
return insulinAfterConstrain;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer applyCarbsConstraints(Integer carbs) {
|
||||||
|
Integer carbsAfterConstrain = carbs;
|
||||||
|
ArrayList<PluginBase> constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
|
||||||
|
for (PluginBase p : constraintsPlugins) {
|
||||||
|
ConstraintsInterface constrain = (ConstraintsInterface) p;
|
||||||
|
if (!p.isEnabled(PluginBase.CONSTRAINTS)) continue;
|
||||||
|
carbsAfterConstrain = Math.min(constrain.applyCarbsConstraints(carbs), carbsAfterConstrain);
|
||||||
|
}
|
||||||
|
return carbsAfterConstrain;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Double applyMaxIOBConstraints(Double maxIob) {
|
||||||
|
Double maxIobAfterConstrain = maxIob;
|
||||||
|
ArrayList<PluginBase> constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
|
||||||
|
for (PluginBase p : constraintsPlugins) {
|
||||||
|
ConstraintsInterface constrain = (ConstraintsInterface) p;
|
||||||
|
if (!p.isEnabled(PluginBase.CONSTRAINTS)) continue;
|
||||||
|
maxIobAfterConstrain = Math.min(constrain.applyMaxIOBConstraints(maxIob), maxIobAfterConstrain);
|
||||||
|
}
|
||||||
|
return maxIobAfterConstrain;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onStatusEvent(final EventNewBG ev) {
|
||||||
|
Thread t = new Thread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
// Give some time to Loop
|
||||||
|
try {
|
||||||
|
Thread.sleep(120 * 1000L);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
// if status not uploaded, upload pump status only
|
||||||
|
if (new Date().getTime() - lastDeviceStatusUpload.getTime() > 120 * 1000L) {
|
||||||
|
uploadDeviceStatus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
t.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void uploadTempBasalStartAbsolute(Double absolute, double durationInMinutes) {
|
||||||
|
try {
|
||||||
|
Context context = MainApp.instance().getApplicationContext();
|
||||||
|
JSONObject data = new JSONObject();
|
||||||
|
data.put("eventType", "Temp Basal");
|
||||||
|
data.put("duration", durationInMinutes);
|
||||||
|
data.put("absolute", absolute);
|
||||||
|
data.put("created_at", DateUtil.toISOString(new Date()));
|
||||||
|
data.put("enteredBy", MainApp.instance().getString(R.string.app_name));
|
||||||
|
Bundle bundle = new Bundle();
|
||||||
|
bundle.putString("action", "dbAdd");
|
||||||
|
bundle.putString("collection", "treatments");
|
||||||
|
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);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void uploadTempBasalStartPercent(Integer percent, double durationInMinutes) {
|
||||||
|
try {
|
||||||
|
SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
|
||||||
|
boolean useAbsolute = SP.getBoolean("ns_sync_use_absolute", false);
|
||||||
|
if (useAbsolute) {
|
||||||
|
double absolute = getBaseBasalRate() * percent / 100d;
|
||||||
|
uploadTempBasalStartAbsolute(absolute, durationInMinutes);
|
||||||
|
} else {
|
||||||
|
Context context = MainApp.instance().getApplicationContext();
|
||||||
|
JSONObject data = new JSONObject();
|
||||||
|
data.put("eventType", "Temp Basal");
|
||||||
|
data.put("duration", durationInMinutes);
|
||||||
|
data.put("percent", percent - 100);
|
||||||
|
data.put("created_at", DateUtil.toISOString(new Date()));
|
||||||
|
data.put("enteredBy", MainApp.instance().getString(R.string.app_name));
|
||||||
|
Bundle bundle = new Bundle();
|
||||||
|
bundle.putString("action", "dbAdd");
|
||||||
|
bundle.putString("collection", "treatments");
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void uploadTempBasalEnd() {
|
||||||
|
try {
|
||||||
|
Context context = MainApp.instance().getApplicationContext();
|
||||||
|
JSONObject data = new JSONObject();
|
||||||
|
data.put("eventType", "Temp Basal");
|
||||||
|
data.put("created_at", DateUtil.toISOString(new Date()));
|
||||||
|
data.put("enteredBy", MainApp.instance().getString(R.string.app_name));
|
||||||
|
Bundle bundle = new Bundle();
|
||||||
|
bundle.putString("action", "dbAdd");
|
||||||
|
bundle.putString("collection", "treatments");
|
||||||
|
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);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void uploadExtendedBolus(Double insulin, double durationInMinutes) {
|
||||||
|
try {
|
||||||
|
Context context = MainApp.instance().getApplicationContext();
|
||||||
|
JSONObject data = new JSONObject();
|
||||||
|
data.put("eventType", "Combo Bolus");
|
||||||
|
data.put("duration", durationInMinutes);
|
||||||
|
data.put("splitNow", 0);
|
||||||
|
data.put("splitExt", 100);
|
||||||
|
data.put("enteredinsulin", insulin);
|
||||||
|
data.put("relative", insulin);
|
||||||
|
data.put("created_at", DateUtil.toISOString(new Date()));
|
||||||
|
data.put("enteredBy", MainApp.instance().getString(R.string.app_name));
|
||||||
|
Bundle bundle = new Bundle();
|
||||||
|
bundle.putString("action", "dbAdd");
|
||||||
|
bundle.putString("collection", "treatments");
|
||||||
|
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);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void uploadDeviceStatus() {
|
||||||
|
DeviceStatus deviceStatus = new DeviceStatus();
|
||||||
|
try {
|
||||||
|
LoopPlugin.LastRun lastRun = LoopPlugin.lastRun;
|
||||||
|
if (lastRun != null && lastRun.lastAPSRun.getTime() > new Date().getTime() - 60 * 1000L) {
|
||||||
|
// do not send if result is older than 1 min
|
||||||
|
APSResult apsResult = lastRun.request;
|
||||||
|
apsResult.json().put("timestamp", DateUtil.toISOString(lastRun.lastAPSRun));
|
||||||
|
deviceStatus.suggested = apsResult.json();
|
||||||
|
|
||||||
|
if (lastRun.request instanceof DetermineBasalResult) {
|
||||||
|
DetermineBasalResult result = (DetermineBasalResult) lastRun.request;
|
||||||
|
deviceStatus.iob = result.iob.json();
|
||||||
|
deviceStatus.iob.put("time", DateUtil.toISOString(lastRun.lastAPSRun));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastRun.setByPump != null && lastRun.setByPump.enacted) { // enacted
|
||||||
|
deviceStatus.enacted = lastRun.request.json();
|
||||||
|
deviceStatus.enacted.put("rate", lastRun.setByPump.json().get("rate"));
|
||||||
|
deviceStatus.enacted.put("duration", lastRun.setByPump.json().get("duration"));
|
||||||
|
deviceStatus.enacted.put("recieved", true);
|
||||||
|
JSONObject requested = new JSONObject();
|
||||||
|
requested.put("duration", lastRun.request.duration);
|
||||||
|
requested.put("rate", lastRun.request.rate);
|
||||||
|
requested.put("temp", "absolute");
|
||||||
|
deviceStatus.enacted.put("requested", requested);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (activePump != null) {
|
||||||
|
deviceStatus.device = "openaps://" + deviceID();
|
||||||
|
deviceStatus.pump = getJSONStatus();
|
||||||
|
|
||||||
|
deviceStatus.created_at = DateUtil.toISOString(new Date());
|
||||||
|
|
||||||
|
deviceStatus.sendToNSClient();
|
||||||
|
lastDeviceStatusUpload = new Date();
|
||||||
|
}
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void uploadBolusWizardRecord(Treatment t, double glucose, String glucoseType, int carbTime, JSONObject boluscalc) {
|
||||||
|
JSONObject data = new JSONObject();
|
||||||
|
try {
|
||||||
|
data.put("eventType", "Bolus Wizard");
|
||||||
|
if (t.insulin != 0d) data.put("insulin", t.insulin);
|
||||||
|
if (t.carbs != 0d) data.put("carbs", t.carbs.intValue());
|
||||||
|
data.put("created_at", DateUtil.toISOString(t.created_at));
|
||||||
|
data.put("timeIndex", t.timeIndex);
|
||||||
|
if (glucose != 0d) data.put("glucose", glucose);
|
||||||
|
data.put("glucoseType", glucoseType);
|
||||||
|
data.put("boluscalc", boluscalc);
|
||||||
|
if (carbTime != 0) data.put("preBolus", carbTime);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
uploadCareportalEntryToNS(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void uploadCareportalEntryToNS(JSONObject data) {
|
||||||
|
try {
|
||||||
|
if (data.has("preBolus") && data.has("carbs")) {
|
||||||
|
JSONObject prebolus = new JSONObject();
|
||||||
|
prebolus.put("carbs", data.get("carbs"));
|
||||||
|
data.remove("carbs");
|
||||||
|
prebolus.put("eventType", data.get("eventType"));
|
||||||
|
if (data.has("enteredBy")) prebolus.put("enteredBy", data.get("enteredBy"));
|
||||||
|
if (data.has("notes")) prebolus.put("notes", data.get("notes"));
|
||||||
|
long mills = DateUtil.fromISODateString(data.getString("created_at")).getTime();
|
||||||
|
Date preBolusDate = new Date(mills + data.getInt("preBolus") * 60000L);
|
||||||
|
prebolus.put("created_at", DateUtil.toISOString(preBolusDate));
|
||||||
|
uploadCareportalEntryToNS(prebolus);
|
||||||
|
}
|
||||||
|
Context context = MainApp.instance().getApplicationContext();
|
||||||
|
Bundle bundle = new Bundle();
|
||||||
|
bundle.putString("action", "dbAdd");
|
||||||
|
bundle.putString("collection", "treatments");
|
||||||
|
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(), NewExtendedBolusDialog.class);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR;
|
||||||
|
|
||||||
|
import android.bluetooth.*;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.preference.ListPreference;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class BluetoothDevicePreference extends ListPreference {
|
||||||
|
|
||||||
|
public BluetoothDevicePreference(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
|
||||||
|
BluetoothAdapter bta = BluetoothAdapter.getDefaultAdapter();
|
||||||
|
Integer size = 0;
|
||||||
|
if (bta != null) {
|
||||||
|
size += bta.getBondedDevices().size();
|
||||||
|
}
|
||||||
|
CharSequence[] entries = new CharSequence[size];
|
||||||
|
int i = 0;
|
||||||
|
if (bta != null) {
|
||||||
|
Set<BluetoothDevice> pairedDevices = bta.getBondedDevices();
|
||||||
|
for (BluetoothDevice dev : pairedDevices) {
|
||||||
|
entries[i] = dev.getName();
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setEntries(entries);
|
||||||
|
setEntryValues(entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BluetoothDevicePreference(Context context) {
|
||||||
|
this(context, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,234 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR;
|
||||||
|
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.HandlerThread;
|
||||||
|
import android.support.v4.app.Fragment;
|
||||||
|
import android.support.v4.app.FragmentManager;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.squareup.otto.Subscribe;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
import info.nightscout.androidaps.R;
|
||||||
|
import info.nightscout.androidaps.events.EventPreferenceChange;
|
||||||
|
import info.nightscout.androidaps.events.EventTempBasalChange;
|
||||||
|
import info.nightscout.androidaps.interfaces.FragmentBase;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.Dialogs.ProfileViewDialog;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.History.DanaRHistoryActivity;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.events.EventDanaRConnectionStatus;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.events.EventDanaRNewStatus;
|
||||||
|
import info.nightscout.utils.DecimalFormatter;
|
||||||
|
import info.nightscout.utils.SetWarnColor;
|
||||||
|
|
||||||
|
public class DanaRFragment extends Fragment implements FragmentBase {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(DanaRFragment.class);
|
||||||
|
|
||||||
|
private static DanaRPlugin danaRPlugin = new DanaRPlugin();
|
||||||
|
|
||||||
|
public static DanaRPlugin getPlugin() {
|
||||||
|
return danaRPlugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Handler sHandler;
|
||||||
|
private static HandlerThread sHandlerThread;
|
||||||
|
|
||||||
|
private Handler loopHandler = new Handler();
|
||||||
|
private Runnable refreshLoop = null;
|
||||||
|
|
||||||
|
TextView lastConnectionView;
|
||||||
|
TextView btConnectionView;
|
||||||
|
TextView lastBolusView;
|
||||||
|
TextView dailyUnitsView;
|
||||||
|
TextView basaBasalRateView;
|
||||||
|
TextView tempBasalView;
|
||||||
|
TextView extendedBolusView;
|
||||||
|
TextView batteryView;
|
||||||
|
TextView reservoirView;
|
||||||
|
TextView iobView;
|
||||||
|
Button viewProfileButton;
|
||||||
|
Button historyButton;
|
||||||
|
|
||||||
|
public DanaRFragment() {
|
||||||
|
if (sHandlerThread == null) {
|
||||||
|
sHandlerThread = new HandlerThread(DanaRFragment.class.getSimpleName());
|
||||||
|
sHandlerThread.start();
|
||||||
|
sHandler = new Handler(sHandlerThread.getLooper());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
if (refreshLoop == null) {
|
||||||
|
refreshLoop = new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
updateGUI();
|
||||||
|
loopHandler.postDelayed(refreshLoop, 60 * 1000L);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
loopHandler.postDelayed(refreshLoop, 60 * 1000L);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
|
Bundle savedInstanceState) {
|
||||||
|
View view = inflater.inflate(R.layout.danar_fragment, container, false);
|
||||||
|
btConnectionView = (TextView) view.findViewById(R.id.danar_btconnection);
|
||||||
|
lastConnectionView = (TextView) view.findViewById(R.id.danar_lastconnection);
|
||||||
|
lastBolusView = (TextView) view.findViewById(R.id.danar_lastbolus);
|
||||||
|
dailyUnitsView = (TextView) view.findViewById(R.id.danar_dailyunits);
|
||||||
|
basaBasalRateView = (TextView) view.findViewById(R.id.danar_basabasalrate);
|
||||||
|
tempBasalView = (TextView) view.findViewById(R.id.danar_tempbasal);
|
||||||
|
extendedBolusView = (TextView) view.findViewById(R.id.danar_extendedbolus);
|
||||||
|
batteryView = (TextView) view.findViewById(R.id.danar_battery);
|
||||||
|
reservoirView = (TextView) view.findViewById(R.id.danar_reservoir);
|
||||||
|
iobView = (TextView) view.findViewById(R.id.danar_iob);
|
||||||
|
viewProfileButton = (Button) view.findViewById(R.id.danar_viewprofile);
|
||||||
|
historyButton = (Button) view.findViewById(R.id.danar_history);
|
||||||
|
|
||||||
|
viewProfileButton.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
FragmentManager manager = getFragmentManager();
|
||||||
|
ProfileViewDialog profileViewDialog = new ProfileViewDialog();
|
||||||
|
profileViewDialog.show(manager, "ProfileViewDialog");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
historyButton.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
startActivity(new Intent(getContext(), DanaRHistoryActivity.class));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
btConnectionView.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
sHandler.post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
DanaRPlugin.sExecutionService.connect("Connect request from GUI");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
updateGUI();
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPause() {
|
||||||
|
super.onPause();
|
||||||
|
MainApp.bus().unregister(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
MainApp.bus().register(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onStatusEvent(final EventDanaRConnectionStatus c) {
|
||||||
|
Activity activity = getActivity();
|
||||||
|
if (activity != null) {
|
||||||
|
activity.runOnUiThread(
|
||||||
|
new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (c.sStatus == EventDanaRConnectionStatus.CONNECTING)
|
||||||
|
btConnectionView.setText("{fa-bluetooth-b spin} " + c.sSecondsElapsed + "s");
|
||||||
|
else if (c.sStatus == EventDanaRConnectionStatus.CONNECTED)
|
||||||
|
btConnectionView.setText("{fa-bluetooth}");
|
||||||
|
else
|
||||||
|
btConnectionView.setText("{fa-bluetooth-b}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onStatusEvent(final EventDanaRNewStatus s) {
|
||||||
|
updateGUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onStatusEvent(final EventTempBasalChange s) {
|
||||||
|
updateGUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onStatusEvent(final EventPreferenceChange s) {
|
||||||
|
updateGUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
// GUI functions
|
||||||
|
private void updateGUI() {
|
||||||
|
final DateFormat formatTime = DateFormat.getTimeInstance(DateFormat.SHORT);
|
||||||
|
|
||||||
|
Activity activity = getActivity();
|
||||||
|
if (activity != null && basaBasalRateView != null)
|
||||||
|
activity.runOnUiThread(new Runnable() {
|
||||||
|
@SuppressLint("SetTextI18n")
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
|
||||||
|
if (DanaRPlugin.getDanaRPump().lastConnection.getTime() != 0) {
|
||||||
|
Long agoMsec = new Date().getTime() - DanaRPlugin.getDanaRPump().lastConnection.getTime();
|
||||||
|
int agoMin = (int) (agoMsec / 60d / 1000d);
|
||||||
|
lastConnectionView.setText(formatTime.format(DanaRPlugin.getDanaRPump().lastConnection) + " (" + agoMin + " " + MainApp.sResources.getString(R.string.minago) + ")");
|
||||||
|
SetWarnColor.setColor(lastConnectionView, agoMin, 16d, 31d);
|
||||||
|
}
|
||||||
|
if (DanaRPlugin.getDanaRPump().lastBolusTime.getTime() != 0) {
|
||||||
|
Long agoMsec = new Date().getTime() - DanaRPlugin.getDanaRPump().lastBolusTime.getTime();
|
||||||
|
double agoHours = (int) (agoMsec / 60d / 60d / 1000d);
|
||||||
|
if (agoHours < 6) // max 6h back
|
||||||
|
lastBolusView.setText(formatTime.format(DanaRPlugin.getDanaRPump().lastBolusTime) + " (" + DecimalFormatter.to1Decimal(agoHours) + " " + getString(R.string.hoursago) + ") " + DecimalFormatter.to2Decimal(danaRPlugin.getDanaRPump().lastBolusAmount) + " U");
|
||||||
|
else lastBolusView.setText("");
|
||||||
|
}
|
||||||
|
|
||||||
|
dailyUnitsView.setText(DecimalFormatter.to0Decimal(DanaRPlugin.getDanaRPump().dailyTotalUnits) + " / " + DanaRPlugin.getDanaRPump().maxDailyTotalUnits + " U");
|
||||||
|
SetWarnColor.setColor(dailyUnitsView, DanaRPlugin.getDanaRPump().dailyTotalUnits, DanaRPlugin.getDanaRPump().maxDailyTotalUnits * 0.75d, DanaRPlugin.getDanaRPump().maxDailyTotalUnits * 0.9d);
|
||||||
|
basaBasalRateView.setText("( " + (DanaRPlugin.getDanaRPump().activeProfile + 1) + " ) " + DecimalFormatter.to2Decimal(danaRPlugin.getBaseBasalRate()) + " U/h");
|
||||||
|
if (danaRPlugin.isRealTempBasalInProgress()) {
|
||||||
|
tempBasalView.setText(danaRPlugin.getRealTempBasal().toString());
|
||||||
|
} else {
|
||||||
|
tempBasalView.setText("");
|
||||||
|
}
|
||||||
|
if (danaRPlugin.isExtendedBoluslInProgress()) {
|
||||||
|
extendedBolusView.setText(danaRPlugin.getExtendedBolus().toString());
|
||||||
|
} else {
|
||||||
|
extendedBolusView.setText("");
|
||||||
|
}
|
||||||
|
reservoirView.setText(DecimalFormatter.to0Decimal(DanaRPlugin.getDanaRPump().reservoirRemainingUnits) + " / 300 U");
|
||||||
|
SetWarnColor.setColorInverse(reservoirView, DanaRPlugin.getDanaRPump().reservoirRemainingUnits, 50d, 20d);
|
||||||
|
batteryView.setText("{fa-battery-" + (DanaRPlugin.getDanaRPump().batteryRemaining / 25) + "}");
|
||||||
|
SetWarnColor.setColorInverse(batteryView, DanaRPlugin.getDanaRPump().batteryRemaining, 51d, 26d);
|
||||||
|
iobView.setText(DanaRPlugin.getDanaRPump().iob + " U");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,732 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR;
|
||||||
|
|
||||||
|
import android.content.ComponentName;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.ServiceConnection;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.os.IBinder;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.squareup.otto.Subscribe;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.Config;
|
||||||
|
import info.nightscout.androidaps.Constants;
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
import info.nightscout.androidaps.R;
|
||||||
|
import info.nightscout.androidaps.data.PumpEnactResult;
|
||||||
|
import info.nightscout.androidaps.db.TempBasal;
|
||||||
|
import info.nightscout.androidaps.db.Treatment;
|
||||||
|
import info.nightscout.androidaps.events.EventAppExit;
|
||||||
|
import info.nightscout.androidaps.events.EventPreferenceChange;
|
||||||
|
import info.nightscout.androidaps.interfaces.ConstraintsInterface;
|
||||||
|
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||||
|
import info.nightscout.androidaps.interfaces.ProfileInterface;
|
||||||
|
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||||
|
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.Services.ExecutionService;
|
||||||
|
import info.nightscout.client.data.NSProfile;
|
||||||
|
import info.nightscout.utils.DateUtil;
|
||||||
|
import info.nightscout.utils.DecimalFormatter;
|
||||||
|
import info.nightscout.utils.Round;
|
||||||
|
import info.nightscout.utils.ToastUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 05.08.2016.
|
||||||
|
*/
|
||||||
|
public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterface, ProfileInterface {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(DanaRPlugin.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getFragmentClass() {
|
||||||
|
return DanaRFragment.class.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean fragmentPumpEnabled = true;
|
||||||
|
static boolean fragmentProfileEnabled = true;
|
||||||
|
static boolean fragmentPumpVisible = true;
|
||||||
|
|
||||||
|
public static ExecutionService sExecutionService;
|
||||||
|
|
||||||
|
|
||||||
|
private static DanaRPump sDanaRPump = new DanaRPump();
|
||||||
|
private static boolean useExtendedBoluses = false;
|
||||||
|
|
||||||
|
public static DanaRPump getDanaRPump() {
|
||||||
|
return sDanaRPump;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DanaRPlugin() {
|
||||||
|
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
|
||||||
|
useExtendedBoluses = sharedPreferences.getBoolean("danar_useextended", false);
|
||||||
|
|
||||||
|
Context context = MainApp.instance().getApplicationContext();
|
||||||
|
Intent intent = new Intent(context, ExecutionService.class);
|
||||||
|
context.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
|
||||||
|
MainApp.bus().register(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
ServiceConnection mConnection = new ServiceConnection() {
|
||||||
|
|
||||||
|
public void onServiceDisconnected(ComponentName name) {
|
||||||
|
log.debug("Service is disconnected");
|
||||||
|
sExecutionService = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||||
|
log.debug("Service is connected");
|
||||||
|
ExecutionService.LocalBinder mLocalBinder = (ExecutionService.LocalBinder) service;
|
||||||
|
sExecutionService = mLocalBinder.getServiceInstance();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@SuppressWarnings("UnusedParameters")
|
||||||
|
@Subscribe
|
||||||
|
public void onStatusEvent(final EventAppExit e) {
|
||||||
|
MainApp.instance().getApplicationContext().unbindService(mConnection);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onStatusEvent(final EventPreferenceChange s) {
|
||||||
|
boolean previousValue = useExtendedBoluses;
|
||||||
|
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
|
||||||
|
useExtendedBoluses = sharedPreferences.getBoolean("danar_useextended", false);
|
||||||
|
if (useExtendedBoluses != previousValue && isExtendedBoluslInProgress()) {
|
||||||
|
sExecutionService.extendedBolusStop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Plugin base interface
|
||||||
|
@Override
|
||||||
|
public int getType() {
|
||||||
|
return PluginBase.PUMP;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return MainApp.instance().getString(R.string.danarpump);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEnabled(int type) {
|
||||||
|
if (type == PluginBase.PROFILE) return fragmentProfileEnabled && fragmentPumpEnabled;
|
||||||
|
else if (type == PluginBase.PUMP) return fragmentPumpEnabled;
|
||||||
|
else if (type == PluginBase.CONSTRAINTS) return fragmentPumpEnabled;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isVisibleInTabs(int type) {
|
||||||
|
if (type == PluginBase.PROFILE || type == PluginBase.CONSTRAINTS) return false;
|
||||||
|
else if (type == PluginBase.PUMP) return fragmentPumpVisible;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canBeHidden(int type) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
|
||||||
|
if (type == PluginBase.PROFILE) this.fragmentProfileEnabled = fragmentEnabled;
|
||||||
|
else if (type == PluginBase.PUMP) this.fragmentPumpEnabled = fragmentEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFragmentVisible(int type, boolean fragmentVisible) {
|
||||||
|
if (type == PluginBase.PUMP)
|
||||||
|
this.fragmentPumpVisible = fragmentVisible;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pump interface
|
||||||
|
@Override
|
||||||
|
public boolean isTempBasalInProgress() {
|
||||||
|
if (getRealTempBasal() != null) return true;
|
||||||
|
if (getExtendedBolus() != null && useExtendedBoluses) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isRealTempBasalInProgress() {
|
||||||
|
return getRealTempBasal() != null; //TODO: crosscheck here
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isExtendedBoluslInProgress() {
|
||||||
|
return getExtendedBolus() != null; //TODO: crosscheck here
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setNewBasalProfile(NSProfile profile) {
|
||||||
|
if (sExecutionService == null) {
|
||||||
|
log.error("setNewBasalProfile sExecutionService is null");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!sExecutionService.updateBasalsInPump(profile))
|
||||||
|
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.failedupdatebasalprofile));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getBaseBasalRate() {
|
||||||
|
return getDanaRPump().currentBasal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getTempBasalAbsoluteRate() {
|
||||||
|
if (isRealTempBasalInProgress()) {
|
||||||
|
if (getRealTempBasal().isAbsolute) {
|
||||||
|
return getRealTempBasal().absolute;
|
||||||
|
} else {
|
||||||
|
Double baseRate = getBaseBasalRate();
|
||||||
|
Double tempRate = baseRate * (getRealTempBasal().percent / 100d);
|
||||||
|
return tempRate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isExtendedBoluslInProgress() && useExtendedBoluses) {
|
||||||
|
return getBaseBasalRate() + getExtendedBolus().absolute;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getTempBasalRemainingMinutes() {
|
||||||
|
if (isRealTempBasalInProgress())
|
||||||
|
return getRealTempBasal().getPlannedRemainingMinutes();
|
||||||
|
if (isExtendedBoluslInProgress() && useExtendedBoluses)
|
||||||
|
return getExtendedBolus().getPlannedRemainingMinutes();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TempBasal getTempBasal() {
|
||||||
|
if (isRealTempBasalInProgress())
|
||||||
|
return getRealTempBasal();
|
||||||
|
if (isExtendedBoluslInProgress() && useExtendedBoluses)
|
||||||
|
return getExtendedBolus();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TempBasal getTempBasal(Date time) {
|
||||||
|
TempBasal temp = MainApp.getConfigBuilder().getActiveTempBasals().getTempBasal(time);
|
||||||
|
if (temp != null) return temp;
|
||||||
|
if (useExtendedBoluses)
|
||||||
|
return MainApp.getConfigBuilder().getActiveTempBasals().getExtendedBolus(time);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TempBasal getRealTempBasal() {
|
||||||
|
return MainApp.getConfigBuilder().getActiveTempBasals().getTempBasal(new Date());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TempBasal getExtendedBolus() {
|
||||||
|
return MainApp.getConfigBuilder().getActiveTempBasals().getExtendedBolus(new Date());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PumpEnactResult deliverTreatment(Double insulin, Integer carbs, Context context) {
|
||||||
|
ConfigBuilderPlugin configBuilderPlugin = MainApp.getConfigBuilder();
|
||||||
|
insulin = configBuilderPlugin.applyBolusConstraints(insulin);
|
||||||
|
if (insulin > 0 || carbs > 0) {
|
||||||
|
Treatment t = new Treatment();
|
||||||
|
boolean connectionOK = false;
|
||||||
|
if (insulin > 0 || carbs > 0) connectionOK = sExecutionService.bolus(insulin, carbs, t);
|
||||||
|
PumpEnactResult result = new PumpEnactResult();
|
||||||
|
result.success = connectionOK;
|
||||||
|
result.bolusDelivered = t.insulin;
|
||||||
|
result.carbsDelivered = carbs;
|
||||||
|
result.comment = MainApp.instance().getString(R.string.virtualpump_resultok);
|
||||||
|
if (Config.logPumpActions)
|
||||||
|
log.debug("deliverTreatment: OK. Asked: " + insulin + " Delivered: " + result.bolusDelivered);
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
PumpEnactResult result = new PumpEnactResult();
|
||||||
|
result.success = false;
|
||||||
|
result.bolusDelivered = 0d;
|
||||||
|
result.carbsDelivered = 0;
|
||||||
|
result.comment = MainApp.instance().getString(R.string.danar_invalidinput);
|
||||||
|
log.error("deliverTreatment: Invalid input");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stopBolusDelivering() {
|
||||||
|
if (sExecutionService == null) {
|
||||||
|
log.error("stopBolusDelivering sExecutionService is null");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sExecutionService.bolusStop();
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is called from APS
|
||||||
|
@Override
|
||||||
|
public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes) {
|
||||||
|
// Recheck pump status if older than 30 min
|
||||||
|
if (getDanaRPump().lastConnection.getTime() + 30 * 60 * 1000L < new Date().getTime()) {
|
||||||
|
doConnect("setTempBasalAbsolute old data");
|
||||||
|
}
|
||||||
|
|
||||||
|
PumpEnactResult result = new PumpEnactResult();
|
||||||
|
|
||||||
|
ConfigBuilderPlugin configBuilderPlugin = MainApp.getConfigBuilder();
|
||||||
|
absoluteRate = configBuilderPlugin.applyBasalConstraints(absoluteRate);
|
||||||
|
|
||||||
|
final boolean doTempOff = getBaseBasalRate() - absoluteRate == 0d;
|
||||||
|
final boolean doLowTemp = absoluteRate < getBaseBasalRate();
|
||||||
|
final boolean doHighTemp = absoluteRate > getBaseBasalRate() && !useExtendedBoluses;
|
||||||
|
final boolean doExtendedTemp = absoluteRate > getBaseBasalRate() && useExtendedBoluses;
|
||||||
|
|
||||||
|
if (doTempOff) {
|
||||||
|
// If extended in progress
|
||||||
|
if (isExtendedBoluslInProgress() && useExtendedBoluses) {
|
||||||
|
if (Config.logPumpActions)
|
||||||
|
log.debug("setTempBasalAbsolute: Stopping extended bolus (doTempOff)");
|
||||||
|
return cancelExtendedBolus();
|
||||||
|
}
|
||||||
|
// If temp in progress
|
||||||
|
if (isRealTempBasalInProgress()) {
|
||||||
|
if (Config.logPumpActions)
|
||||||
|
log.debug("setTempBasalAbsolute: Stopping temp basal (doTempOff)");
|
||||||
|
return cancelRealTempBasal();
|
||||||
|
}
|
||||||
|
result.success = true;
|
||||||
|
result.enacted = false;
|
||||||
|
result.percent = 100;
|
||||||
|
result.isPercent = true;
|
||||||
|
result.isTempCancel = true;
|
||||||
|
if (Config.logPumpActions)
|
||||||
|
log.debug("setTempBasalAbsolute: doTempOff OK");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (doLowTemp || doHighTemp) {
|
||||||
|
Integer percentRate = Double.valueOf(absoluteRate / getBaseBasalRate() * 100).intValue();
|
||||||
|
if (percentRate < 100) percentRate = Round.ceilTo((double) percentRate, 10d).intValue();
|
||||||
|
else percentRate = Round.floorTo((double) percentRate, 10d).intValue();
|
||||||
|
if (percentRate > 200) {
|
||||||
|
percentRate = 200;
|
||||||
|
}
|
||||||
|
// If extended in progress
|
||||||
|
if (isExtendedBoluslInProgress() && useExtendedBoluses) {
|
||||||
|
if (Config.logPumpActions)
|
||||||
|
log.debug("setTempBasalAbsolute: Stopping extended bolus (doLowTemp || doHighTemp)");
|
||||||
|
result = cancelExtendedBolus();
|
||||||
|
if (!result.success) {
|
||||||
|
log.error("setTempBasalAbsolute: Failed to stop previous extended bolus (doLowTemp || doHighTemp)");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Check if some temp is already in progress
|
||||||
|
if (isRealTempBasalInProgress()) {
|
||||||
|
// Correct basal already set ?
|
||||||
|
if (getRealTempBasal().percent == percentRate) {
|
||||||
|
result.success = true;
|
||||||
|
result.percent = percentRate;
|
||||||
|
result.absolute = getTempBasalAbsoluteRate();
|
||||||
|
result.enacted = false;
|
||||||
|
result.duration = ((Double) getTempBasalRemainingMinutes()).intValue();
|
||||||
|
result.isPercent = true;
|
||||||
|
result.isTempCancel = false;
|
||||||
|
if (Config.logPumpActions)
|
||||||
|
log.debug("setTempBasalAbsolute: Correct temp basal already set (doLowTemp || doHighTemp)");
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
if (Config.logPumpActions)
|
||||||
|
log.debug("setTempBasalAbsolute: Stopping temp basal (doLowTemp || doHighTemp)");
|
||||||
|
result = cancelRealTempBasal();
|
||||||
|
// Check for proper result
|
||||||
|
if (!result.success) {
|
||||||
|
log.error("setTempBasalAbsolute: Failed to stop previous temp basal (doLowTemp || doHighTemp)");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Convert duration from minutes to hours
|
||||||
|
if (Config.logPumpActions)
|
||||||
|
log.debug("setTempBasalAbsolute: Setting temp basal " + percentRate + "% for " + durationInMinutes + " mins (doLowTemp || doHighTemp)");
|
||||||
|
return setTempBasalPercent(percentRate, durationInMinutes);
|
||||||
|
}
|
||||||
|
if (doExtendedTemp) {
|
||||||
|
// Check if some temp is already in progress
|
||||||
|
if (isRealTempBasalInProgress()) {
|
||||||
|
if (Config.logPumpActions)
|
||||||
|
log.debug("setTempBasalAbsolute: Stopping temp basal (doExtendedTemp)");
|
||||||
|
result = cancelRealTempBasal();
|
||||||
|
// Check for proper result
|
||||||
|
if (!result.success) {
|
||||||
|
log.error("setTempBasalAbsolute: Failed to stop previous temp basal (doExtendedTemp)");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate # of halfHours from minutes
|
||||||
|
Integer durationInHalfHours = Math.max(durationInMinutes / 30, 1);
|
||||||
|
// We keep current basal running so need to sub current basal
|
||||||
|
Double extendedRateToSet = absoluteRate - getBaseBasalRate();
|
||||||
|
extendedRateToSet = configBuilderPlugin.applyBasalConstraints(extendedRateToSet);
|
||||||
|
// needs to be rounded to 0.1
|
||||||
|
extendedRateToSet = Round.roundTo(extendedRateToSet, 0.1d);
|
||||||
|
|
||||||
|
// What is current rate of extended bolusing in u/h?
|
||||||
|
if (Config.logPumpActions) {
|
||||||
|
log.debug("setTempBasalAbsolute: Extended bolus in progress: " + isExtendedBoluslInProgress() + " rate: " + getDanaRPump().extendedBolusAbsoluteRate + "U/h duration remaining: " + getDanaRPump().extendedBolusRemainingMinutes + "min");
|
||||||
|
log.debug("setTempBasalAbsolute: Rate to set: " + extendedRateToSet + "U/h");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compare with extended rate in progress
|
||||||
|
if (Math.abs(getDanaRPump().extendedBolusAbsoluteRate - extendedRateToSet) < 0.02D) { // Allow some rounding diff
|
||||||
|
// correct extended already set
|
||||||
|
result.success = true;
|
||||||
|
result.absolute = getDanaRPump().extendedBolusAbsoluteRate;
|
||||||
|
result.enacted = false;
|
||||||
|
result.duration = getDanaRPump().extendedBolusRemainingMinutes;
|
||||||
|
result.isPercent = false;
|
||||||
|
result.isTempCancel = false;
|
||||||
|
if (Config.logPumpActions)
|
||||||
|
log.debug("setTempBasalAbsolute: Correct extended already set");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now set new extended, no need to to stop previous (if running) because it's replaced
|
||||||
|
Double extendedAmount = extendedRateToSet / 2 * durationInHalfHours;
|
||||||
|
if (Config.logPumpActions)
|
||||||
|
log.debug("setTempBasalAbsolute: Setting extended: " + extendedAmount + "U halfhours: " + durationInHalfHours);
|
||||||
|
result = setExtendedBolus(extendedAmount, durationInMinutes);
|
||||||
|
if (!result.success) {
|
||||||
|
log.error("setTempBasalAbsolute: Failed to set extended bolus");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if (Config.logPumpActions)
|
||||||
|
log.debug("setTempBasalAbsolute: Extended bolus set ok");
|
||||||
|
result.absolute = result.absolute + getBaseBasalRate();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
// We should never end here
|
||||||
|
log.error("setTempBasalAbsolute: Internal error");
|
||||||
|
result.success = false;
|
||||||
|
result.comment = "Internal error";
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes) {
|
||||||
|
PumpEnactResult result = new PumpEnactResult();
|
||||||
|
ConfigBuilderPlugin configBuilderPlugin = MainApp.getConfigBuilder();
|
||||||
|
percent = configBuilderPlugin.applyBasalConstraints(percent);
|
||||||
|
if (percent < 0) {
|
||||||
|
result.isTempCancel = false;
|
||||||
|
result.enacted = false;
|
||||||
|
result.success = false;
|
||||||
|
result.comment = MainApp.instance().getString(R.string.danar_invalidinput);
|
||||||
|
log.error("setTempBasalPercent: Invalid input");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if (percent > 200) percent = 200;
|
||||||
|
if (getDanaRPump().isTempBasalInProgress && getDanaRPump().tempBasalPercent == percent) {
|
||||||
|
result.enacted = false;
|
||||||
|
result.success = true;
|
||||||
|
result.isTempCancel = false;
|
||||||
|
result.comment = MainApp.instance().getString(R.string.virtualpump_resultok);
|
||||||
|
result.duration = getDanaRPump().tempBasalRemainingMin;
|
||||||
|
result.percent = getDanaRPump().tempBasalPercent;
|
||||||
|
result.isPercent = true;
|
||||||
|
if (Config.logPumpActions)
|
||||||
|
log.debug("setTempBasalPercent: Correct value already set");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
int durationInHours = Math.max(durationInMinutes / 60, 1);
|
||||||
|
boolean connectionOK = sExecutionService.tempBasal(percent, durationInHours);
|
||||||
|
if (connectionOK && getDanaRPump().isTempBasalInProgress && getDanaRPump().tempBasalPercent == percent) {
|
||||||
|
result.enacted = true;
|
||||||
|
result.success = true;
|
||||||
|
result.comment = MainApp.instance().getString(R.string.virtualpump_resultok);
|
||||||
|
result.isTempCancel = false;
|
||||||
|
result.duration = getDanaRPump().tempBasalRemainingMin;
|
||||||
|
result.percent = getDanaRPump().tempBasalPercent;
|
||||||
|
result.isPercent = true;
|
||||||
|
if (Config.logPumpActions)
|
||||||
|
log.debug("setTempBasalPercent: OK");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
result.enacted = false;
|
||||||
|
result.success = false;
|
||||||
|
result.comment = MainApp.instance().getString(R.string.danar_valuenotsetproperly);
|
||||||
|
log.error("setTempBasalPercent: Failed to set temp basal");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes) {
|
||||||
|
ConfigBuilderPlugin configBuilderPlugin = MainApp.getConfigBuilder();
|
||||||
|
insulin = configBuilderPlugin.applyBolusConstraints(insulin);
|
||||||
|
// needs to be rounded to 0.1
|
||||||
|
insulin = Round.roundTo(insulin, 0.1d);
|
||||||
|
|
||||||
|
PumpEnactResult result = new PumpEnactResult();
|
||||||
|
if (getDanaRPump().isExtendedInProgress && Math.abs(getDanaRPump().extendedBolusAmount - insulin) < 0.1d) {
|
||||||
|
result.enacted = false;
|
||||||
|
result.success = true;
|
||||||
|
result.comment = MainApp.instance().getString(R.string.virtualpump_resultok);
|
||||||
|
result.duration = getDanaRPump().extendedBolusRemainingMinutes;
|
||||||
|
result.absolute = getDanaRPump().extendedBolusAbsoluteRate;
|
||||||
|
result.isPercent = false;
|
||||||
|
result.isTempCancel = false;
|
||||||
|
if (Config.logPumpActions)
|
||||||
|
log.debug("setExtendedBolus: Correct extended bolus already set");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
int durationInHalfHours = Math.max(durationInMinutes / 30, 1);
|
||||||
|
boolean connectionOK = sExecutionService.extendedBolus(insulin, durationInHalfHours);
|
||||||
|
if (connectionOK && getDanaRPump().isExtendedInProgress && Math.abs(getDanaRPump().extendedBolusAmount - insulin) < 0.1d) {
|
||||||
|
result.enacted = true;
|
||||||
|
result.success = true;
|
||||||
|
result.comment = MainApp.instance().getString(R.string.virtualpump_resultok);
|
||||||
|
result.isTempCancel = false;
|
||||||
|
result.duration = getDanaRPump().extendedBolusRemainingMinutes;
|
||||||
|
result.absolute = getDanaRPump().extendedBolusAbsoluteRate;
|
||||||
|
result.bolusDelivered = getDanaRPump().extendedBolusAmount;
|
||||||
|
result.isPercent = false;
|
||||||
|
if (Config.logPumpActions)
|
||||||
|
log.debug("setExtendedBolus: OK");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
result.enacted = false;
|
||||||
|
result.success = false;
|
||||||
|
result.comment = MainApp.instance().getString(R.string.danar_valuenotsetproperly);
|
||||||
|
log.error("setExtendedBolus: Failed to extended bolus");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PumpEnactResult cancelTempBasal() {
|
||||||
|
if (isRealTempBasalInProgress())
|
||||||
|
return cancelRealTempBasal();
|
||||||
|
if (isExtendedBoluslInProgress())
|
||||||
|
return cancelExtendedBolus();
|
||||||
|
PumpEnactResult result = new PumpEnactResult();
|
||||||
|
result.success = true;
|
||||||
|
result.enacted = false;
|
||||||
|
result.comment = MainApp.instance().getString(R.string.virtualpump_resultok);
|
||||||
|
result.isTempCancel = true;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PumpEnactResult cancelRealTempBasal() {
|
||||||
|
PumpEnactResult result = new PumpEnactResult();
|
||||||
|
if (getDanaRPump().isTempBasalInProgress) {
|
||||||
|
sExecutionService.tempBasalStop();
|
||||||
|
result.enacted = true;
|
||||||
|
result.isTempCancel = true;
|
||||||
|
}
|
||||||
|
if (!getDanaRPump().isTempBasalInProgress) {
|
||||||
|
result.success = true;
|
||||||
|
result.isTempCancel = true;
|
||||||
|
result.comment = MainApp.instance().getString(R.string.virtualpump_resultok);
|
||||||
|
if (Config.logPumpActions)
|
||||||
|
log.debug("cancelRealTempBasal: OK");
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
result.success = false;
|
||||||
|
result.comment = MainApp.instance().getString(R.string.danar_valuenotsetproperly);
|
||||||
|
result.isTempCancel = true;
|
||||||
|
log.error("cancelRealTempBasal: Failed to cancel temp basal");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PumpEnactResult cancelExtendedBolus() {
|
||||||
|
PumpEnactResult result = new PumpEnactResult();
|
||||||
|
if (getDanaRPump().isExtendedInProgress) {
|
||||||
|
sExecutionService.extendedBolusStop();
|
||||||
|
result.enacted = true;
|
||||||
|
result.isTempCancel = true;
|
||||||
|
}
|
||||||
|
if (!getDanaRPump().isExtendedInProgress) {
|
||||||
|
result.success = true;
|
||||||
|
result.comment = MainApp.instance().getString(R.string.virtualpump_resultok);
|
||||||
|
if (Config.logPumpActions)
|
||||||
|
log.debug("cancelExtendedBolus: OK");
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
result.success = false;
|
||||||
|
result.comment = MainApp.instance().getString(R.string.danar_valuenotsetproperly);
|
||||||
|
log.error("cancelExtendedBolus: Failed to cancel extended bolus");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void doConnect(String from) {
|
||||||
|
if (sExecutionService != null) sExecutionService.connect(from);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isConnected() {
|
||||||
|
return sExecutionService != null && sExecutionService.isConnected();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isConnecting() {
|
||||||
|
return sExecutionService != null && sExecutionService.isConnecting();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JSONObject getJSONStatus() {
|
||||||
|
if (getDanaRPump().lastConnection.getTime() + 5 * 60 * 1000L < new Date().getTime()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
JSONObject pump = new JSONObject();
|
||||||
|
JSONObject battery = new JSONObject();
|
||||||
|
JSONObject status = new JSONObject();
|
||||||
|
JSONObject extended = new JSONObject();
|
||||||
|
try {
|
||||||
|
battery.put("percent", getDanaRPump().batteryRemaining);
|
||||||
|
status.put("status", "normal");
|
||||||
|
status.put("timestamp", DateUtil.toISOString(getDanaRPump().lastConnection));
|
||||||
|
if (isTempBasalInProgress()) {
|
||||||
|
extended.put("TempBasalAbsoluteRate", getTempBasalAbsoluteRate());
|
||||||
|
extended.put("TempBasalStart", getTempBasal().timeStart.toLocaleString());
|
||||||
|
extended.put("TempBasalRemaining", getTempBasal().getPlannedRemainingMinutes());
|
||||||
|
extended.put("IsExtended", getTempBasal().isExtended);
|
||||||
|
extended.put("BaseBasalRate", getBaseBasalRate());
|
||||||
|
try {
|
||||||
|
extended.put("ActiveProfile", MainApp.getConfigBuilder().getActiveProfile().getProfile().getActiveProfile());
|
||||||
|
} catch (Exception e) {}
|
||||||
|
}
|
||||||
|
extended.put("PumpIOB", getDanaRPump().iob);
|
||||||
|
extended.put("LastBolus", getDanaRPump().lastBolusTime.toLocaleString());
|
||||||
|
extended.put("LastBolusAmount", getDanaRPump().lastBolusAmount);
|
||||||
|
|
||||||
|
pump.put("battery", battery);
|
||||||
|
pump.put("status", status);
|
||||||
|
pump.put("extended", extended);
|
||||||
|
pump.put("reservoir", (int) getDanaRPump().reservoirRemainingUnits);
|
||||||
|
pump.put("clock", DateUtil.toISOString(new Date()));
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return pump;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String deviceID() {
|
||||||
|
return getDanaRPump().serialNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constraint interface
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isLoopEnabled() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isClosedModeEnabled() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAutosensModeEnabled() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAMAModeEnabled() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("PointlessBooleanExpression")
|
||||||
|
@Override
|
||||||
|
public Double applyBasalConstraints(Double absoluteRate) {
|
||||||
|
double origAbsoluteRate = absoluteRate;
|
||||||
|
if (getDanaRPump() != null) {
|
||||||
|
if (absoluteRate > getDanaRPump().maxBasal) {
|
||||||
|
absoluteRate = getDanaRPump().maxBasal;
|
||||||
|
if (Config.logConstraintsChanges && origAbsoluteRate != Constants.basalAbsoluteOnlyForCheckLimit)
|
||||||
|
log.debug("Limiting rate " + origAbsoluteRate + "U/h by pump constraint to " + absoluteRate + "U/h");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return absoluteRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("PointlessBooleanExpression")
|
||||||
|
@Override
|
||||||
|
public Integer applyBasalConstraints(Integer percentRate) {
|
||||||
|
Integer origPercentRate = percentRate;
|
||||||
|
if (percentRate < 0) percentRate = 0;
|
||||||
|
if (percentRate > 200) percentRate = 200;
|
||||||
|
if (!Objects.equals(percentRate, origPercentRate) && Config.logConstraintsChanges && !Objects.equals(origPercentRate, Constants.basalPercentOnlyForCheckLimit))
|
||||||
|
log.debug("Limiting percent rate " + origPercentRate + "% to " + percentRate + "%");
|
||||||
|
return percentRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("PointlessBooleanExpression")
|
||||||
|
@Override
|
||||||
|
public Double applyBolusConstraints(Double insulin) {
|
||||||
|
double origInsulin = insulin;
|
||||||
|
if (getDanaRPump() != null) {
|
||||||
|
if (insulin > getDanaRPump().maxBolus) {
|
||||||
|
insulin = getDanaRPump().maxBolus;
|
||||||
|
if (Config.logConstraintsChanges && origInsulin != Constants.bolusOnlyForCheckLimit)
|
||||||
|
log.debug("Limiting bolus " + origInsulin + "U by pump constraint to " + insulin + "U");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return insulin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer applyCarbsConstraints(Integer carbs) {
|
||||||
|
return carbs;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Double applyMaxIOBConstraints(Double maxIob) {
|
||||||
|
return maxIob;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public NSProfile getProfile() {
|
||||||
|
DanaRPump pump = getDanaRPump();
|
||||||
|
if (pump.lastSettingsRead.getTime() == 0)
|
||||||
|
return null; // no info now
|
||||||
|
return pump.createConvertedProfile();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reply for sms communicator
|
||||||
|
public String shortStatus() {
|
||||||
|
final DateFormat formatTime = DateFormat.getTimeInstance(DateFormat.SHORT);
|
||||||
|
String ret = "";
|
||||||
|
if (getDanaRPump().lastConnection.getTime() != 0) {
|
||||||
|
Long agoMsec = new Date().getTime() - getDanaRPump().lastConnection.getTime();
|
||||||
|
int agoMin = (int) (agoMsec / 60d / 1000d);
|
||||||
|
ret += "LastConn: " + agoMin + " minago\n";
|
||||||
|
}
|
||||||
|
if (getDanaRPump().lastBolusTime.getTime() != 0) {
|
||||||
|
ret += "LastBolus: " + DecimalFormatter.to2Decimal(getDanaRPump().lastBolusAmount) + "U @" + formatTime.format(getDanaRPump().lastBolusTime) + "\n";
|
||||||
|
}
|
||||||
|
if (isRealTempBasalInProgress()) {
|
||||||
|
ret += "Temp: " + getRealTempBasal().toString() + "\n";
|
||||||
|
}
|
||||||
|
if (isExtendedBoluslInProgress()) {
|
||||||
|
ret += "Extended: " + getExtendedBolus().toString() + "\n";
|
||||||
|
}
|
||||||
|
ret += "IOB: " + getDanaRPump().iob + "U\n";
|
||||||
|
ret += "Reserv: " + DecimalFormatter.to0Decimal(getDanaRPump().reservoirRemainingUnits) + "U\n";
|
||||||
|
ret += "Batt: " + getDanaRPump().batteryRemaining + "\n";
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
// TODO: daily total constraint
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,158 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR;
|
||||||
|
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.text.DecimalFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.Constants;
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
import info.nightscout.client.data.NSProfile;
|
||||||
|
import info.nightscout.utils.SafeParse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 04.07.2016.
|
||||||
|
*/
|
||||||
|
public class DanaRPump {
|
||||||
|
public static final int UNITS_MGDL = 0;
|
||||||
|
public static final int UNITS_MMOL = 1;
|
||||||
|
|
||||||
|
public Date lastConnection = new Date(0);
|
||||||
|
public Date lastSettingsRead = new Date(0);
|
||||||
|
|
||||||
|
// Info
|
||||||
|
public String serialNumber = "";
|
||||||
|
public Date shippingDate = new Date(0);
|
||||||
|
public String shippingCountry = "";
|
||||||
|
public boolean isNewPump = false;
|
||||||
|
public int password = -1;
|
||||||
|
public Date pumpTime = new Date(0);
|
||||||
|
|
||||||
|
// Status
|
||||||
|
public boolean pumpSuspended;
|
||||||
|
public boolean calculatorEnabled;
|
||||||
|
public double dailyTotalUnits;
|
||||||
|
public int maxDailyTotalUnits;
|
||||||
|
|
||||||
|
public double iob;
|
||||||
|
|
||||||
|
public double reservoirRemainingUnits;
|
||||||
|
public int batteryRemaining;
|
||||||
|
|
||||||
|
public boolean bolusBlocked;
|
||||||
|
public Date lastBolusTime = new Date(0);
|
||||||
|
public double lastBolusAmount;
|
||||||
|
|
||||||
|
public double currentBasal;
|
||||||
|
|
||||||
|
public boolean isTempBasalInProgress;
|
||||||
|
public int tempBasalPercent;
|
||||||
|
public int tempBasalRemainingMin;
|
||||||
|
public int tempBasalTotalSec;
|
||||||
|
public Date tempBasalStart;
|
||||||
|
|
||||||
|
public boolean isExtendedInProgress;
|
||||||
|
public int extendedBolusMinutes;
|
||||||
|
public double extendedBolusAmount;
|
||||||
|
public double extendedBolusAbsoluteRate;
|
||||||
|
public int extendedBolusSoFarInMinutes;
|
||||||
|
public Date extendedBolusStart;
|
||||||
|
public int extendedBolusRemainingMinutes;
|
||||||
|
|
||||||
|
// Profile
|
||||||
|
public int units;
|
||||||
|
public int easyBasalMode;
|
||||||
|
public boolean basal48Enable = false;
|
||||||
|
public int currentCIR;
|
||||||
|
public double currentCF;
|
||||||
|
public double currentAI;
|
||||||
|
public double currentTarget;
|
||||||
|
public int currentAIDR;
|
||||||
|
|
||||||
|
public int morningCIR;
|
||||||
|
public double morningCF;
|
||||||
|
public int afternoonCIR;
|
||||||
|
public double afternoonCF;
|
||||||
|
public int eveningCIR;
|
||||||
|
public double eveningCF;
|
||||||
|
public int nightCIR;
|
||||||
|
public double nightCF;
|
||||||
|
|
||||||
|
|
||||||
|
public int activeProfile = 0;
|
||||||
|
public double[][] pumpProfiles = null;
|
||||||
|
|
||||||
|
//Limits
|
||||||
|
public double maxBolus;
|
||||||
|
public double maxBasal;
|
||||||
|
|
||||||
|
public NSProfile createConvertedProfile() {
|
||||||
|
JSONObject json = new JSONObject();
|
||||||
|
JSONObject store = new JSONObject();
|
||||||
|
JSONObject profile = new JSONObject();
|
||||||
|
|
||||||
|
// Morning / 6:00–10:59
|
||||||
|
// Afternoon / 11:00–16:59
|
||||||
|
// Evening / 17:00–21:59
|
||||||
|
// Night / 22:00–5:59
|
||||||
|
|
||||||
|
SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
|
||||||
|
double dia = SafeParse.stringToDouble(SP.getString("danarprofile_dia", "3"));
|
||||||
|
double car = SafeParse.stringToDouble(SP.getString("danarprofile_car", "20"));
|
||||||
|
|
||||||
|
try {
|
||||||
|
json.put("defaultProfile", "" + (activeProfile + 1));
|
||||||
|
json.put("store", store);
|
||||||
|
profile.put("dia", dia);
|
||||||
|
|
||||||
|
JSONArray carbratios = new JSONArray();
|
||||||
|
carbratios.put(new JSONObject().put("time", "00:00").put("timeAsSeconds", 0).put("value", nightCF));
|
||||||
|
carbratios.put(new JSONObject().put("time", "06:00").put("timeAsSeconds", 6 * 3600).put("value", morningCF));
|
||||||
|
carbratios.put(new JSONObject().put("time", "11:00").put("timeAsSeconds", 11 * 3600).put("value", afternoonCF));
|
||||||
|
carbratios.put(new JSONObject().put("time", "14:00").put("timeAsSeconds", 17 * 3600).put("value", eveningCF));
|
||||||
|
carbratios.put(new JSONObject().put("time", "22:00").put("timeAsSeconds", 22 * 3600).put("value", nightCF));
|
||||||
|
profile.put("carbratio", carbratios);
|
||||||
|
|
||||||
|
profile.put("carbs_hr", car);
|
||||||
|
|
||||||
|
JSONArray sens = new JSONArray();
|
||||||
|
sens.put(new JSONObject().put("time", "00:00").put("timeAsSeconds", 0).put("value", nightCIR));
|
||||||
|
sens.put(new JSONObject().put("time", "06:00").put("timeAsSeconds", 6 * 3600).put("value", morningCIR));
|
||||||
|
sens.put(new JSONObject().put("time", "11:00").put("timeAsSeconds", 11 * 3600).put("value", afternoonCIR));
|
||||||
|
sens.put(new JSONObject().put("time", "17:00").put("timeAsSeconds", 17 * 3600).put("value", eveningCIR));
|
||||||
|
sens.put(new JSONObject().put("time", "22:00").put("timeAsSeconds", 22 * 3600).put("value", nightCIR));
|
||||||
|
profile.put("sens", sens);
|
||||||
|
|
||||||
|
JSONArray basals = new JSONArray();
|
||||||
|
int basalValues = basal48Enable ? 48 : 24;
|
||||||
|
int basalIncrement = basal48Enable ? 30 * 60 : 60 * 60;
|
||||||
|
for (int h = 0; h < basalValues; h++) {
|
||||||
|
String time;
|
||||||
|
DecimalFormat df = new DecimalFormat("00");
|
||||||
|
if (basal48Enable) {
|
||||||
|
time = df.format((long) h / 2) + ":" + df.format(30 * (h % 2));
|
||||||
|
} else {
|
||||||
|
time = df.format(h) + ":00";
|
||||||
|
}
|
||||||
|
basals.put(new JSONObject().put("time", time).put("timeAsSeconds", h * basalIncrement).put("value", pumpProfiles[activeProfile][h]));
|
||||||
|
}
|
||||||
|
profile.put("basal", basals);
|
||||||
|
|
||||||
|
profile.put("target_low", new JSONArray().put(new JSONObject().put("time", "00:00").put("timeAsSeconds", 0).put("value", currentTarget)));
|
||||||
|
profile.put("target_high", new JSONArray().put(new JSONObject().put("time", "00:00").put("timeAsSeconds", 0).put("value", currentTarget)));
|
||||||
|
profile.put("units", units == UNITS_MGDL ? Constants.MGDL : Constants.MMOL);
|
||||||
|
store.put("" + (activeProfile + 1), profile);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return new NSProfile(json, "" + (activeProfile + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,112 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR.Dialogs;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.HandlerThread;
|
||||||
|
import android.support.v4.app.DialogFragment;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.MainActivity;
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
import info.nightscout.androidaps.R;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.DanaRFragment;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin;
|
||||||
|
import info.nightscout.client.data.NSProfile;
|
||||||
|
import info.nightscout.utils.DecimalFormatter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 10.07.2016.
|
||||||
|
*/
|
||||||
|
public class ProfileViewDialog extends DialogFragment {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(ProfileViewDialog.class);
|
||||||
|
|
||||||
|
private static TextView noProfile;
|
||||||
|
private static TextView units;
|
||||||
|
private static TextView dia;
|
||||||
|
private static TextView activeProfile;
|
||||||
|
private static TextView ic;
|
||||||
|
private static TextView isf;
|
||||||
|
private static TextView basal;
|
||||||
|
private static TextView target;
|
||||||
|
|
||||||
|
private static Button refreshButton;
|
||||||
|
|
||||||
|
Handler mHandler;
|
||||||
|
static HandlerThread mHandlerThread;
|
||||||
|
|
||||||
|
NSProfile profile = null;
|
||||||
|
|
||||||
|
public ProfileViewDialog() {
|
||||||
|
mHandlerThread = new HandlerThread(ProfileViewDialog.class.getSimpleName());
|
||||||
|
mHandlerThread.start();
|
||||||
|
|
||||||
|
mHandler = new Handler(mHandlerThread.getLooper());
|
||||||
|
profile = ((DanaRPlugin) MainApp.getSpecificPlugin(DanaRPlugin.class)).getProfile();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
|
Bundle savedInstanceState) {
|
||||||
|
View layout = inflater.inflate(R.layout.nsprofileviewer_fragment, container, false);
|
||||||
|
|
||||||
|
noProfile = (TextView) layout.findViewById(R.id.profileview_noprofile);
|
||||||
|
units = (TextView) layout.findViewById(R.id.profileview_units);
|
||||||
|
dia = (TextView) layout.findViewById(R.id.profileview_dia);
|
||||||
|
activeProfile = (TextView) layout.findViewById(R.id.profileview_activeprofile);
|
||||||
|
ic = (TextView) layout.findViewById(R.id.profileview_ic);
|
||||||
|
isf = (TextView) layout.findViewById(R.id.profileview_isf);
|
||||||
|
basal = (TextView) layout.findViewById(R.id.profileview_basal);
|
||||||
|
target = (TextView) layout.findViewById(R.id.profileview_target);
|
||||||
|
refreshButton = (Button) layout.findViewById(R.id.profileview_reload);
|
||||||
|
refreshButton.setVisibility(View.VISIBLE);
|
||||||
|
refreshButton.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
mHandler.post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
DanaRPlugin.getDanaRPump().lastSettingsRead = new Date(0);
|
||||||
|
DanaRPlugin.doConnect("ProfileViewDialog");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
dismiss();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
setContent();
|
||||||
|
return layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
getDialog().getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setContent() {
|
||||||
|
if (profile == null) {
|
||||||
|
noProfile.setVisibility(View.VISIBLE);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
noProfile.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
units.setText(profile.getUnits());
|
||||||
|
dia.setText(DecimalFormatter.to2Decimal(profile.getDia()) + " h");
|
||||||
|
activeProfile.setText(profile.getActiveProfile());
|
||||||
|
ic.setText(profile.getIcList());
|
||||||
|
isf.setText(profile.getIsfList());
|
||||||
|
basal.setText(profile.getBasalList());
|
||||||
|
target.setText(profile.getTargetList());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,451 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR.History;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.ComponentName;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.ServiceConnection;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.HandlerThread;
|
||||||
|
import android.os.IBinder;
|
||||||
|
import android.support.v7.widget.CardView;
|
||||||
|
import android.support.v7.widget.LinearLayoutManager;
|
||||||
|
import android.support.v7.widget.RecyclerView;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.AdapterView;
|
||||||
|
import android.widget.ArrayAdapter;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.Spinner;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.j256.ormlite.dao.Dao;
|
||||||
|
import com.j256.ormlite.stmt.PreparedQuery;
|
||||||
|
import com.j256.ormlite.stmt.QueryBuilder;
|
||||||
|
import com.j256.ormlite.stmt.Where;
|
||||||
|
import com.squareup.otto.Subscribe;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.Constants;
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
import info.nightscout.androidaps.R;
|
||||||
|
import info.nightscout.androidaps.db.DanaRHistoryRecord;
|
||||||
|
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.Services.ExecutionService;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.comm.RecordTypes;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.events.EventDanaRConnectionStatus;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.events.EventDanaRSyncStatus;
|
||||||
|
import info.nightscout.client.data.NSProfile;
|
||||||
|
import info.nightscout.utils.DecimalFormatter;
|
||||||
|
import info.nightscout.utils.ToastUtils;
|
||||||
|
|
||||||
|
public class DanaRHistoryActivity extends Activity {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(DanaRHistoryActivity.class);
|
||||||
|
|
||||||
|
private boolean mBounded;
|
||||||
|
private static ExecutionService mExecutionService;
|
||||||
|
|
||||||
|
private Handler mHandler;
|
||||||
|
private static HandlerThread mHandlerThread;
|
||||||
|
|
||||||
|
static NSProfile profile = null;
|
||||||
|
|
||||||
|
Spinner historyTypeSpinner;
|
||||||
|
TextView statusView;
|
||||||
|
Button reloadButton;
|
||||||
|
Button syncButton;
|
||||||
|
RecyclerView recyclerView;
|
||||||
|
LinearLayoutManager llm;
|
||||||
|
|
||||||
|
static byte showingType = RecordTypes.RECORD_TYPE_ALARM;
|
||||||
|
List<DanaRHistoryRecord> historyList = new ArrayList<>();
|
||||||
|
|
||||||
|
public static class TypeList {
|
||||||
|
public byte type;
|
||||||
|
String name;
|
||||||
|
|
||||||
|
public TypeList(byte type, String name) {
|
||||||
|
this.type = type;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public DanaRHistoryActivity() {
|
||||||
|
super();
|
||||||
|
mHandlerThread = new HandlerThread(DanaRHistoryActivity.class.getSimpleName());
|
||||||
|
mHandlerThread.start();
|
||||||
|
this.mHandler = new Handler(mHandlerThread.getLooper());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStart() {
|
||||||
|
super.onStart();
|
||||||
|
Intent intent = new Intent(this, ExecutionService.class);
|
||||||
|
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
MainApp.bus().register(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPause() {
|
||||||
|
super.onPause();
|
||||||
|
MainApp.bus().unregister(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStop() {
|
||||||
|
super.onStop();
|
||||||
|
if (mBounded) {
|
||||||
|
unbindService(mConnection);
|
||||||
|
mBounded = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ServiceConnection mConnection = new ServiceConnection() {
|
||||||
|
|
||||||
|
public void onServiceDisconnected(ComponentName name) {
|
||||||
|
log.debug("Service is disconnected");
|
||||||
|
mBounded = false;
|
||||||
|
mExecutionService = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||||
|
log.debug("Service is connected");
|
||||||
|
mBounded = true;
|
||||||
|
ExecutionService.LocalBinder mLocalBinder = (ExecutionService.LocalBinder) service;
|
||||||
|
mExecutionService = mLocalBinder.getServiceInstance();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.danar_historyactivity);
|
||||||
|
|
||||||
|
historyTypeSpinner = (Spinner) findViewById(R.id.danar_historytype);
|
||||||
|
statusView = (TextView) findViewById(R.id.danar_historystatus);
|
||||||
|
reloadButton = (Button) findViewById(R.id.danar_historyreload);
|
||||||
|
syncButton = (Button) findViewById(R.id.danar_historysync);
|
||||||
|
recyclerView = (RecyclerView) findViewById(R.id.danar_history_recyclerview);
|
||||||
|
|
||||||
|
recyclerView.setHasFixedSize(true);
|
||||||
|
llm = new LinearLayoutManager(this);
|
||||||
|
recyclerView.setLayoutManager(llm);
|
||||||
|
|
||||||
|
RecyclerViewAdapter adapter = new RecyclerViewAdapter(historyList);
|
||||||
|
recyclerView.setAdapter(adapter);
|
||||||
|
|
||||||
|
statusView.setVisibility(View.GONE);
|
||||||
|
|
||||||
|
// Types
|
||||||
|
|
||||||
|
ArrayList<TypeList> typeList = new ArrayList<>();
|
||||||
|
typeList.add(new TypeList(RecordTypes.RECORD_TYPE_ALARM, getString(R.string.danar_history_alarm)));
|
||||||
|
typeList.add(new TypeList(RecordTypes.RECORD_TYPE_BASALHOUR, getString(R.string.danar_history_basalhours)));
|
||||||
|
typeList.add(new TypeList(RecordTypes.RECORD_TYPE_BOLUS, getString(R.string.danar_history_bolus)));
|
||||||
|
typeList.add(new TypeList(RecordTypes.RECORD_TYPE_CARBO, getString(R.string.danar_history_carbohydrates)));
|
||||||
|
typeList.add(new TypeList(RecordTypes.RECORD_TYPE_DAILY, getString(R.string.danar_history_dailyinsulin)));
|
||||||
|
typeList.add(new TypeList(RecordTypes.RECORD_TYPE_ERROR, getString(R.string.danar_history_errors)));
|
||||||
|
typeList.add(new TypeList(RecordTypes.RECORD_TYPE_GLUCOSE, getString(R.string.danar_history_glucose)));
|
||||||
|
typeList.add(new TypeList(RecordTypes.RECORD_TYPE_REFILL, getString(R.string.danar_history_refill)));
|
||||||
|
typeList.add(new TypeList(RecordTypes.RECORD_TYPE_SUSPEND, getString(R.string.danar_history_syspend)));
|
||||||
|
ArrayAdapter<TypeList> spinnerAdapter = new ArrayAdapter<>(this,
|
||||||
|
android.R.layout.simple_spinner_item, typeList);
|
||||||
|
spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||||
|
historyTypeSpinner.setAdapter(spinnerAdapter);
|
||||||
|
|
||||||
|
reloadButton.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
if (mExecutionService.isConnected() || mExecutionService.isConnecting()) {
|
||||||
|
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), getString(R.string.pumpbusy));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mHandler.post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
TypeList selected = (TypeList) historyTypeSpinner.getSelectedItem();
|
||||||
|
runOnUiThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
reloadButton.setVisibility(View.GONE);
|
||||||
|
syncButton.setVisibility(View.GONE);
|
||||||
|
statusView.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
clearCardView();
|
||||||
|
mExecutionService.loadHistory(selected.type);
|
||||||
|
loadDataFromDB(selected.type);
|
||||||
|
runOnUiThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
reloadButton.setVisibility(View.VISIBLE);
|
||||||
|
syncButton.setVisibility(View.VISIBLE);
|
||||||
|
statusView.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
syncButton.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
mHandler.post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
runOnUiThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
reloadButton.setVisibility(View.GONE);
|
||||||
|
syncButton.setVisibility(View.GONE);
|
||||||
|
statusView.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
DanaRNSHistorySync sync = new DanaRNSHistorySync(historyList);
|
||||||
|
sync.sync(DanaRNSHistorySync.SYNC_ALL);
|
||||||
|
runOnUiThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
reloadButton.setVisibility(View.VISIBLE);
|
||||||
|
syncButton.setVisibility(View.VISIBLE);
|
||||||
|
statusView.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
historyTypeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
||||||
|
@Override
|
||||||
|
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
||||||
|
TypeList selected = (TypeList) historyTypeSpinner.getSelectedItem();
|
||||||
|
loadDataFromDB(selected.type);
|
||||||
|
showingType = selected.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNothingSelected(AdapterView<?> parent) {
|
||||||
|
clearCardView();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
profile = ConfigBuilderPlugin.getActiveProfile().getProfile();
|
||||||
|
if (profile == null) {
|
||||||
|
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.noprofile));
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.HistoryViewHolder> {
|
||||||
|
|
||||||
|
List<DanaRHistoryRecord> historyList;
|
||||||
|
|
||||||
|
RecyclerViewAdapter(List<DanaRHistoryRecord> historyList) {
|
||||||
|
this.historyList = historyList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HistoryViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
|
||||||
|
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.danar_history_item, viewGroup, false);
|
||||||
|
return new HistoryViewHolder(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(HistoryViewHolder holder, int position) {
|
||||||
|
DateFormat df = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT);
|
||||||
|
DanaRHistoryRecord record = historyList.get(position);
|
||||||
|
holder.time.setText(df.format(new Date(record.getRecordDate())));
|
||||||
|
holder.value.setText(DecimalFormatter.to2Decimal(record.getRecordValue()));
|
||||||
|
holder.stringvalue.setText(record.getStringRecordValue());
|
||||||
|
holder.bolustype.setText(record.getBolusType());
|
||||||
|
holder.duration.setText(DecimalFormatter.to0Decimal(record.getRecordDuration()));
|
||||||
|
holder.dailybasal.setText(DecimalFormatter.to2Decimal(record.getRecordDailyBasal()) + "U");
|
||||||
|
holder.dailybolus.setText(DecimalFormatter.to2Decimal(record.getRecordDailyBolus()) + "U");
|
||||||
|
holder.alarm.setText(record.getRecordAlarm());
|
||||||
|
switch (showingType) {
|
||||||
|
case RecordTypes.RECORD_TYPE_ALARM:
|
||||||
|
holder.time.setVisibility(View.VISIBLE);
|
||||||
|
holder.value.setVisibility(View.VISIBLE);
|
||||||
|
holder.stringvalue.setVisibility(View.GONE);
|
||||||
|
holder.bolustype.setVisibility(View.GONE);
|
||||||
|
holder.duration.setVisibility(View.GONE);
|
||||||
|
holder.dailybasal.setVisibility(View.GONE);
|
||||||
|
holder.dailybolus.setVisibility(View.GONE);
|
||||||
|
holder.alarm.setVisibility(View.VISIBLE);
|
||||||
|
break;
|
||||||
|
case RecordTypes.RECORD_TYPE_BOLUS:
|
||||||
|
holder.time.setVisibility(View.VISIBLE);
|
||||||
|
holder.value.setVisibility(View.VISIBLE);
|
||||||
|
holder.stringvalue.setVisibility(View.GONE);
|
||||||
|
holder.bolustype.setVisibility(View.VISIBLE);
|
||||||
|
holder.duration.setVisibility(View.VISIBLE);
|
||||||
|
holder.dailybasal.setVisibility(View.GONE);
|
||||||
|
holder.dailybolus.setVisibility(View.GONE);
|
||||||
|
holder.alarm.setVisibility(View.GONE);
|
||||||
|
break;
|
||||||
|
case RecordTypes.RECORD_TYPE_DAILY:
|
||||||
|
holder.time.setVisibility(View.VISIBLE);
|
||||||
|
holder.value.setVisibility(View.GONE);
|
||||||
|
holder.stringvalue.setVisibility(View.GONE);
|
||||||
|
holder.bolustype.setVisibility(View.GONE);
|
||||||
|
holder.duration.setVisibility(View.GONE);
|
||||||
|
holder.dailybasal.setVisibility(View.VISIBLE);
|
||||||
|
holder.dailybolus.setVisibility(View.VISIBLE);
|
||||||
|
holder.alarm.setVisibility(View.GONE);
|
||||||
|
break;
|
||||||
|
case RecordTypes.RECORD_TYPE_GLUCOSE:
|
||||||
|
holder.value.setText(NSProfile.toUnitsString(record.getRecordValue(), record.getRecordValue() * Constants.MGDL_TO_MMOLL, profile.getUnits()));
|
||||||
|
// rest is the same
|
||||||
|
case RecordTypes.RECORD_TYPE_CARBO:
|
||||||
|
case RecordTypes.RECORD_TYPE_BASALHOUR:
|
||||||
|
case RecordTypes.RECORD_TYPE_ERROR:
|
||||||
|
case RecordTypes.RECORD_TYPE_PRIME:
|
||||||
|
case RecordTypes.RECORD_TYPE_REFILL:
|
||||||
|
case RecordTypes.RECORD_TYPE_TB:
|
||||||
|
holder.time.setVisibility(View.VISIBLE);
|
||||||
|
holder.value.setVisibility(View.VISIBLE);
|
||||||
|
holder.stringvalue.setVisibility(View.GONE);
|
||||||
|
holder.bolustype.setVisibility(View.GONE);
|
||||||
|
holder.duration.setVisibility(View.GONE);
|
||||||
|
holder.dailybasal.setVisibility(View.GONE);
|
||||||
|
holder.dailybolus.setVisibility(View.GONE);
|
||||||
|
holder.alarm.setVisibility(View.GONE);
|
||||||
|
break;
|
||||||
|
case RecordTypes.RECORD_TYPE_SUSPEND:
|
||||||
|
holder.time.setVisibility(View.VISIBLE);
|
||||||
|
holder.value.setVisibility(View.GONE);
|
||||||
|
holder.stringvalue.setVisibility(View.VISIBLE);
|
||||||
|
holder.bolustype.setVisibility(View.GONE);
|
||||||
|
holder.duration.setVisibility(View.GONE);
|
||||||
|
holder.dailybasal.setVisibility(View.GONE);
|
||||||
|
holder.dailybolus.setVisibility(View.GONE);
|
||||||
|
holder.alarm.setVisibility(View.GONE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return historyList.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
|
||||||
|
super.onAttachedToRecyclerView(recyclerView);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class HistoryViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
CardView cv;
|
||||||
|
TextView time;
|
||||||
|
TextView value;
|
||||||
|
TextView bolustype;
|
||||||
|
TextView stringvalue;
|
||||||
|
TextView duration;
|
||||||
|
TextView dailybasal;
|
||||||
|
TextView dailybolus;
|
||||||
|
TextView alarm;
|
||||||
|
|
||||||
|
HistoryViewHolder(View itemView) {
|
||||||
|
super(itemView);
|
||||||
|
cv = (CardView) itemView.findViewById(R.id.danar_history_cardview);
|
||||||
|
time = (TextView) itemView.findViewById(R.id.danar_history_time);
|
||||||
|
value = (TextView) itemView.findViewById(R.id.danar_history_value);
|
||||||
|
bolustype = (TextView) itemView.findViewById(R.id.danar_history_bolustype);
|
||||||
|
stringvalue = (TextView) itemView.findViewById(R.id.danar_history_stringvalue);
|
||||||
|
duration = (TextView) itemView.findViewById(R.id.danar_history_duration);
|
||||||
|
dailybasal = (TextView) itemView.findViewById(R.id.danar_history_dailybasal);
|
||||||
|
dailybolus = (TextView) itemView.findViewById(R.id.danar_history_dailybolus);
|
||||||
|
alarm = (TextView) itemView.findViewById(R.id.danar_history_alarm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadDataFromDB(byte type) {
|
||||||
|
try {
|
||||||
|
Dao<DanaRHistoryRecord, String> dao = MainApp.getDbHelper().getDaoDanaRHistory();
|
||||||
|
QueryBuilder<DanaRHistoryRecord, String> queryBuilder = dao.queryBuilder();
|
||||||
|
queryBuilder.orderBy("recordDate", false);
|
||||||
|
Where where = queryBuilder.where();
|
||||||
|
where.eq("recordCode", type);
|
||||||
|
queryBuilder.limit(200L);
|
||||||
|
PreparedQuery<DanaRHistoryRecord> preparedQuery = queryBuilder.prepare();
|
||||||
|
historyList = dao.query(preparedQuery);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
historyList = new ArrayList<>();
|
||||||
|
}
|
||||||
|
runOnUiThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
recyclerView.swapAdapter(new RecyclerViewAdapter(historyList), false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clearCardView() {
|
||||||
|
historyList = new ArrayList<>();
|
||||||
|
runOnUiThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
recyclerView.swapAdapter(new RecyclerViewAdapter(historyList), false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onStatusEvent(final EventDanaRSyncStatus s) {
|
||||||
|
log.debug("EventDanaRSyncStatus: " + s.message);
|
||||||
|
runOnUiThread(
|
||||||
|
new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
statusView.setText(s.message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onStatusEvent(final EventDanaRConnectionStatus c) {
|
||||||
|
runOnUiThread(
|
||||||
|
new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (c.sStatus == EventDanaRConnectionStatus.CONNECTING) {
|
||||||
|
statusView.setText(String.format(getString(R.string.danar_history_connectingfor), c.sSecondsElapsed));
|
||||||
|
log.debug("EventDanaRConnectionStatus: " + "Connecting for " + c.sSecondsElapsed + "s");
|
||||||
|
} else if (c.sStatus == EventDanaRConnectionStatus.CONNECTED) {
|
||||||
|
statusView.setText(MainApp.sResources.getString(R.string.connected));
|
||||||
|
log.debug("EventDanaRConnectionStatus: Connected");
|
||||||
|
} else {
|
||||||
|
statusView.setText(MainApp.sResources.getString(R.string.disconnected));
|
||||||
|
log.debug("EventDanaRConnectionStatus: Disconnected");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,230 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR.History;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
import info.nightscout.androidaps.R;
|
||||||
|
import info.nightscout.androidaps.db.DanaRHistoryRecord;
|
||||||
|
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.comm.RecordTypes;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.events.EventDanaRSyncStatus;
|
||||||
|
import info.nightscout.client.data.NSProfile;
|
||||||
|
import info.nightscout.utils.DateUtil;
|
||||||
|
import info.nightscout.utils.ToastUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 20.07.2016.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class DanaRNSHistorySync {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(DanaRNSHistorySync.class);
|
||||||
|
private List<DanaRHistoryRecord> historyRecords;
|
||||||
|
|
||||||
|
public final static int SYNC_BOLUS = 0b00000001;
|
||||||
|
public final static int SYNC_ERROR = 0b00000010;
|
||||||
|
public final static int SYNC_REFILL = 0b00000100;
|
||||||
|
public final static int SYNC_GLUCOSE = 0b00001000;
|
||||||
|
public final static int SYNC_CARBO = 0b00010000;
|
||||||
|
public final static int SYNC_ALARM = 0b00100000;
|
||||||
|
public final static int SYNC_BASALHOURS = 0b01000000;
|
||||||
|
public final static int SYNC_ALL = 0b11111111;
|
||||||
|
|
||||||
|
public final static String DANARSIGNATURE = "DANARMESSAGE";
|
||||||
|
|
||||||
|
public DanaRNSHistorySync(List<DanaRHistoryRecord> historyRecords) {
|
||||||
|
this.historyRecords = historyRecords;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void sync(int what) {
|
||||||
|
try {
|
||||||
|
ConfigBuilderPlugin ConfigBuilderPlugin = MainApp.getConfigBuilder();
|
||||||
|
NSProfile profile = ConfigBuilderPlugin.getActiveProfile().getProfile();
|
||||||
|
if (profile == null) {
|
||||||
|
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.noprofile));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Calendar cal = Calendar.getInstance();
|
||||||
|
long records = historyRecords.size();
|
||||||
|
long processing = 0;
|
||||||
|
long uploaded = 0;
|
||||||
|
log.debug("Database contains " + records + " records");
|
||||||
|
EventDanaRSyncStatus ev = new EventDanaRSyncStatus();
|
||||||
|
for (DanaRHistoryRecord record : historyRecords) {
|
||||||
|
processing++;
|
||||||
|
if (record.get_id() != null) continue;
|
||||||
|
//log.debug(record.getBytes());
|
||||||
|
JSONObject nsrec = new JSONObject();
|
||||||
|
ev.message = MainApp.sResources.getString(R.string.uploading) + " " + processing + "/" + records + " "; // TODO: translations
|
||||||
|
switch (record.getRecordCode()) {
|
||||||
|
case RecordTypes.RECORD_TYPE_BOLUS:
|
||||||
|
if ((what & SYNC_BOLUS) == 0) break;
|
||||||
|
switch (record.getBolusType()) {
|
||||||
|
case "S":
|
||||||
|
log.debug("Syncing standard bolus record " + record.getRecordValue() + "U " + DateUtil.toISOString(record.getRecordDate()));
|
||||||
|
nsrec.put(DANARSIGNATURE, record.getBytes());
|
||||||
|
nsrec.put("eventType", "Meal Bolus");
|
||||||
|
nsrec.put("insulin", record.getRecordValue());
|
||||||
|
nsrec.put("created_at", DateUtil.toISOString(record.getRecordDate()));
|
||||||
|
nsrec.put("enteredBy", MainApp.sResources.getString(R.string.app_name));
|
||||||
|
ConfigBuilderPlugin.uploadCareportalEntryToNS(nsrec);
|
||||||
|
uploaded++;
|
||||||
|
ev.message += MainApp.sResources.getString(R.string.danar_sbolus);
|
||||||
|
break;
|
||||||
|
case "E":
|
||||||
|
if (record.getRecordDuration() > 0) {
|
||||||
|
log.debug("Syncing extended bolus record " + record.getRecordValue() + "U " + DateUtil.toISOString(record.getRecordDate()));
|
||||||
|
nsrec.put(DANARSIGNATURE, record.getBytes());
|
||||||
|
nsrec.put("eventType", "Combo Bolus");
|
||||||
|
nsrec.put("insulin", 0);
|
||||||
|
nsrec.put("duration", record.getRecordDuration());
|
||||||
|
nsrec.put("relative", record.getRecordValue() / record.getRecordDuration() * 60);
|
||||||
|
nsrec.put("splitNow", 0);
|
||||||
|
nsrec.put("splitExt", 100);
|
||||||
|
cal.setTimeInMillis(record.getRecordDate());
|
||||||
|
cal.add(Calendar.MINUTE, -1 * record.getRecordDuration());
|
||||||
|
nsrec.put("created_at", DateUtil.toISOString(cal.getTime()));
|
||||||
|
nsrec.put("enteredBy", MainApp.sResources.getString(R.string.app_name));
|
||||||
|
ConfigBuilderPlugin.uploadCareportalEntryToNS(nsrec);
|
||||||
|
uploaded++;
|
||||||
|
ev.message += MainApp.sResources.getString(R.string.danar_ebolus);
|
||||||
|
} else {
|
||||||
|
log.debug("NOT Syncing extended bolus record " + record.getRecordValue() + "U " + DateUtil.toISOString(record.getRecordDate()) + " zero duration");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "DS":
|
||||||
|
log.debug("Syncing dual(S) bolus record " + record.getRecordValue() + "U " + DateUtil.toISOString(record.getRecordDate()));
|
||||||
|
nsrec.put(DANARSIGNATURE, record.getBytes());
|
||||||
|
nsrec.put("eventType", "Combo Bolus");
|
||||||
|
nsrec.put("insulin", record.getRecordValue());
|
||||||
|
nsrec.put("splitNow", 100);
|
||||||
|
nsrec.put("splitExt", 0);
|
||||||
|
nsrec.put("created_at", DateUtil.toISOString(record.getRecordDate()));
|
||||||
|
nsrec.put("enteredBy", MainApp.sResources.getString(R.string.app_name));
|
||||||
|
ConfigBuilderPlugin.uploadCareportalEntryToNS(nsrec);
|
||||||
|
uploaded++;
|
||||||
|
ev.message += MainApp.sResources.getString(R.string.danar_dsbolus);
|
||||||
|
break;
|
||||||
|
case "DE":
|
||||||
|
log.debug("Syncing dual(E) bolus record " + record.getRecordValue() + "U " + DateUtil.toISOString(record.getRecordDate()));
|
||||||
|
nsrec.put(DANARSIGNATURE, record.getBytes());
|
||||||
|
nsrec.put("eventType", "Combo Bolus");
|
||||||
|
nsrec.put("duration", record.getRecordDuration());
|
||||||
|
nsrec.put("relative", record.getRecordValue() / record.getRecordDuration() * 60);
|
||||||
|
nsrec.put("splitNow", 0);
|
||||||
|
nsrec.put("splitExt", 100);
|
||||||
|
cal.setTimeInMillis(record.getRecordDate());
|
||||||
|
cal.add(Calendar.MINUTE, -1 * record.getRecordDuration());
|
||||||
|
nsrec.put("created_at", DateUtil.toISOString(cal.getTime()));
|
||||||
|
nsrec.put("enteredBy", MainApp.sResources.getString(R.string.app_name));
|
||||||
|
ConfigBuilderPlugin.uploadCareportalEntryToNS(nsrec);
|
||||||
|
uploaded++;
|
||||||
|
ev.message += MainApp.sResources.getString(R.string.danar_debolus);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
log.debug("Unknown bolus record");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case RecordTypes.RECORD_TYPE_ERROR:
|
||||||
|
if ((what & SYNC_ERROR) == 0) break;
|
||||||
|
log.debug("Syncing error record " + DateUtil.toISOString(record.getRecordDate()));
|
||||||
|
nsrec.put(DANARSIGNATURE, record.getBytes());
|
||||||
|
nsrec.put("eventType", "Note");
|
||||||
|
nsrec.put("notes", "Error");
|
||||||
|
nsrec.put("created_at", DateUtil.toISOString(record.getRecordDate()));
|
||||||
|
nsrec.put("enteredBy", MainApp.sResources.getString(R.string.app_name));
|
||||||
|
ConfigBuilderPlugin.uploadCareportalEntryToNS(nsrec);
|
||||||
|
uploaded++;
|
||||||
|
ev.message += MainApp.sResources.getString(R.string.danar_error);
|
||||||
|
break;
|
||||||
|
case RecordTypes.RECORD_TYPE_REFILL:
|
||||||
|
if ((what & SYNC_REFILL) == 0) break;
|
||||||
|
log.debug("Syncing refill record " + record.getRecordValue() + " " + DateUtil.toISOString(record.getRecordDate()));
|
||||||
|
nsrec.put(DANARSIGNATURE, record.getBytes());
|
||||||
|
nsrec.put("eventType", "Insulin Change");
|
||||||
|
nsrec.put("notes", "Refill " + record.getRecordValue() + "U");
|
||||||
|
nsrec.put("created_at", DateUtil.toISOString(record.getRecordDate()));
|
||||||
|
nsrec.put("enteredBy", MainApp.sResources.getString(R.string.app_name));
|
||||||
|
ConfigBuilderPlugin.uploadCareportalEntryToNS(nsrec);
|
||||||
|
uploaded++;
|
||||||
|
ev.message += MainApp.sResources.getString(R.string.danar_refill);
|
||||||
|
break;
|
||||||
|
case RecordTypes.RECORD_TYPE_BASALHOUR:
|
||||||
|
if ((what & SYNC_BASALHOURS) == 0) break;
|
||||||
|
log.debug("Syncing basal hour record " + record.getRecordValue() + " " + DateUtil.toISOString(record.getRecordDate()));
|
||||||
|
nsrec.put(DANARSIGNATURE, record.getBytes());
|
||||||
|
nsrec.put("eventType", "Temp Basal");
|
||||||
|
nsrec.put("absolute", record.getRecordValue());
|
||||||
|
nsrec.put("duration", 60);
|
||||||
|
nsrec.put("created_at", DateUtil.toISOString(record.getRecordDate()));
|
||||||
|
nsrec.put("enteredBy", MainApp.sResources.getString(R.string.app_name));
|
||||||
|
ConfigBuilderPlugin.uploadCareportalEntryToNS(nsrec);
|
||||||
|
uploaded++;
|
||||||
|
ev.message += MainApp.sResources.getString(R.string.danar_basalhour);
|
||||||
|
break;
|
||||||
|
case RecordTypes.RECORD_TYPE_TB:
|
||||||
|
//log.debug("Ignoring TB record " + record.getBytes() + " " + DateUtil.toISOString(record.getRecordDate()));
|
||||||
|
break;
|
||||||
|
case RecordTypes.RECORD_TYPE_GLUCOSE:
|
||||||
|
if ((what & SYNC_GLUCOSE) == 0) break;
|
||||||
|
log.debug("Syncing glucose record " + record.getRecordValue() + " " + DateUtil.toISOString(record.getRecordDate()));
|
||||||
|
nsrec.put(DANARSIGNATURE, record.getBytes());
|
||||||
|
nsrec.put("eventType", "BG Check");
|
||||||
|
nsrec.put("glucose", NSProfile.fromMgdlToUnits(record.getRecordValue(), profile.getUnits()));
|
||||||
|
nsrec.put("glucoseType", "Finger");
|
||||||
|
nsrec.put("created_at", DateUtil.toISOString(record.getRecordDate()));
|
||||||
|
nsrec.put("enteredBy", MainApp.sResources.getString(R.string.app_name));
|
||||||
|
ConfigBuilderPlugin.uploadCareportalEntryToNS(nsrec);
|
||||||
|
uploaded++;
|
||||||
|
ev.message += MainApp.sResources.getString(R.string.danar_glucose);
|
||||||
|
break;
|
||||||
|
case RecordTypes.RECORD_TYPE_CARBO:
|
||||||
|
if ((what & SYNC_CARBO) == 0) break;
|
||||||
|
log.debug("Syncing carbo record " + record.getRecordValue() + "g " + DateUtil.toISOString(record.getRecordDate()));
|
||||||
|
nsrec.put(DANARSIGNATURE, record.getBytes());
|
||||||
|
nsrec.put("eventType", "Meal Bolus");
|
||||||
|
nsrec.put("carbs", record.getRecordValue());
|
||||||
|
nsrec.put("created_at", DateUtil.toISOString(record.getRecordDate()));
|
||||||
|
nsrec.put("enteredBy", MainApp.sResources.getString(R.string.app_name));
|
||||||
|
ConfigBuilderPlugin.uploadCareportalEntryToNS(nsrec);
|
||||||
|
uploaded++;
|
||||||
|
ev.message += MainApp.sResources.getString(R.string.danar_carbohydrate);
|
||||||
|
break;
|
||||||
|
case RecordTypes.RECORD_TYPE_ALARM:
|
||||||
|
if ((what & SYNC_ALARM) == 0) break;
|
||||||
|
log.debug("Syncing alarm record " + record.getRecordAlarm() + " " + DateUtil.toISOString(record.getRecordDate()));
|
||||||
|
nsrec.put(DANARSIGNATURE, record.getBytes());
|
||||||
|
nsrec.put("eventType", "Note");
|
||||||
|
nsrec.put("notes", "Alarm: " + record.getRecordAlarm());
|
||||||
|
nsrec.put("created_at", DateUtil.toISOString(record.getRecordDate()));
|
||||||
|
nsrec.put("enteredBy", MainApp.sResources.getString(R.string.app_name));
|
||||||
|
ConfigBuilderPlugin.uploadCareportalEntryToNS(nsrec);
|
||||||
|
uploaded++;
|
||||||
|
ev.message += MainApp.sResources.getString(R.string.danar_alarm);
|
||||||
|
break;
|
||||||
|
case RecordTypes.RECORD_TYPE_SUSPEND: // TODO: this too
|
||||||
|
case RecordTypes.RECORD_TYPE_DAILY:
|
||||||
|
case RecordTypes.RECORD_TYPE_PRIME:
|
||||||
|
// Ignore
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
log.error("Unknown record type");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
MainApp.bus().post(ev);
|
||||||
|
}
|
||||||
|
ev.message = String.format(MainApp.sResources.getString(R.string.danar_totaluploaded), uploaded);
|
||||||
|
MainApp.bus().post(ev);
|
||||||
|
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,224 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothSocket;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
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.plugins.DanaR.comm.MessageBase;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.comm.MessageHashTable;
|
||||||
|
import info.nightscout.utils.CRC;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 17.07.2016.
|
||||||
|
*/
|
||||||
|
public class SerialIOThread extends Thread {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(SerialIOThread.class);
|
||||||
|
|
||||||
|
private InputStream mInputStream = null;
|
||||||
|
private OutputStream mOutputStream = null;
|
||||||
|
private BluetoothSocket mRfCommSocket;
|
||||||
|
|
||||||
|
private static final ScheduledExecutorService worker = Executors.newSingleThreadScheduledExecutor();
|
||||||
|
private static ScheduledFuture<?> scheduledDisconnection = null;
|
||||||
|
|
||||||
|
private boolean mKeepRunning = true;
|
||||||
|
private byte[] mReadBuff = new byte[0];
|
||||||
|
|
||||||
|
MessageBase processedMessage;
|
||||||
|
|
||||||
|
public SerialIOThread(BluetoothSocket rfcommSocket) {
|
||||||
|
super(SerialIOThread.class.toString());
|
||||||
|
|
||||||
|
mRfCommSocket = rfcommSocket;
|
||||||
|
try {
|
||||||
|
mOutputStream = mRfCommSocket.getOutputStream();
|
||||||
|
mInputStream = mRfCommSocket.getInputStream();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
this.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final void run() {
|
||||||
|
try {
|
||||||
|
while (mKeepRunning) {
|
||||||
|
int availableBytes = mInputStream.available();
|
||||||
|
// Ask for 1024 byte (or more if available)
|
||||||
|
byte[] newData = new byte[Math.max(1024, availableBytes)];
|
||||||
|
int gotBytes = mInputStream.read(newData);
|
||||||
|
// When we are here there is some new data available
|
||||||
|
appendToBuffer(newData, gotBytes);
|
||||||
|
|
||||||
|
// process all messages we already got
|
||||||
|
while (mReadBuff.length > 3) { // 3rd byte is packet size. continue only if we an determine packet size
|
||||||
|
byte[] extractedBuff = cutMessageFromBuffer();
|
||||||
|
if (extractedBuff == null) break; // message is not complete in buffer (wrong packet calls disconnection)
|
||||||
|
|
||||||
|
int command = (extractedBuff[5] & 0xFF) | ((extractedBuff[4] << 8) & 0xFF00);
|
||||||
|
|
||||||
|
MessageBase message;
|
||||||
|
if (processedMessage != null && processedMessage.getCommand() == command) {
|
||||||
|
message = processedMessage;
|
||||||
|
} else {
|
||||||
|
// get it from hash table
|
||||||
|
message = MessageHashTable.findMessage(command);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.logDanaMessageDetail)
|
||||||
|
log.debug("<<<<< " + message.getMessageName() + " " + message.toHexString(extractedBuff));
|
||||||
|
|
||||||
|
// process the message content
|
||||||
|
message.received = true;
|
||||||
|
message.handleMessage(extractedBuff);
|
||||||
|
synchronized (message) {
|
||||||
|
message.notify();
|
||||||
|
}
|
||||||
|
scheduleDisconnection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (Config.logDanaSerialEngine && e.getMessage().indexOf("bt socket closed") < 0)
|
||||||
|
log.error("Thread exception: ", e);
|
||||||
|
mKeepRunning = false;
|
||||||
|
}
|
||||||
|
disconnect("EndOfLoop");
|
||||||
|
}
|
||||||
|
|
||||||
|
void appendToBuffer(byte[] newData, int gotBytes) {
|
||||||
|
// add newData to mReadBuff
|
||||||
|
byte[] newReadBuff = new byte[mReadBuff.length + gotBytes];
|
||||||
|
System.arraycopy(mReadBuff, 0, newReadBuff, 0, mReadBuff.length);
|
||||||
|
System.arraycopy(newData, 0, newReadBuff, mReadBuff.length, gotBytes);
|
||||||
|
mReadBuff = newReadBuff;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] cutMessageFromBuffer() {
|
||||||
|
if (mReadBuff[0] == (byte) 0x7E && mReadBuff[1] == (byte) 0x7E) {
|
||||||
|
int length = (mReadBuff[2] & 0xFF) + 7;
|
||||||
|
// Check if we have enough data
|
||||||
|
if (mReadBuff.length < length) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (mReadBuff[length - 2] != (byte) 0x2E || mReadBuff[length - 1] != (byte) 0x2E) {
|
||||||
|
log.error("wrong packet lenght=" + length + " data " + MessageBase.toHexString(mReadBuff));
|
||||||
|
disconnect("wrong packet");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
short crc = CRC.getCrc16(mReadBuff, 3, length - 7);
|
||||||
|
byte crcByte0 = (byte) (crc >> 8 & 0xFF);
|
||||||
|
byte crcByte1 = (byte) (crc & 0xFF);
|
||||||
|
|
||||||
|
byte crcByte0received = mReadBuff[length - 4];
|
||||||
|
byte crcByte1received = mReadBuff[length - 3];
|
||||||
|
|
||||||
|
if (crcByte0 != crcByte0received || crcByte1 != crcByte1received) {
|
||||||
|
log.error("CRC Error" + String.format("%02x ", crcByte0) + String.format("%02x ", crcByte1) + String.format("%02x ", crcByte0received) + String.format("%02x ", crcByte1received));
|
||||||
|
disconnect("crc error");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// Packet is verified here. extract data
|
||||||
|
byte[] extractedBuff = new byte[length];
|
||||||
|
System.arraycopy(mReadBuff, 0, extractedBuff, 0, length);
|
||||||
|
// remove extracted data from read buffer
|
||||||
|
byte[] unprocessedData = new byte[mReadBuff.length - length];
|
||||||
|
System.arraycopy(mReadBuff, length, unprocessedData, 0, unprocessedData.length);
|
||||||
|
mReadBuff = unprocessedData;
|
||||||
|
return extractedBuff;
|
||||||
|
} else {
|
||||||
|
log.error("Wrong beginning of packet len=" + mReadBuff.length + " " + MessageBase.toHexString(mReadBuff));
|
||||||
|
disconnect("Wrong beginning of packet");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void sendMessage(MessageBase message) {
|
||||||
|
if (!mRfCommSocket.isConnected()) {
|
||||||
|
log.error("Socket not connected on sendMessage");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
processedMessage = message;
|
||||||
|
|
||||||
|
byte[] messageBytes = message.getRawMessageBytes();
|
||||||
|
if (Config.logDanaSerialEngine)
|
||||||
|
log.debug(">>>>> " + message.getMessageName() + " " + message.toHexString(messageBytes));
|
||||||
|
|
||||||
|
try {
|
||||||
|
mOutputStream.write(messageBytes);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("sendMessage write exception: ", e);
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized (message) {
|
||||||
|
try {
|
||||||
|
message.wait(5000);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
log.error("sendMessage InterruptedException", e);
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Thread.sleep(200);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
}
|
||||||
|
if (!message.received) {
|
||||||
|
log.warn("Reply not received " + message.getMessageName());
|
||||||
|
}
|
||||||
|
scheduleDisconnection();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void scheduleDisconnection() {
|
||||||
|
class DisconnectRunnable implements Runnable {
|
||||||
|
public void run() {
|
||||||
|
disconnect("scheduleDisconnection");
|
||||||
|
scheduledDisconnection = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// prepare task for execution in 5 sec
|
||||||
|
// cancel waiting task to prevent sending multiple disconnections
|
||||||
|
if (scheduledDisconnection != null)
|
||||||
|
scheduledDisconnection.cancel(false);
|
||||||
|
Runnable task = new DisconnectRunnable();
|
||||||
|
final int sec = 5;
|
||||||
|
scheduledDisconnection = worker.schedule(task, sec, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void disconnect(String reason) {
|
||||||
|
mKeepRunning = false;
|
||||||
|
try {
|
||||||
|
mInputStream.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (Config.logDanaSerialEngine) log.debug(e.getMessage());
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
mOutputStream.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (Config.logDanaSerialEngine) log.debug(e.getMessage());
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
mRfCommSocket.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (Config.logDanaSerialEngine) log.debug(e.getMessage());
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
System.runFinalization();
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (Config.logDanaSerialEngine) log.debug(e.getMessage());
|
||||||
|
}
|
||||||
|
if (Config.logDanaSerialEngine) log.debug("Disconnected: " + reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,491 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR.Services;
|
||||||
|
|
||||||
|
import android.app.Service;
|
||||||
|
import android.bluetooth.BluetoothAdapter;
|
||||||
|
import android.bluetooth.BluetoothDevice;
|
||||||
|
import android.bluetooth.BluetoothSocket;
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.IntentFilter;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.os.Binder;
|
||||||
|
import android.os.IBinder;
|
||||||
|
import android.os.PowerManager;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
|
|
||||||
|
import com.squareup.otto.Subscribe;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.Config;
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
import info.nightscout.androidaps.R;
|
||||||
|
import info.nightscout.androidaps.db.Treatment;
|
||||||
|
import info.nightscout.androidaps.events.EventAppExit;
|
||||||
|
import info.nightscout.androidaps.events.EventPreferenceChange;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.DanaRPump;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.SerialIOThread;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.comm.MessageBase;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.comm.MsgBolusProgress;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.comm.MsgBolusStart;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.comm.MsgBolusStop;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.comm.MsgCheckValue;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistoryAlarm;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistoryBasalHour;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistoryBolus;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistoryCarbo;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistoryDailyInsulin;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistoryDone;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistoryError;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistoryGlucose;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistoryRefill;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistorySuspend;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.comm.MsgPCCommStart;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.comm.MsgPCCommStop;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.comm.MsgSetActivateBasalProfile;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.comm.MsgSetBasalProfile;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.comm.MsgSetCarbsEntry;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.comm.MsgSetExtendedBolusStart;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.comm.MsgSetExtendedBolusStop;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.comm.MsgSetTempBasalStart;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.comm.MsgSetTempBasalStop;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.comm.MsgSettingActiveProfile;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.comm.MsgSettingBasal;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.comm.MsgSettingGlucose;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.comm.MsgSettingMaxValues;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.comm.MsgSettingProfileRatios;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.comm.MsgSettingProfileRatiosAll;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.comm.MsgSettingPumpTime;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.comm.MsgSettingShippingInfo;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.comm.MsgStatus;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.comm.MsgStatusBasic;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.comm.MsgStatusBolusExtended;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.comm.MsgStatusTempBasal;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.comm.RecordTypes;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.events.EventDanaRBolusStart;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.events.EventDanaRConnectionStatus;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.events.EventDanaRNewStatus;
|
||||||
|
import info.nightscout.client.data.NSProfile;
|
||||||
|
import info.nightscout.utils.SafeParse;
|
||||||
|
import info.nightscout.utils.ToastUtils;
|
||||||
|
|
||||||
|
public class ExecutionService extends Service {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(ExecutionService.class);
|
||||||
|
|
||||||
|
private SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
|
||||||
|
private String devName;
|
||||||
|
|
||||||
|
private SerialIOThread mSerialIOThread;
|
||||||
|
private BluetoothSocket mRfcommSocket;
|
||||||
|
private BluetoothDevice mBTDevice;
|
||||||
|
|
||||||
|
private PowerManager.WakeLock mWakeLock;
|
||||||
|
private IBinder mBinder = new LocalBinder();
|
||||||
|
|
||||||
|
private DanaRPump danaRPump;
|
||||||
|
private Treatment bolusingTreatment = null;
|
||||||
|
|
||||||
|
private static Boolean connectionInProgress = false;
|
||||||
|
private static final Object connectionLock = new Object();
|
||||||
|
|
||||||
|
private static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");
|
||||||
|
|
||||||
|
private BroadcastReceiver receiver = new BroadcastReceiver() {
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
|
||||||
|
String action = intent.getAction();
|
||||||
|
if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) {
|
||||||
|
log.debug("Device has disconnected " + device.getName());//Device has disconnected
|
||||||
|
if (mBTDevice != null && mBTDevice.getName().equals(device.getName())) {
|
||||||
|
if (mSerialIOThread != null) {
|
||||||
|
mSerialIOThread.disconnect("BT disconnection broadcast");
|
||||||
|
}
|
||||||
|
MainApp.bus().post(new EventDanaRConnectionStatus(EventDanaRConnectionStatus.DISCONNECTED, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public ExecutionService() {
|
||||||
|
registerBus();
|
||||||
|
MainApp.instance().getApplicationContext().registerReceiver(receiver, new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED));
|
||||||
|
danaRPump = DanaRPlugin.getDanaRPump();
|
||||||
|
|
||||||
|
PowerManager powerManager = (PowerManager) MainApp.instance().getApplicationContext().getSystemService(Context.POWER_SERVICE);
|
||||||
|
mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ExecutionService");
|
||||||
|
}
|
||||||
|
|
||||||
|
public class LocalBinder extends Binder {
|
||||||
|
public ExecutionService getServiceInstance() {
|
||||||
|
return ExecutionService.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");
|
||||||
|
|
||||||
|
if (mSerialIOThread != null)
|
||||||
|
mSerialIOThread.disconnect("Application exit");
|
||||||
|
|
||||||
|
MainApp.instance().getApplicationContext().unregisterReceiver(receiver);
|
||||||
|
|
||||||
|
stopSelf();
|
||||||
|
if (Config.logFunctionCalls)
|
||||||
|
log.debug("EventAppExit finished");
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isConnected() {
|
||||||
|
return mRfcommSocket != null && mRfcommSocket.isConnected();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isConnecting() {
|
||||||
|
return connectionInProgress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void connect(String from) {
|
||||||
|
if (danaRPump.password != -1 && danaRPump.password != SafeParse.stringToInt(SP.getString("danar_password", "-1"))) {
|
||||||
|
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.wrongpumppassword), R.raw.error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
while (isConnected() || isConnecting()) {
|
||||||
|
if (Config.logDanaBTComm)
|
||||||
|
log.debug("already connected/connecting from: " + from);
|
||||||
|
waitMsec(3000);
|
||||||
|
}
|
||||||
|
final long maxConnectionTime = 5 * 60 * 1000L; // 5 min
|
||||||
|
synchronized (connectionLock) {
|
||||||
|
//log.debug("entering connection while loop");
|
||||||
|
connectionInProgress = true;
|
||||||
|
mWakeLock.acquire();
|
||||||
|
getBTSocketForSelectedPump();
|
||||||
|
if (mRfcommSocket == null || mBTDevice == null)
|
||||||
|
return; // Device not found
|
||||||
|
long startTime = new Date().getTime();
|
||||||
|
while (!isConnected() && startTime + maxConnectionTime >= new Date().getTime()) {
|
||||||
|
long secondsElapsed = (new Date().getTime() - startTime) / 1000L;
|
||||||
|
MainApp.bus().post(new EventDanaRConnectionStatus(EventDanaRConnectionStatus.CONNECTING, (int) secondsElapsed));
|
||||||
|
if (Config.logDanaBTComm)
|
||||||
|
log.debug("connect waiting " + secondsElapsed + "sec from: " + from);
|
||||||
|
try {
|
||||||
|
mRfcommSocket.connect();
|
||||||
|
} catch (IOException e) {
|
||||||
|
//e.printStackTrace();
|
||||||
|
if (e.getMessage().contains("socket closed")) {
|
||||||
|
e.printStackTrace();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
waitMsec(1000);
|
||||||
|
|
||||||
|
if (isConnected()) {
|
||||||
|
if (mSerialIOThread != null) {
|
||||||
|
mSerialIOThread.disconnect("Recreate SerialIOThread");
|
||||||
|
}
|
||||||
|
mSerialIOThread = new SerialIOThread(mRfcommSocket);
|
||||||
|
MainApp.bus().post(new EventDanaRConnectionStatus(EventDanaRConnectionStatus.CONNECTED, 0));
|
||||||
|
if (!getPumpStatus()) {
|
||||||
|
mSerialIOThread.disconnect("getPumpStatus failed");
|
||||||
|
waitMsec(3000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!isConnected()) {
|
||||||
|
MainApp.bus().post(new EventDanaRConnectionStatus(EventDanaRConnectionStatus.DISCONNECTED, 0));
|
||||||
|
log.error("Pump connection timed out");
|
||||||
|
}
|
||||||
|
connectionInProgress = false;
|
||||||
|
mWakeLock.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getBTSocketForSelectedPump() {
|
||||||
|
devName = SP.getString("danar_bt_name", "");
|
||||||
|
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
|
||||||
|
|
||||||
|
if (bluetoothAdapter != null) {
|
||||||
|
Set<BluetoothDevice> bondedDevices = bluetoothAdapter.getBondedDevices();
|
||||||
|
|
||||||
|
for (BluetoothDevice device : bondedDevices) {
|
||||||
|
if (devName.equals(device.getName())) {
|
||||||
|
mBTDevice = device;
|
||||||
|
try {
|
||||||
|
mRfcommSocket = mBTDevice.createRfcommSocketToServiceRecord(SPP_UUID);
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("Error creating socket: ", e);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.nobtadapter));
|
||||||
|
}
|
||||||
|
if (mBTDevice == null) {
|
||||||
|
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.devicenotfound));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onStatusEvent(final EventPreferenceChange pch) {
|
||||||
|
if (mSerialIOThread != null)
|
||||||
|
mSerialIOThread.disconnect("EventPreferenceChange");
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean getPumpStatus() {
|
||||||
|
try {
|
||||||
|
MsgStatus statusMsg = new MsgStatus();
|
||||||
|
MsgStatusBasic statusBasicMsg = new MsgStatusBasic();
|
||||||
|
MsgStatusTempBasal tempStatusMsg = new MsgStatusTempBasal();
|
||||||
|
MsgStatusBolusExtended exStatusMsg = new MsgStatusBolusExtended();
|
||||||
|
|
||||||
|
|
||||||
|
mSerialIOThread.sendMessage(tempStatusMsg); // do this before statusBasic because here is temp duration
|
||||||
|
mSerialIOThread.sendMessage(exStatusMsg);
|
||||||
|
mSerialIOThread.sendMessage(statusMsg);
|
||||||
|
mSerialIOThread.sendMessage(statusBasicMsg);
|
||||||
|
mSerialIOThread.sendMessage(new MsgSettingShippingInfo()); // TODO: show it somewhere
|
||||||
|
|
||||||
|
if (danaRPump.isNewPump) {
|
||||||
|
mSerialIOThread.sendMessage(new MsgCheckValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!statusMsg.received) {
|
||||||
|
mSerialIOThread.sendMessage(statusMsg);
|
||||||
|
}
|
||||||
|
if (!statusBasicMsg.received) {
|
||||||
|
mSerialIOThread.sendMessage(statusBasicMsg);
|
||||||
|
}
|
||||||
|
if (!tempStatusMsg.received) {
|
||||||
|
// Load of status of current basal rate failed, give one more try
|
||||||
|
mSerialIOThread.sendMessage(tempStatusMsg);
|
||||||
|
}
|
||||||
|
if (!exStatusMsg.received) {
|
||||||
|
// Load of status of current extended bolus failed, give one more try
|
||||||
|
mSerialIOThread.sendMessage(exStatusMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check we have really current status of pump
|
||||||
|
if (!statusMsg.received || !statusBasicMsg.received || !tempStatusMsg.received || !exStatusMsg.received) {
|
||||||
|
waitMsec(10 * 1000);
|
||||||
|
log.debug("getPumpStatus failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Date now = new Date();
|
||||||
|
if (danaRPump.lastSettingsRead.getTime() + 60 * 60 * 1000L < now.getTime()) {
|
||||||
|
mSerialIOThread.sendMessage(new MsgSettingShippingInfo());
|
||||||
|
mSerialIOThread.sendMessage(new MsgSettingActiveProfile());
|
||||||
|
//0x3203
|
||||||
|
mSerialIOThread.sendMessage(new MsgSettingBasal());
|
||||||
|
//0x3201
|
||||||
|
mSerialIOThread.sendMessage(new MsgSettingMaxValues());
|
||||||
|
mSerialIOThread.sendMessage(new MsgSettingGlucose());
|
||||||
|
mSerialIOThread.sendMessage(new MsgSettingPumpTime());
|
||||||
|
mSerialIOThread.sendMessage(new MsgSettingActiveProfile());
|
||||||
|
mSerialIOThread.sendMessage(new MsgSettingProfileRatios());
|
||||||
|
mSerialIOThread.sendMessage(new MsgSettingProfileRatiosAll());
|
||||||
|
danaRPump.lastSettingsRead = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
danaRPump.lastConnection = now;
|
||||||
|
MainApp.bus().post(new EventDanaRNewStatus());
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean tempBasal(int percent, int durationInHours) {
|
||||||
|
connect("tempBasal");
|
||||||
|
if (!isConnected()) return false;
|
||||||
|
mSerialIOThread.sendMessage(new MsgSetTempBasalStart(percent, durationInHours));
|
||||||
|
mSerialIOThread.sendMessage(new MsgStatusTempBasal());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean tempBasalStop() {
|
||||||
|
connect("tempBasalStop");
|
||||||
|
if (!isConnected()) return false;
|
||||||
|
mSerialIOThread.sendMessage(new MsgSetTempBasalStop());
|
||||||
|
mSerialIOThread.sendMessage(new MsgStatusTempBasal());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean extendedBolus(double insulin, int durationInHalfHours) {
|
||||||
|
connect("extendedBolus");
|
||||||
|
if (!isConnected()) return false;
|
||||||
|
mSerialIOThread.sendMessage(new MsgSetExtendedBolusStart(insulin, (byte) (durationInHalfHours & 0xFF)));
|
||||||
|
mSerialIOThread.sendMessage(new MsgStatusBolusExtended());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean extendedBolusStop() {
|
||||||
|
connect("extendedBolusStop");
|
||||||
|
if (!isConnected()) return false;
|
||||||
|
mSerialIOThread.sendMessage(new MsgSetExtendedBolusStop());
|
||||||
|
mSerialIOThread.sendMessage(new MsgStatusBolusExtended());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean bolus(Double amount, int carbs, Treatment t) {
|
||||||
|
bolusingTreatment = t;
|
||||||
|
MsgBolusStart start = new MsgBolusStart(amount);
|
||||||
|
MsgBolusProgress progress = new MsgBolusProgress(MainApp.bus(), amount, t);
|
||||||
|
MsgBolusStop stop = new MsgBolusStop(MainApp.bus(), amount, t);
|
||||||
|
|
||||||
|
connect("bolus");
|
||||||
|
if (!isConnected()) return false;
|
||||||
|
|
||||||
|
if (carbs > 0) {
|
||||||
|
Calendar time = Calendar.getInstance();
|
||||||
|
mSerialIOThread.sendMessage(new MsgSetCarbsEntry(time, carbs));
|
||||||
|
}
|
||||||
|
MainApp.bus().post(new EventDanaRBolusStart());
|
||||||
|
|
||||||
|
if (!stop.stopped) {
|
||||||
|
mSerialIOThread.sendMessage(start);
|
||||||
|
} else {
|
||||||
|
t.insulin = 0d;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
while (!stop.stopped && !start.failed) {
|
||||||
|
waitMsec(100);
|
||||||
|
}
|
||||||
|
waitMsec(300);
|
||||||
|
bolusingTreatment = null;
|
||||||
|
getPumpStatus();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void bolusStop() {
|
||||||
|
if (Config.logDanaBTComm)
|
||||||
|
log.debug("bolusStop >>>>> @ " + (bolusingTreatment == null ? "" : bolusingTreatment.insulin));
|
||||||
|
MsgBolusStop stop = new MsgBolusStop();
|
||||||
|
stop.forced = true;
|
||||||
|
if (isConnected()) {
|
||||||
|
mSerialIOThread.sendMessage(stop);
|
||||||
|
while (!stop.stopped) {
|
||||||
|
mSerialIOThread.sendMessage(stop);
|
||||||
|
waitMsec(200);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
stop.stopped = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean carbsEntry(int amount) {
|
||||||
|
connect("carbsEntry");
|
||||||
|
if (!isConnected()) return false;
|
||||||
|
Calendar time = Calendar.getInstance();
|
||||||
|
MsgSetCarbsEntry msg = new MsgSetCarbsEntry(time, amount);
|
||||||
|
mSerialIOThread.sendMessage(msg);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean loadHistory(byte type) {
|
||||||
|
connect("loadHistory");
|
||||||
|
if (!isConnected()) return false;
|
||||||
|
MessageBase msg = null;
|
||||||
|
switch (type) {
|
||||||
|
case RecordTypes.RECORD_TYPE_ALARM:
|
||||||
|
msg = new MsgHistoryAlarm();
|
||||||
|
break;
|
||||||
|
case RecordTypes.RECORD_TYPE_BASALHOUR:
|
||||||
|
msg = new MsgHistoryBasalHour();
|
||||||
|
break;
|
||||||
|
case RecordTypes.RECORD_TYPE_BOLUS:
|
||||||
|
msg = new MsgHistoryBolus();
|
||||||
|
break;
|
||||||
|
case RecordTypes.RECORD_TYPE_CARBO:
|
||||||
|
msg = new MsgHistoryCarbo();
|
||||||
|
break;
|
||||||
|
case RecordTypes.RECORD_TYPE_DAILY:
|
||||||
|
msg = new MsgHistoryDailyInsulin();
|
||||||
|
break;
|
||||||
|
case RecordTypes.RECORD_TYPE_ERROR:
|
||||||
|
msg = new MsgHistoryError();
|
||||||
|
break;
|
||||||
|
case RecordTypes.RECORD_TYPE_GLUCOSE:
|
||||||
|
msg = new MsgHistoryGlucose();
|
||||||
|
break;
|
||||||
|
case RecordTypes.RECORD_TYPE_REFILL:
|
||||||
|
msg = new MsgHistoryRefill();
|
||||||
|
break;
|
||||||
|
case RecordTypes.RECORD_TYPE_SUSPEND:
|
||||||
|
msg = new MsgHistorySuspend();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
MsgHistoryDone done = new MsgHistoryDone();
|
||||||
|
mSerialIOThread.sendMessage(new MsgPCCommStart());
|
||||||
|
waitMsec(400);
|
||||||
|
mSerialIOThread.sendMessage(msg);
|
||||||
|
while (!done.received && mRfcommSocket.isConnected()) {
|
||||||
|
waitMsec(100);
|
||||||
|
}
|
||||||
|
waitMsec(200);
|
||||||
|
mSerialIOThread.sendMessage(new MsgPCCommStop());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean updateBasalsInPump(final NSProfile profile) {
|
||||||
|
connect("updateBasalsInPump");
|
||||||
|
if (!isConnected()) return false;
|
||||||
|
double[] basal = buildDanaRProfileRecord(profile);
|
||||||
|
MsgSetBasalProfile msgSet = new MsgSetBasalProfile((byte) 0, basal);
|
||||||
|
mSerialIOThread.sendMessage(msgSet);
|
||||||
|
MsgSetActivateBasalProfile msgActivate = new MsgSetActivateBasalProfile((byte) 0);
|
||||||
|
mSerialIOThread.sendMessage(msgActivate);
|
||||||
|
getPumpStatus();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private double[] buildDanaRProfileRecord(NSProfile nsProfile) {
|
||||||
|
double[] record = new double[24];
|
||||||
|
for (Integer hour = 0; hour < 24; hour++) {
|
||||||
|
double value = nsProfile.getBasal(hour * 60 * 60);
|
||||||
|
if (Config.logDanaMessageDetail)
|
||||||
|
log.debug("NS basal value for " + hour + ":00 is " + value);
|
||||||
|
record[hour] = value;
|
||||||
|
}
|
||||||
|
return record;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void waitMsec(long msecs) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(msecs);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,173 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR.comm;
|
||||||
|
|
||||||
|
import android.annotation.TargetApi;
|
||||||
|
import android.os.Build;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.GregorianCalendar;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.Config;
|
||||||
|
import info.nightscout.utils.CRC;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 00 01 02 03 04 05 06
|
||||||
|
*
|
||||||
|
* 7E 7E len F1 CMD SUB data CRC CRC 2E 2E
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class MessageBase {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(MessageBase.class);
|
||||||
|
private byte[] buffer = new byte[512];
|
||||||
|
private int position = 6;
|
||||||
|
|
||||||
|
public boolean received = false;
|
||||||
|
public boolean failed = false;
|
||||||
|
|
||||||
|
public void SetCommand(int cmd) {
|
||||||
|
this.buffer[4] = (byte) (cmd >> 8 & 0xFF);
|
||||||
|
this.buffer[5] = (byte) (cmd & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddParamByte(byte data) {
|
||||||
|
this.buffer[this.position++] = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddParamInt(int data) {
|
||||||
|
this.buffer[this.position++] = (byte) (data >> 8 & 0xFF);
|
||||||
|
this.buffer[this.position++] = (byte) (data & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddParamDate(GregorianCalendar date) {
|
||||||
|
AddParamByte((byte) (date.get(Calendar.YEAR) - 1900 - 100));
|
||||||
|
AddParamByte((byte) (date.get(Calendar.MONTH) + 1));
|
||||||
|
AddParamByte((byte) (date.get(Calendar.DAY_OF_MONTH)));
|
||||||
|
AddParamByte((byte) (date.get(Calendar.HOUR)));
|
||||||
|
AddParamByte((byte) (date.get(Calendar.MINUTE)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getRawMessageBytes() {
|
||||||
|
this.buffer[0] = (byte) 0x7E;
|
||||||
|
this.buffer[1] = (byte) 0x7E;
|
||||||
|
|
||||||
|
int length = this.position - 3;
|
||||||
|
|
||||||
|
this.buffer[2] = (byte) length;
|
||||||
|
this.buffer[3] = (byte) 0xF1;
|
||||||
|
|
||||||
|
this.AddParamInt(CRC.getCrc16(this.buffer, 3, length));
|
||||||
|
|
||||||
|
this.buffer[length + 5] = (byte) 0x2E;
|
||||||
|
this.buffer[length + 6] = (byte) 0x2E;
|
||||||
|
|
||||||
|
return Arrays.copyOf(buffer, length + 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMessageName() {
|
||||||
|
return MessageOriginalNames.getName(getCommand());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleMessage(byte[] bytes) {
|
||||||
|
if (Config.logDanaMessageDetail) {
|
||||||
|
if (bytes.length > 6) {
|
||||||
|
int command = (bytes[5] & 0xFF) | ((bytes[4] << 8) & 0xFF00);
|
||||||
|
log.debug("UNPROCESSED MSG: " + getMessageName() + " Command: " + String.format("%04X", command) + " Data: " + toHexString(bytes));
|
||||||
|
} else {
|
||||||
|
log.debug("MISFORMATTED MSG: " + toHexString(bytes));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCommand() {
|
||||||
|
int command = byteFromRawBuff(buffer, 5) | (byteFromRawBuff(buffer, 4) << 8);
|
||||||
|
return command;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int byteFromRawBuff(byte[] buff, int offset) {
|
||||||
|
return buff[offset] & 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int intFromBuff(byte[] buff, int offset, int length) {
|
||||||
|
offset += 6;
|
||||||
|
switch (length) {
|
||||||
|
case 1:
|
||||||
|
return byteFromRawBuff(buff, offset);
|
||||||
|
case 2:
|
||||||
|
return (byteFromRawBuff(buff, offset) << 8) + byteFromRawBuff(buff, offset + 1);
|
||||||
|
case 3:
|
||||||
|
return (byteFromRawBuff(buff, offset + 2) << 16) + (byteFromRawBuff(buff, offset + 1) << 8) + byteFromRawBuff(buff, offset);
|
||||||
|
case 4:
|
||||||
|
return (byteFromRawBuff(buff, offset + 3) << 24) + (byteFromRawBuff(buff, offset + 2) << 16) + (byteFromRawBuff(buff, offset + 1) << 8) + byteFromRawBuff(buff, offset);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Date dateTimeFromBuff(byte[] buff, int offset) {
|
||||||
|
Date date =
|
||||||
|
new Date(
|
||||||
|
100 + intFromBuff(buff, offset, 1),
|
||||||
|
intFromBuff(buff, offset + 1, 1) - 1,
|
||||||
|
intFromBuff(buff, offset + 2, 1),
|
||||||
|
intFromBuff(buff, offset + 3, 1),
|
||||||
|
intFromBuff(buff, offset + 4, 1),
|
||||||
|
0
|
||||||
|
);
|
||||||
|
return date;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Date dateTimeSecFromBuff(byte[] buff, int offset) {
|
||||||
|
Date date =
|
||||||
|
new Date(
|
||||||
|
100 + intFromBuff(buff, offset, 1),
|
||||||
|
intFromBuff(buff, offset + 1, 1) - 1,
|
||||||
|
intFromBuff(buff, offset + 2, 1),
|
||||||
|
intFromBuff(buff, offset + 3, 1),
|
||||||
|
intFromBuff(buff, offset + 4, 1),
|
||||||
|
intFromBuff(buff, offset + 5, 1)
|
||||||
|
);
|
||||||
|
return date;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Date dateFromBuff(byte[] buff, int offset) {
|
||||||
|
Date date =
|
||||||
|
new Date(
|
||||||
|
100 + intFromBuff(buff, offset, 1),
|
||||||
|
intFromBuff(buff, offset + 1, 1) - 1,
|
||||||
|
intFromBuff(buff, offset + 2, 1)
|
||||||
|
);
|
||||||
|
return date;
|
||||||
|
}
|
||||||
|
|
||||||
|
@TargetApi(Build.VERSION_CODES.KITKAT)
|
||||||
|
public static String stringFromBuff(byte[] buff, int offset, int length) {
|
||||||
|
byte[] strbuff = new byte[length];
|
||||||
|
System.arraycopy(buff, offset + 6, strbuff, 0, length);
|
||||||
|
return new String(strbuff, StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TargetApi(Build.VERSION_CODES.KITKAT)
|
||||||
|
public static String asciiStringFromBuff(byte[] buff, int offset, int length) {
|
||||||
|
byte[] strbuff = new byte[length];
|
||||||
|
System.arraycopy(buff, offset + 6, strbuff, 0, length);
|
||||||
|
for (int pos = 0; pos < length; pos++)
|
||||||
|
strbuff[pos] += 65; // "A"
|
||||||
|
return new String(strbuff, StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String toHexString(byte[] buff) {
|
||||||
|
StringBuffer sb = new StringBuffer();
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
for (byte element : buff) {
|
||||||
|
sb.append(String.format("%02x ", element));
|
||||||
|
if (++count % 4 == 0) sb.append(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR.comm;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 28.05.2016.
|
||||||
|
*/
|
||||||
|
public class MessageHashTable {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(MessageHashTable.class);
|
||||||
|
|
||||||
|
public static HashMap<Integer, MessageBase> messages = null;
|
||||||
|
|
||||||
|
static {
|
||||||
|
if (messages == null) {
|
||||||
|
messages = new HashMap<Integer, MessageBase>();
|
||||||
|
put(new MsgBolusStop()); // 0x0101 CMD_MEALINS_STOP
|
||||||
|
put(new MsgBolusStart()); // 0x0102 CMD_MEALINS_START_DATA
|
||||||
|
put(new MsgBolusProgress()); // 0x0202 CMD_PUMP_THIS_REMAINDER_MEAL_INS
|
||||||
|
put(new MsgStatusProfile()); // 0x0204 CMD_PUMP_CALCULATION_SETTING
|
||||||
|
put(new MsgStatusTempBasal()); // 0x0205 CMD_PUMP_EXERCISE_MODE
|
||||||
|
put(new MsgStatusBolusExtended()); // 0x0207 CMD_PUMP_EXPANS_INS_I
|
||||||
|
put(new MsgStatusBasic()); // 0x020A CMD_PUMP_INITVIEW_I
|
||||||
|
put(new MsgStatus()); // 0x020B CMD_PUMP_STATUS
|
||||||
|
put(new MsgInitConnStatusTime()); // 0x0301 CMD_PUMPINIT_TIME_INFO
|
||||||
|
put(new MsgInitConnStatusBolus()); // 0x0302 CMD_PUMPINIT_BOLUS_INFO
|
||||||
|
put(new MsgInitConnStatusBasic()); // 0x0303 CMD_PUMPINIT_INIT_INFO
|
||||||
|
put(new MsgInitConnStatusOption()); // 0x0304 CMD_PUMPINIT_OPTION
|
||||||
|
put(new MsgSetTempBasalStart()); // 0x0401 CMD_PUMPSET_EXERCISE_S
|
||||||
|
put(new MsgSetCarbsEntry()); // 0x0402 CMD_PUMPSET_HIS_S
|
||||||
|
put(new MsgSetTempBasalStop()); // 0x0403 CMD_PUMPSET_EXERCISE_STOP
|
||||||
|
put(new MsgSetExtendedBolusStop()); // 0x0406 CMD_PUMPSET_EXPANS_INS_STOP
|
||||||
|
put(new MsgSetExtendedBolusStart()); // 0x0407 CMD_PUMPSET_EXPANS_INS_S
|
||||||
|
put(new MsgOcclusion()); // 0x0601 CMD_PUMPOWAY_SYSTEM_STATUS
|
||||||
|
put(new MsgPCCommStart()); // 0x3001 CMD_CONNECT
|
||||||
|
put(new MsgPCCommStop()); // 0x3002 CMD_DISCONNECT
|
||||||
|
put(new MsgHistoryBolus()); // 0x3101 CMD_HISTORY_MEAL_INS
|
||||||
|
put(new MsgHistoryDailyInsulin()); // 0x3102 CMD_HISTORY_DAY_INS
|
||||||
|
put(new MsgHistoryGlucose()); // 0x3104 CMD_HISTORY_GLUCOSE
|
||||||
|
put(new MsgHistoryAlarm()); // 0x3105 CMD_HISTORY_ALARM
|
||||||
|
put(new MsgHistoryError()); // 0x3106 CMD_HISTORY_ERROR
|
||||||
|
put(new MsgHistoryCarbo()); // 0x3107 CMD_HISTORY_CARBOHY
|
||||||
|
put(new MsgHistoryRefill()); // 0x3108 CMD_HISTORY_REFILL
|
||||||
|
put(new MsgHistorySuspend()); // 0x3109 CMD_HISTORY_SUSPEND
|
||||||
|
put(new MsgHistoryBasalHour()); // 0x310A CMD_HISTORY_BASAL_HOUR
|
||||||
|
put(new MsgHistoryDone()); // 0x31F1 CMD_HISTORY_DONT_USED
|
||||||
|
put(new MsgSettingBasal()); // 0x3202 CMD_SETTING_V_BASAL_INS_I
|
||||||
|
put(new MsgSettingProfileRatios()); // 0x3204 CMD_SETTING_V_CCC_I
|
||||||
|
put(new MsgSettingMaxValues()); // 0x3205 CMD_SETTING_V_MAX_VALUE_I
|
||||||
|
put(new MsgSettingBasalProfileAll()); // 0x3206 CMD_SETTING_V_BASAL_PROFILE_ALL
|
||||||
|
put(new MsgSettingShippingInfo()); // 0x3207 CMD_SETTING_V_SHIPPING_I
|
||||||
|
put(new MsgSettingGlucose()); // 0x3209 CMD_SETTING_V_GLUCOSEandEASY
|
||||||
|
put(new MsgSettingPumpTime()); // 0x320A CMD_SETTING_V_TIME_I
|
||||||
|
put(new MsgSettingUserOptions()); // 0x320B CMD_SETTING_V_USER_OPTIONS
|
||||||
|
put(new MsgSettingActiveProfile()); // 0x320C CMD_SETTING_V_PROFILE_NUMBER
|
||||||
|
put(new MsgSettingProfileRatiosAll()); // 0x320D CMD_SETTING_V_CIR_CF_VALUE
|
||||||
|
put(new MsgSetBasalProfile()); // 0x3306 CMD_SETTING_BASAL_PROFILE_S
|
||||||
|
put(new MsgSetActivateBasalProfile()); // 0x330C CMD_SETTING_PROFILE_NUMBER_S
|
||||||
|
put(new MsgHistoryAllDone()); // 0x41F1 CMD_HISTORY_ALL_DONE
|
||||||
|
put(new MsgHistoryAll()); // 0x41F2 CMD_HISTORY_ALL
|
||||||
|
put(new MsgHistoryNewDone()); // 0x42F1 CMD_HISTORY_NEW_DONE
|
||||||
|
put(new MsgHistoryNew()); // 0x42F2 CMD_HISTORY_NEW
|
||||||
|
put(new MsgCheckValue()); // 0xF0F1 CMD_PUMP_CHECK_VALUE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void put(MessageBase message) {
|
||||||
|
int command = message.getCommand();
|
||||||
|
//String name = MessageOriginalNames.getName(command);
|
||||||
|
messages.put(command, message);
|
||||||
|
//log.debug(String.format("%04x ", command) + " " + name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MessageBase findMessage(Integer command) {
|
||||||
|
if (messages.containsKey(command)) {
|
||||||
|
return messages.get(command);
|
||||||
|
} else {
|
||||||
|
return new MessageBase();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,163 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR.comm;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 28.05.2016.
|
||||||
|
*/
|
||||||
|
public class MessageOriginalNames {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(MessageOriginalNames.class);
|
||||||
|
|
||||||
|
public static HashMap<Integer,String> messageNames;
|
||||||
|
|
||||||
|
static {
|
||||||
|
messageNames = new HashMap<Integer,String>();
|
||||||
|
|
||||||
|
messageNames.put(0x3001, "CMD_CONNECT");
|
||||||
|
messageNames.put(0x3002, "CMD_DISCONNECT");
|
||||||
|
|
||||||
|
messageNames.put(0x3101, "CMD_HISTORY_MEAL_INS");
|
||||||
|
messageNames.put(0x3102, "CMD_HISTORY_DAY_INS");
|
||||||
|
messageNames.put(0x3103, "CMD_HISTORY_AIR_SUB");
|
||||||
|
messageNames.put(0x3104, "CMD_HISTORY_GLUCOSE");
|
||||||
|
messageNames.put(0x3105, "CMD_HISTORY_ALARM");
|
||||||
|
messageNames.put(0x3106, "CMD_HISTORY_ERROR");
|
||||||
|
messageNames.put(0x3107, "CMD_HISTORY_CARBOHY");
|
||||||
|
messageNames.put(0x3108, "CMD_HISTORY_REFILL");
|
||||||
|
messageNames.put(0x3109, "CMD_HISTORY_SUSPEND");
|
||||||
|
messageNames.put(0x310a, "CMD_HISTORY_BASAL_HOUR");
|
||||||
|
messageNames.put(0x310b, "CMD_HISTORY_TB");
|
||||||
|
messageNames.put(0x31f1, "CMD_HISTORY_STOP");
|
||||||
|
messageNames.put(0x31f2, "CMD_HISTORY_LAST_T_R");
|
||||||
|
messageNames.put(0x31f3, "CMD_HISTORY_LAST_T_S");
|
||||||
|
|
||||||
|
messageNames.put(0x0501, "CMD_HISPAGE_MEAL_INS");
|
||||||
|
messageNames.put(0x0502, "CMD_HISPAGE_DAY_INS");
|
||||||
|
messageNames.put(0x0503, "CMD_HISPAGE_AIR_SUB");
|
||||||
|
messageNames.put(0x0504, "CMD_HISPAGE_GLUCOSE");
|
||||||
|
messageNames.put(0x0505, "CMD_HISPAGE_ALARM");
|
||||||
|
messageNames.put(0x0506, "CMD_HISPAGE_ERROR");
|
||||||
|
messageNames.put(0x0507, "CMD_HISPAGE_CARBOHY");
|
||||||
|
messageNames.put(0x0508, "CMD_HISPAGE_REFILL");
|
||||||
|
messageNames.put(0x050a, "CMD_HISPAGE_DAILTY_PRE_DATA");
|
||||||
|
messageNames.put(0x050b, "CMD_HISPAGE_BOLUS_AVG");
|
||||||
|
messageNames.put(0x050c, "CMD_HISPAGE_BASAL_RECORD");
|
||||||
|
messageNames.put(0x050d, "CMD_HISPAGE_TB");
|
||||||
|
|
||||||
|
messageNames.put(0x3201, "CMD_SETTING_V_MEAL_INS_I");
|
||||||
|
messageNames.put(0x3202, "CMD_SETTING_V_BASAL_INS_I");
|
||||||
|
messageNames.put(0x3203, "CMD_SETTING_V_MEAL_SETTING_I");
|
||||||
|
messageNames.put(0x3204, "CMD_SETTING_V_CCC_I");
|
||||||
|
messageNames.put(0x3205, "CMD_SETTING_V_MAX_VALUE_I");
|
||||||
|
messageNames.put(0x3206, "CMD_SETTING_V_BASAL_PROFILE_ALL");
|
||||||
|
messageNames.put(0x3207, "CMD_SETTING_V_SHIPPING_I");
|
||||||
|
messageNames.put(0x3208, "CMD_SETTING_V_CLOGGIN_SENS_I");
|
||||||
|
messageNames.put(0x3209, "CMD_SETTING_V_GLUCOSEandEASY");
|
||||||
|
messageNames.put(0x320a, "CMD_SETTING_V_TIME_I");
|
||||||
|
messageNames.put(0x320b, "CMD_SETTING_V_USER_OPTIONS");
|
||||||
|
messageNames.put(0x320c, "CMD_SETTING_V_PROFILE_NUMBER");
|
||||||
|
messageNames.put(0x320d, "CMD_SETTING_V_CIR_CF_VALUE");
|
||||||
|
|
||||||
|
messageNames.put(0x3301, "CMD_SETTING_MEAL_INS_S");
|
||||||
|
messageNames.put(0x3302, "CMD_SETTING_Based_INS_S");
|
||||||
|
messageNames.put(0x3303, "CMD_SETTING_MEAL_SETTING_S");
|
||||||
|
messageNames.put(0x3304, "CMD_SETTING_CCC_S");
|
||||||
|
messageNames.put(0x3305, "CMD_SETTING_MAX_VALUE_S");
|
||||||
|
messageNames.put(0x3306, "CMD_SETTING_BASAL_PROFILE_S");
|
||||||
|
messageNames.put(0x3307, "CMD_SETTING_SHIPPING_S");
|
||||||
|
messageNames.put(0x3308, "CMD_SETTING_CLOGGIN_SENS_S");
|
||||||
|
messageNames.put(0x3309, "CMD_SETTING_GLUCOSEandEASY_S");
|
||||||
|
messageNames.put(0x330a, "CMD_SETTING_TIME_S");
|
||||||
|
messageNames.put(0x330b, "CMD_SETTING_USER_OPTIONS_S");
|
||||||
|
messageNames.put(0x330c, "CMD_SETTING_PROFILE_NUMBER_S");
|
||||||
|
messageNames.put(0x330d, "CMD_SETTING_CIR_CF_VALUE_S");
|
||||||
|
|
||||||
|
messageNames.put(0x0101, "CMD_MEALINS_STOP");
|
||||||
|
messageNames.put(0x0102, "CMD_MEALINS_START_DATA");
|
||||||
|
messageNames.put(0x0103, "CMD_MEALINS_START_NODATA");
|
||||||
|
messageNames.put(0x0104, "CMD_MEALINS_START_DATA_SPEED");
|
||||||
|
messageNames.put(0x0105, "CMD_MEALINS_START_NODATA_SPEED");
|
||||||
|
|
||||||
|
messageNames.put(0x0201, "CMD_PUMP_ACT_INS_VALUE");
|
||||||
|
messageNames.put(0x0202, "CMD_PUMP_THIS_REMAINDER_MEAL_INS");
|
||||||
|
messageNames.put(0x0203, "CMD_PUMP_BASE_SET");
|
||||||
|
messageNames.put(0x0204, "CMD_PUMP_CALCULATION_SETTING");
|
||||||
|
messageNames.put(0x0205, "CMD_PUMP_EXERCISE_MODE");
|
||||||
|
messageNames.put(0x0206, "CMD_PUMP_MEAL_INS_I");
|
||||||
|
|
||||||
|
messageNames.put(0x0207, "CMD_PUMP_EXPANS_INS_I");
|
||||||
|
messageNames.put(0x0208, "CMD_PUMP_EXPANS_INS_RQ");
|
||||||
|
|
||||||
|
messageNames.put(0x0209, "CMD_PUMP_DUAL_INS_RQ");
|
||||||
|
messageNames.put(0x020a, "CMD_PUMP_INITVIEW_I");
|
||||||
|
messageNames.put(0x020b, "CMD_PUMP_STATUS");
|
||||||
|
messageNames.put(0x020c, "CMD_PUMP_CAR_N_CIR");
|
||||||
|
|
||||||
|
messageNames.put(0x0301, "CMD_PUMPINIT_TIME_INFO");
|
||||||
|
messageNames.put(0x0302, "CMD_PUMPINIT_BOLUS_INFO");
|
||||||
|
messageNames.put(0x0303, "CMD_PUMPINIT_INIT_INFO");
|
||||||
|
messageNames.put(0x0304, "CMD_PUMPINIT_OPTION");
|
||||||
|
|
||||||
|
messageNames.put(0x0401, "CMD_PUMPSET_EXERCISE_S");
|
||||||
|
messageNames.put(0x0402, "CMD_PUMPSET_HIS_S");
|
||||||
|
messageNames.put(0x0403, "CMD_PUMPSET_EXERCISE_STOP");
|
||||||
|
|
||||||
|
messageNames.put(0x0404, "CMD_PUMPSET_PAUSE");
|
||||||
|
messageNames.put(0x0405, "CMD_PUMPSET_PAUSE_STOP");
|
||||||
|
|
||||||
|
messageNames.put(0x0406, "CMD_PUMPSET_EXPANS_INS_STOP");
|
||||||
|
messageNames.put(0x0407, "CMD_PUMPSET_EXPANS_INS_S");
|
||||||
|
|
||||||
|
messageNames.put(0x0408, "CMD_PUMPSET_DUAL_S");
|
||||||
|
messageNames.put(0x0409, "CMD_PUMPSET_EASY_OFF");
|
||||||
|
|
||||||
|
|
||||||
|
messageNames.put(0x0601, "CMD_PUMPOWAY_SYSTEM_STATUS");
|
||||||
|
messageNames.put(0x0602, "CMD_PUMPOWAY_GLUCOSE_ALARM");
|
||||||
|
messageNames.put(0x0603, "CMD_PUMPOWAY_LOW_INSULIN_ALARM");
|
||||||
|
messageNames.put(0x0610, "CMD_PUMP_ALARM_TIEOUT");
|
||||||
|
|
||||||
|
messageNames.put(0x0701, "CMD_MSGRECEP_TAKE_SUGAR");
|
||||||
|
messageNames.put(0x0702, "CMD_MSGRECEP_GO_TO_DOCTOR");
|
||||||
|
messageNames.put(0x0703, "CMD_MSGRECEP_CALL_TO_CAREGIVER");
|
||||||
|
messageNames.put(0x0704, "CMD_MSGRECEP_CHECK_GLUCOSE_AGAIN");
|
||||||
|
messageNames.put(0x0705, "CMD_MSGRECEP_CALL_TO_HOME");
|
||||||
|
messageNames.put(0x0706, "CMD_MSGRECEP_DO_DELIVER");
|
||||||
|
|
||||||
|
messageNames.put(0x0801, "CMD_MSGSEND_YES_I_DO");
|
||||||
|
messageNames.put(0x0802, "CMD_MSGSEND_NO_I_CANNOT");
|
||||||
|
messageNames.put(0x0803, "CMD_MSGSEND_CALL_TO_ME_MOM");
|
||||||
|
messageNames.put(0x0804, "CMD_MSGSEND_DO_NOT_INFUSE");
|
||||||
|
|
||||||
|
messageNames.put(0x0901, "CMD_FILL_REFILL_COUNT");
|
||||||
|
messageNames.put(0x0902, "CMD_FILL_PRIME_CHECK");
|
||||||
|
messageNames.put(0x0903, "CMD_FILL_PRIME_END");
|
||||||
|
messageNames.put(0x0904, "CMD_FILL_PRIME_STOP");
|
||||||
|
messageNames.put(0x0905, "CMD_FILL_PRIME_PAUSE");
|
||||||
|
messageNames.put(0x0906, "CMD_FILL_PRIME_RATE");
|
||||||
|
|
||||||
|
messageNames.put(0x41f2, "CMD_HISTORY_ALL");
|
||||||
|
messageNames.put(0x42f2, "CMD_HISTORY_NEW");
|
||||||
|
|
||||||
|
messageNames.put(0x41f1, "CMD_HISTORY_ALL_DONE");
|
||||||
|
messageNames.put(0x42f1, "CMD_HISTORY_NEW_DONE");
|
||||||
|
|
||||||
|
messageNames.put(0xF0F1, "CMD_PUMP_CHECK_VALUE");
|
||||||
|
messageNames.put(0xF0F2, "CMD_PUMP_TIMECHANGE_CHECK");
|
||||||
|
messageNames.put(0xF0F3, "CMD_PUMP_TIMECHANGE_CLEAR");
|
||||||
|
messageNames.put(0x43F2, "CMD_HISTORY_DATEOVER_ALL");
|
||||||
|
messageNames.put(0x4300, "CMD_HISTORY_DATEOVER_DONE");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getName(Integer command) {
|
||||||
|
if (messageNames.containsKey(command))
|
||||||
|
return messageNames.get(command);
|
||||||
|
else {
|
||||||
|
log.debug("Unknown command: " + String.format("%04X", command));
|
||||||
|
return "UNKNOWN_COMMAND";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR.comm;
|
||||||
|
|
||||||
|
import com.squareup.otto.Bus;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.Config;
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
import info.nightscout.androidaps.R;
|
||||||
|
import info.nightscout.androidaps.db.Treatment;
|
||||||
|
import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress;
|
||||||
|
|
||||||
|
public class MsgBolusProgress extends MessageBase {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(MsgBolusProgress.class);
|
||||||
|
private static Bus bus = null;
|
||||||
|
|
||||||
|
private static Treatment t;
|
||||||
|
private static double amount;
|
||||||
|
|
||||||
|
public int progress = -1;
|
||||||
|
|
||||||
|
public MsgBolusProgress() {
|
||||||
|
SetCommand(0x0202);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MsgBolusProgress(Bus bus, double amount, Treatment t) {
|
||||||
|
this();
|
||||||
|
this.amount = amount;
|
||||||
|
this.t = t;
|
||||||
|
this.bus = bus;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleMessage(byte[] bytes) {
|
||||||
|
progress = intFromBuff(bytes, 0, 2);
|
||||||
|
Double done = (amount * 100 - progress) / 100d;
|
||||||
|
t.insulin = done;
|
||||||
|
EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance();
|
||||||
|
bolusingEvent.status = String.format(MainApp.sResources.getString(R.string.bolusdelivering), done);
|
||||||
|
bolusingEvent.t = t;
|
||||||
|
bolusingEvent.percent = Math.min((int) (done / amount * 100), 100);
|
||||||
|
|
||||||
|
if (Config.logDanaMessageDetail) {
|
||||||
|
log.debug("Bolus remaining: " + progress + " delivered: " + done);
|
||||||
|
}
|
||||||
|
|
||||||
|
bus.post(bolusingEvent);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR.comm;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.BuildConfig;
|
||||||
|
import info.nightscout.androidaps.Config;
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
|
||||||
|
public class MsgBolusStart extends MessageBase {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(MsgBolusStart.class);
|
||||||
|
|
||||||
|
public MsgBolusStart() {
|
||||||
|
SetCommand(0x0102);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MsgBolusStart(double amount) {
|
||||||
|
this();
|
||||||
|
|
||||||
|
// HARDCODED LIMIT
|
||||||
|
amount = MainApp.getConfigBuilder().applyBolusConstraints(amount);
|
||||||
|
if (amount < 0) amount = 0d;
|
||||||
|
if (amount > BuildConfig.MAXBOLUS) amount = BuildConfig.MAXBOLUS;
|
||||||
|
|
||||||
|
AddParamInt((int) (amount * 100));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleMessage(byte[] bytes) {
|
||||||
|
int result = intFromBuff(bytes, 0, 1);
|
||||||
|
if (result != 2) {
|
||||||
|
failed = true;
|
||||||
|
log.debug("Messsage response: " + result + " FAILED!!");
|
||||||
|
} else {
|
||||||
|
if (Config.logDanaMessageDetail)
|
||||||
|
log.debug("Messsage response: " + result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR.comm;
|
||||||
|
|
||||||
|
import com.squareup.otto.Bus;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
import info.nightscout.androidaps.R;
|
||||||
|
import info.nightscout.androidaps.db.Treatment;
|
||||||
|
import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress;
|
||||||
|
|
||||||
|
public class MsgBolusStop extends MessageBase {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(MsgBolusStop.class);
|
||||||
|
private static Treatment t;
|
||||||
|
private static Double amount;
|
||||||
|
private static Bus bus = null;
|
||||||
|
|
||||||
|
public static boolean stopped = false;
|
||||||
|
public static boolean forced = false;
|
||||||
|
|
||||||
|
public MsgBolusStop() {
|
||||||
|
SetCommand(0x0101);
|
||||||
|
stopped = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MsgBolusStop(Bus bus, Double amount, Treatment t) {
|
||||||
|
this();
|
||||||
|
this.bus = bus;
|
||||||
|
this.t = t;
|
||||||
|
this.amount = amount;
|
||||||
|
forced = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleMessage(byte[] bytes) {
|
||||||
|
EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance();
|
||||||
|
stopped = true;
|
||||||
|
if (!forced) {
|
||||||
|
t.insulin = amount;
|
||||||
|
bolusingEvent.status = MainApp.sResources.getString(R.string.overview_bolusprogress_delivered);
|
||||||
|
bolusingEvent.percent = 100;
|
||||||
|
} else {
|
||||||
|
bolusingEvent.status = MainApp.sResources.getString(R.string.overview_bolusprogress_stoped);
|
||||||
|
}
|
||||||
|
bus.post(bolusingEvent);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR.comm;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.Config;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 30.06.2016.
|
||||||
|
*/
|
||||||
|
public class MsgCheckValue extends MessageBase {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(MsgCheckValue.class);
|
||||||
|
|
||||||
|
public MsgCheckValue() {
|
||||||
|
SetCommand(0xF0F1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleMessage(byte[] bytes) {
|
||||||
|
int a = intFromBuff(bytes, 0, 1);
|
||||||
|
int b = intFromBuff(bytes, 1, 1);
|
||||||
|
if (a != 3 || b <= 0) {
|
||||||
|
// another message will follow
|
||||||
|
} else {
|
||||||
|
|
||||||
|
}
|
||||||
|
if (Config.logDanaMessageDetail)
|
||||||
|
log.debug("Response: " + String.format("%02X ", a) + String.format("%02X ", b));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR.comm;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 20.07.2016.
|
||||||
|
*/
|
||||||
|
public class MsgHistoryAlarm extends MsgHistoryAll {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(MsgHistoryAlarm.class);
|
||||||
|
public MsgHistoryAlarm() {
|
||||||
|
SetCommand(0x3105);
|
||||||
|
}
|
||||||
|
// Handle message taken from MsgHistoryAll
|
||||||
|
}
|
|
@ -0,0 +1,160 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR.comm;
|
||||||
|
|
||||||
|
import com.j256.ormlite.dao.Dao;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
import info.nightscout.androidaps.db.DanaRHistoryRecord;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.events.EventDanaRSyncStatus;
|
||||||
|
|
||||||
|
public class MsgHistoryAll extends MessageBase {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(MsgHistoryAll.class);
|
||||||
|
|
||||||
|
public MsgHistoryAll() {
|
||||||
|
SetCommand(0x41F2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleMessage(byte[] bytes) {
|
||||||
|
byte recordCode = (byte) intFromBuff(bytes, 0, 1);
|
||||||
|
Date date = dateFromBuff(bytes, 1); // 3 bytes
|
||||||
|
Date datetime = dateTimeFromBuff(bytes, 1); // 5 bytes
|
||||||
|
Date datetimewihtsec = dateTimeSecFromBuff(bytes, 1); // 6 bytes
|
||||||
|
|
||||||
|
double dailyBasal = intFromBuff(bytes, 4, 2) * 0.01d;
|
||||||
|
double dailyBolus = intFromBuff(bytes, 6, 2) * 0.01d;
|
||||||
|
byte paramByte5 = (byte) intFromBuff(bytes, 4, 1);
|
||||||
|
byte paramByte6 = (byte) intFromBuff(bytes, 5, 1);
|
||||||
|
byte paramByte7 = (byte) intFromBuff(bytes, 6, 1);
|
||||||
|
byte paramByte8 = (byte) intFromBuff(bytes, 7, 1);
|
||||||
|
double value = (double) intFromBuff(bytes, 8, 2);
|
||||||
|
|
||||||
|
EventDanaRSyncStatus ev = new EventDanaRSyncStatus();
|
||||||
|
|
||||||
|
DanaRHistoryRecord danaRHistoryRecord = new DanaRHistoryRecord();
|
||||||
|
|
||||||
|
danaRHistoryRecord.setRecordCode(recordCode);
|
||||||
|
danaRHistoryRecord.setBytes(bytes);
|
||||||
|
|
||||||
|
String messageType = "";
|
||||||
|
|
||||||
|
switch (recordCode) {
|
||||||
|
case RecordTypes.RECORD_TYPE_BOLUS:
|
||||||
|
danaRHistoryRecord.setRecordDate(datetime);
|
||||||
|
switch (0xF0 & paramByte8) {
|
||||||
|
case 0xA0:
|
||||||
|
danaRHistoryRecord.setBolusType("DS");
|
||||||
|
messageType += "DS bolus";
|
||||||
|
break;
|
||||||
|
case 0xC0:
|
||||||
|
danaRHistoryRecord.setBolusType("E");
|
||||||
|
messageType += "E bolus";
|
||||||
|
break;
|
||||||
|
case 0x80:
|
||||||
|
danaRHistoryRecord.setBolusType("S");
|
||||||
|
messageType += "S bolus";
|
||||||
|
break;
|
||||||
|
case 0x90:
|
||||||
|
danaRHistoryRecord.setBolusType("DE");
|
||||||
|
messageType += "DE bolus";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
danaRHistoryRecord.setBolusType("None");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
danaRHistoryRecord.setRecordDuration(((int) paramByte8 & 0x0F) * 60 + (int) paramByte7);
|
||||||
|
danaRHistoryRecord.setRecordValue(value * 0.01);
|
||||||
|
break;
|
||||||
|
case RecordTypes.RECORD_TYPE_DAILY:
|
||||||
|
messageType += "dailyinsulin";
|
||||||
|
danaRHistoryRecord.setRecordDate(date);
|
||||||
|
danaRHistoryRecord.setRecordDailyBasal(dailyBasal);
|
||||||
|
danaRHistoryRecord.setRecordDailyBolus(dailyBolus);
|
||||||
|
break;
|
||||||
|
case RecordTypes.RECORD_TYPE_PRIME:
|
||||||
|
messageType += "prime";
|
||||||
|
danaRHistoryRecord.setRecordDate(datetimewihtsec);
|
||||||
|
danaRHistoryRecord.setRecordValue(value * 0.01);
|
||||||
|
break;
|
||||||
|
case RecordTypes.RECORD_TYPE_ERROR:
|
||||||
|
messageType += "error";
|
||||||
|
danaRHistoryRecord.setRecordDate(datetimewihtsec);
|
||||||
|
danaRHistoryRecord.setRecordValue(value * 0.01);
|
||||||
|
break;
|
||||||
|
case RecordTypes.RECORD_TYPE_REFILL:
|
||||||
|
messageType += "refill";
|
||||||
|
danaRHistoryRecord.setRecordDate(datetimewihtsec);
|
||||||
|
danaRHistoryRecord.setRecordValue(value * 0.01);
|
||||||
|
break;
|
||||||
|
case RecordTypes.RECORD_TYPE_BASALHOUR:
|
||||||
|
messageType += "basal hour";
|
||||||
|
danaRHistoryRecord.setRecordDate(datetimewihtsec);
|
||||||
|
danaRHistoryRecord.setRecordValue(value * 0.01);
|
||||||
|
break;
|
||||||
|
case RecordTypes.RECORD_TYPE_TB:
|
||||||
|
messageType += "tb";
|
||||||
|
danaRHistoryRecord.setRecordDate(datetimewihtsec);
|
||||||
|
danaRHistoryRecord.setRecordValue(value * 0.01);
|
||||||
|
break;
|
||||||
|
case RecordTypes.RECORD_TYPE_GLUCOSE:
|
||||||
|
messageType += "glucose";
|
||||||
|
danaRHistoryRecord.setRecordDate(datetimewihtsec);
|
||||||
|
danaRHistoryRecord.setRecordValue(value);
|
||||||
|
break;
|
||||||
|
case RecordTypes.RECORD_TYPE_CARBO:
|
||||||
|
messageType += "carbo";
|
||||||
|
danaRHistoryRecord.setRecordDate(datetimewihtsec);
|
||||||
|
danaRHistoryRecord.setRecordValue(value);
|
||||||
|
break;
|
||||||
|
case RecordTypes.RECORD_TYPE_ALARM:
|
||||||
|
messageType += "alarm";
|
||||||
|
danaRHistoryRecord.setRecordDate(datetimewihtsec);
|
||||||
|
String strAlarm = "None";
|
||||||
|
switch ((int) paramByte8) {
|
||||||
|
case 67:
|
||||||
|
strAlarm = "Check";
|
||||||
|
break;
|
||||||
|
case 79:
|
||||||
|
strAlarm = "Occlusion";
|
||||||
|
break;
|
||||||
|
case 66:
|
||||||
|
strAlarm = "Low Battery";
|
||||||
|
break;
|
||||||
|
case 83:
|
||||||
|
strAlarm = "Shutdown";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
danaRHistoryRecord.setRecordAlarm(strAlarm);
|
||||||
|
danaRHistoryRecord.setRecordValue(value * 0.01);
|
||||||
|
break;
|
||||||
|
case RecordTypes.RECORD_TYPE_SUSPEND:
|
||||||
|
messageType += "suspend";
|
||||||
|
danaRHistoryRecord.setRecordDate(datetimewihtsec);
|
||||||
|
String strRecordValue = "Off";
|
||||||
|
if ((int) paramByte8 == 79)
|
||||||
|
strRecordValue = "On";
|
||||||
|
danaRHistoryRecord.setStringRecordValue(strRecordValue);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Dao<DanaRHistoryRecord, String> daoHistoryRecords = MainApp.getDbHelper().getDaoDanaRHistory();
|
||||||
|
daoHistoryRecords.createIfNotExists(danaRHistoryRecord);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
DateFormat df = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT);
|
||||||
|
ev.message = df.format(new Date(danaRHistoryRecord.getRecordDate()));
|
||||||
|
ev.message += " " + messageType;
|
||||||
|
MainApp.bus().post(ev);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR.comm;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.Config;
|
||||||
|
|
||||||
|
public class MsgHistoryAllDone extends MessageBase {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(MsgHistoryAllDone.class);
|
||||||
|
public static boolean received = false;
|
||||||
|
|
||||||
|
public MsgHistoryAllDone() {
|
||||||
|
SetCommand(0x41F1);
|
||||||
|
received = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleMessage(byte[] bytes) {
|
||||||
|
received = true;
|
||||||
|
if (Config.logDanaMessageDetail)
|
||||||
|
log.debug("History all done received");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR.comm;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 20.07.2016.
|
||||||
|
*/
|
||||||
|
public class MsgHistoryBasalHour extends MsgHistoryAll {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(MsgHistoryBasalHour.class);
|
||||||
|
public MsgHistoryBasalHour() {
|
||||||
|
SetCommand(0x310A);
|
||||||
|
}
|
||||||
|
// Handle message taken from MsgHistoryAll
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR.comm;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 20.07.2016.
|
||||||
|
*/
|
||||||
|
public class MsgHistoryBolus extends MsgHistoryAll {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(MsgHistoryBolus.class);
|
||||||
|
public MsgHistoryBolus() {
|
||||||
|
SetCommand(0x3101);
|
||||||
|
}
|
||||||
|
// Handle message taken from MsgHistoryAll
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR.comm;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 20.07.2016.
|
||||||
|
*/
|
||||||
|
public class MsgHistoryCarbo extends MsgHistoryAll {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(MsgHistoryCarbo.class);
|
||||||
|
public MsgHistoryCarbo() {
|
||||||
|
SetCommand(0x3107);
|
||||||
|
}
|
||||||
|
// Handle message taken from MsgHistoryAll
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR.comm;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 20.07.2016.
|
||||||
|
*/
|
||||||
|
public class MsgHistoryDailyInsulin extends MsgHistoryAll {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(MsgHistoryDailyInsulin.class);
|
||||||
|
public MsgHistoryDailyInsulin() {
|
||||||
|
SetCommand(0x3102);
|
||||||
|
}
|
||||||
|
// Handle message taken from MsgHistoryAll
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR.comm;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.Config;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 20.07.2016.
|
||||||
|
*/
|
||||||
|
public class MsgHistoryDone extends MessageBase {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(MsgHistoryDone.class);
|
||||||
|
public static boolean received = false;
|
||||||
|
|
||||||
|
public MsgHistoryDone() {
|
||||||
|
SetCommand(0x31F1);
|
||||||
|
received = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleMessage(byte[] bytes) {
|
||||||
|
received = true;
|
||||||
|
if (Config.logDanaMessageDetail)
|
||||||
|
log.debug("History done received");
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR.comm;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 20.07.2016.
|
||||||
|
*/
|
||||||
|
public class MsgHistoryError extends MsgHistoryAll {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(MsgHistoryError.class);
|
||||||
|
public MsgHistoryError() {
|
||||||
|
SetCommand(0x3106);
|
||||||
|
}
|
||||||
|
// Handle message taken from MsgHistoryAll
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR.comm;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 20.07.2016.
|
||||||
|
*/
|
||||||
|
public class MsgHistoryGlucose extends MsgHistoryAll {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(MsgHistoryGlucose.class);
|
||||||
|
public MsgHistoryGlucose() {
|
||||||
|
SetCommand(0x3104);
|
||||||
|
}
|
||||||
|
// Handle message taken from MsgHistoryAll
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR.comm;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 20.07.2016.
|
||||||
|
*/
|
||||||
|
public class MsgHistoryNew extends MsgHistoryAll {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(MsgHistoryNew.class);
|
||||||
|
public MsgHistoryNew() {
|
||||||
|
SetCommand(0x42F2);
|
||||||
|
}
|
||||||
|
// Handle message taken from MsgHistoryAll
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR.comm;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.Config;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 20.07.2016.
|
||||||
|
*/
|
||||||
|
public class MsgHistoryNewDone extends MessageBase {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(MsgHistoryNewDone.class);
|
||||||
|
public static boolean received = false;
|
||||||
|
|
||||||
|
public MsgHistoryNewDone() {
|
||||||
|
SetCommand(0x42F1);
|
||||||
|
received = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleMessage(byte[] bytes) {
|
||||||
|
received = true;
|
||||||
|
if (Config.logDanaMessageDetail)
|
||||||
|
log.debug("History new done received");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR.comm;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 20.07.2016.
|
||||||
|
*/
|
||||||
|
public class MsgHistoryRefill extends MsgHistoryAll {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(MsgHistoryRefill.class);
|
||||||
|
public MsgHistoryRefill() {
|
||||||
|
SetCommand(0x3108);
|
||||||
|
}
|
||||||
|
// Handle message taken from MsgHistoryAll
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR.comm;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 20.07.2016.
|
||||||
|
*/
|
||||||
|
public class MsgHistorySuspend extends MsgHistoryAll {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(MsgHistorySuspend.class);
|
||||||
|
public MsgHistorySuspend() {
|
||||||
|
SetCommand(0x3109);
|
||||||
|
}
|
||||||
|
// Handle message taken from MsgHistoryAll
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR.comm;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class MsgInitConnStatusBasic extends MessageBase {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(MsgInitConnStatusBasic.class);
|
||||||
|
|
||||||
|
public MsgInitConnStatusBasic() {
|
||||||
|
SetCommand(0x0303);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleMessage(byte[] bytes) {
|
||||||
|
int a = intFromBuff(bytes, 0, 1);
|
||||||
|
int b = intFromBuff(bytes, 1, 1);
|
||||||
|
int c = intFromBuff(bytes, 2, 1);
|
||||||
|
int d = intFromBuff(bytes, 3, 1);
|
||||||
|
int e = intFromBuff(bytes, 4, 1);
|
||||||
|
int f = intFromBuff(bytes, 5, 1);
|
||||||
|
int g = intFromBuff(bytes, 6, 1);
|
||||||
|
int h = intFromBuff(bytes, 7, 1);
|
||||||
|
int i = intFromBuff(bytes, 8, 1);
|
||||||
|
int j = intFromBuff(bytes, 9, 1);
|
||||||
|
int k = intFromBuff(bytes, 10, 1);
|
||||||
|
int l = intFromBuff(bytes, 11, 1);
|
||||||
|
int m = intFromBuff(bytes, 12, 1);
|
||||||
|
int n = intFromBuff(bytes, 13, 1);
|
||||||
|
int o;
|
||||||
|
try {
|
||||||
|
o = intFromBuff(bytes, 21, 1);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
o = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR.comm;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 28.05.2016.
|
||||||
|
*/
|
||||||
|
public class MsgInitConnStatusBolus extends MessageBase {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(MsgInitConnStatusBolus.class);
|
||||||
|
|
||||||
|
public MsgInitConnStatusBolus() {
|
||||||
|
SetCommand(0x0302);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleMessage(byte[] bytes) {
|
||||||
|
int a1 = intFromBuff(bytes, 0, 1);
|
||||||
|
int a2 = intFromBuff(bytes, 1, 1);
|
||||||
|
int c = intFromBuff(bytes, 8, 2);
|
||||||
|
int d = c / 100;
|
||||||
|
int e = intFromBuff(bytes, 10, 2);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR.comm;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.Config;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 28.05.2016.
|
||||||
|
*/
|
||||||
|
public class MsgInitConnStatusOption extends MessageBase {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(MsgInitConnStatusOption.class);
|
||||||
|
|
||||||
|
public MsgInitConnStatusOption() {
|
||||||
|
SetCommand(0x0304);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleMessage(byte[] bytes) {
|
||||||
|
int a = intFromBuff(bytes, 0, 1);
|
||||||
|
int b = intFromBuff(bytes, 1, 1);
|
||||||
|
int c = intFromBuff(bytes, 2, 1);
|
||||||
|
int d = intFromBuff(bytes, 3, 1);
|
||||||
|
int e = intFromBuff(bytes, 4, 1);
|
||||||
|
int f = intFromBuff(bytes, 5, 1);
|
||||||
|
int g = intFromBuff(bytes, 6, 1);
|
||||||
|
int h = intFromBuff(bytes, 7, 1);
|
||||||
|
int i = intFromBuff(bytes, 8, 1);
|
||||||
|
if (bytes.length >= 21) {
|
||||||
|
DanaRPlugin.getDanaRPump().password = intFromBuff(bytes, 9, 2) ^ 0x3463;
|
||||||
|
if (Config.logDanaMessageDetail)
|
||||||
|
log.debug("Pump password: " + DanaRPlugin.getDanaRPump().password);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR.comm;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.Config;
|
||||||
|
|
||||||
|
public class MsgInitConnStatusTime extends MessageBase {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(MsgInitConnStatusTime.class);
|
||||||
|
|
||||||
|
public MsgInitConnStatusTime() {
|
||||||
|
SetCommand(0x0301);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleMessage(byte[] bytes) {
|
||||||
|
Date time = dateTimeSecFromBuff(bytes, 0);
|
||||||
|
|
||||||
|
if (Config.logDanaMessageDetail)
|
||||||
|
log.debug("Pump time: " + time);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR.comm;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.Config;
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
import info.nightscout.androidaps.R;
|
||||||
|
import info.nightscout.androidaps.Services.Intents;
|
||||||
|
import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress;
|
||||||
|
import info.nightscout.client.data.DbLogger;
|
||||||
|
import info.nightscout.utils.DateUtil;
|
||||||
|
|
||||||
|
public class MsgOcclusion extends MessageBase {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(MsgOcclusion.class);
|
||||||
|
|
||||||
|
public MsgOcclusion() {
|
||||||
|
SetCommand(0x0601);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleMessage(byte[] bytes) {
|
||||||
|
if (Config.logDanaMessageDetail)
|
||||||
|
log.debug("Oclusion detected");
|
||||||
|
EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance();
|
||||||
|
MsgBolusStop.stopped = true;
|
||||||
|
bolusingEvent.status = MainApp.sResources.getString(R.string.overview_bolusiprogress_occlusion);
|
||||||
|
MainApp.bus().post(bolusingEvent);
|
||||||
|
sendToNSClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendToNSClient() {
|
||||||
|
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", "Announcement");
|
||||||
|
data.put("created_at", DateUtil.toISOString(new Date()));
|
||||||
|
data.put("notes", MainApp.sResources.getString(R.string.overview_bolusiprogress_occlusion));
|
||||||
|
data.put("isAnnouncement", true);
|
||||||
|
} 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(), MsgOcclusion.class);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR.comm;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.Config;
|
||||||
|
|
||||||
|
public class MsgPCCommStart extends MessageBase {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(MsgPCCommStart.class);
|
||||||
|
public MsgPCCommStart() {
|
||||||
|
SetCommand(0x3001);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleMessage(byte[] bytes) {
|
||||||
|
if (Config.logDanaMessageDetail)
|
||||||
|
log.debug("PC comm start received");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR.comm;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.Config;
|
||||||
|
|
||||||
|
public class MsgPCCommStop extends MessageBase {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(MsgPCCommStop.class);
|
||||||
|
public MsgPCCommStop() {
|
||||||
|
SetCommand(0x3002);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleMessage(byte[] bytes) {
|
||||||
|
if (Config.logDanaMessageDetail)
|
||||||
|
log.debug("PC comm stop received");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR.comm;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.Config;
|
||||||
|
|
||||||
|
public class MsgSetActivateBasalProfile extends MessageBase {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(MsgSetActivateBasalProfile.class);
|
||||||
|
|
||||||
|
public MsgSetActivateBasalProfile() {
|
||||||
|
SetCommand(0x330C);
|
||||||
|
}
|
||||||
|
|
||||||
|
// index 0-3
|
||||||
|
public MsgSetActivateBasalProfile(byte index) {
|
||||||
|
this();
|
||||||
|
AddParamByte(index);
|
||||||
|
if (Config.logDanaMessageDetail)
|
||||||
|
log.debug("Activate basal profile: " + index);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleMessage(byte[] bytes) {
|
||||||
|
int result = intFromBuff(bytes, 0, 1);
|
||||||
|
if (result != 1) {
|
||||||
|
failed = true;
|
||||||
|
log.debug("Activate basal profile result: " + result + " FAILED!!!");
|
||||||
|
} else {
|
||||||
|
if (Config.logDanaMessageDetail)
|
||||||
|
log.debug("Activate basal profile result: " + result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR.comm;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.Config;
|
||||||
|
|
||||||
|
public class MsgSetBasalProfile extends MessageBase {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(MsgSetBasalProfile.class);
|
||||||
|
|
||||||
|
public MsgSetBasalProfile() {
|
||||||
|
SetCommand(0x3306);
|
||||||
|
}
|
||||||
|
|
||||||
|
// index 0-3
|
||||||
|
public MsgSetBasalProfile(byte index, double[] values) {
|
||||||
|
this();
|
||||||
|
AddParamByte(index);
|
||||||
|
for (Integer i = 0; i < 24; i++) {
|
||||||
|
AddParamInt((int) (values[i] * 100));
|
||||||
|
}
|
||||||
|
if (Config.logDanaMessageDetail)
|
||||||
|
log.debug("Set basal profile: " + index);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleMessage(byte[] bytes) {
|
||||||
|
int result = intFromBuff(bytes, 0, 1);
|
||||||
|
if (result != 1) {
|
||||||
|
failed = true;
|
||||||
|
log.debug("Set basal profile result: " + result + " FAILED!!!");
|
||||||
|
} else {
|
||||||
|
if (Config.logDanaMessageDetail)
|
||||||
|
log.debug("Set basal profile result: " + result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR.comm;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.Calendar;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.Config;
|
||||||
|
|
||||||
|
public class MsgSetCarbsEntry extends MessageBase {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(MsgSetCarbsEntry.class);
|
||||||
|
|
||||||
|
public MsgSetCarbsEntry() {
|
||||||
|
SetCommand(0x0402);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MsgSetCarbsEntry(Calendar time, int amount) {
|
||||||
|
this();
|
||||||
|
|
||||||
|
AddParamByte((byte) RecordTypes.RECORD_TYPE_CARBO);
|
||||||
|
AddParamByte((byte) (time.get(Calendar.YEAR) % 100));
|
||||||
|
AddParamByte((byte) (time.get(Calendar.MONTH) + 1));
|
||||||
|
AddParamByte((byte) (time.get(Calendar.DAY_OF_MONTH)));
|
||||||
|
AddParamByte((byte) (time.get(Calendar.HOUR_OF_DAY)));
|
||||||
|
AddParamByte((byte) (time.get(Calendar.MINUTE)));
|
||||||
|
AddParamByte((byte) (time.get(Calendar.SECOND)));
|
||||||
|
AddParamByte((byte) 0x43); //??
|
||||||
|
AddParamInt(amount);
|
||||||
|
if (Config.logDanaMessageDetail)
|
||||||
|
log.debug("Set carb entry: " + amount + " date " + time.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleMessage(byte[] bytes) {
|
||||||
|
int result = intFromBuff(bytes, 0, 1);
|
||||||
|
if (result != 1) {
|
||||||
|
failed = true;
|
||||||
|
log.debug("Set carb entry result: " + result + " FAILED!!!");
|
||||||
|
} else {
|
||||||
|
if (Config.logDanaMessageDetail)
|
||||||
|
log.debug("Set carb entry result: " + result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR.comm;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.Config;
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
|
||||||
|
public class MsgSetExtendedBolusStart extends MessageBase {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(MsgSetExtendedBolusStart.class);
|
||||||
|
|
||||||
|
public MsgSetExtendedBolusStart() {
|
||||||
|
SetCommand(0x0407);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MsgSetExtendedBolusStart(double amount, byte halfhours) {
|
||||||
|
this();
|
||||||
|
|
||||||
|
// HARDCODED LIMITS
|
||||||
|
if (halfhours < 1) halfhours = 1;
|
||||||
|
if (halfhours > 16) halfhours = 16;
|
||||||
|
amount = MainApp.getConfigBuilder().applyBolusConstraints(amount);
|
||||||
|
if (amount < 0d) amount = 0d;
|
||||||
|
if (amount > 10d) amount = 10d;
|
||||||
|
|
||||||
|
AddParamInt((int) (amount * 100));
|
||||||
|
AddParamByte(halfhours);
|
||||||
|
if (Config.logDanaMessageDetail)
|
||||||
|
log.debug("Set extended bolus start: " + (((int) (amount * 100)) / 100d) + "U halfhours: " + (int) halfhours);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleMessage(byte[] bytes) {
|
||||||
|
int result = intFromBuff(bytes, 0, 1);
|
||||||
|
if (result != 1) {
|
||||||
|
failed = true;
|
||||||
|
log.debug("Set extended bolus start result: " + result + " FAILED!!!");
|
||||||
|
} else {
|
||||||
|
if (Config.logDanaMessageDetail)
|
||||||
|
log.debug("Set extended bolus start result: " + result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR.comm;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.Config;
|
||||||
|
|
||||||
|
public class MsgSetExtendedBolusStop extends MessageBase {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(MsgSetExtendedBolusStop.class);
|
||||||
|
|
||||||
|
public MsgSetExtendedBolusStop() {
|
||||||
|
SetCommand(0x0406);
|
||||||
|
if (Config.logDanaMessageDetail)
|
||||||
|
log.debug("Set extended bolus stop");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleMessage(byte[] bytes) {
|
||||||
|
int result = intFromBuff(bytes, 0, 1);
|
||||||
|
if (result != 1) {
|
||||||
|
failed = true;
|
||||||
|
log.debug("Set extended bolus stop result: " + result + " FAILED!!!");
|
||||||
|
} else {
|
||||||
|
if (Config.logDanaMessageDetail)
|
||||||
|
log.debug("Set extended bolus stop result: " + result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR.comm;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.Config;
|
||||||
|
|
||||||
|
public class MsgSetTempBasalStart extends MessageBase {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(MsgSetTempBasalStart.class);
|
||||||
|
|
||||||
|
public MsgSetTempBasalStart() {
|
||||||
|
SetCommand(0x0401);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MsgSetTempBasalStart(int percent, int durationInHours) {
|
||||||
|
this();
|
||||||
|
|
||||||
|
//HARDCODED LIMITS
|
||||||
|
if (percent < 0) percent = 0;
|
||||||
|
if (percent > 200) percent = 200;
|
||||||
|
if (durationInHours < 1) durationInHours = 1;
|
||||||
|
if (durationInHours > 24) durationInHours = 24;
|
||||||
|
|
||||||
|
AddParamByte((byte) (percent & 255));
|
||||||
|
AddParamByte((byte) (durationInHours & 255));
|
||||||
|
|
||||||
|
if (Config.logDanaMessageDetail)
|
||||||
|
log.debug("Temp basal start percent: " + percent + " duration hours: " + durationInHours);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleMessage(byte[] bytes) {
|
||||||
|
int result = intFromBuff(bytes, 0, 1);
|
||||||
|
if (result != 1) {
|
||||||
|
failed = true;
|
||||||
|
log.debug("Set temp basal start result: " + result + " FAILED!!!");
|
||||||
|
} else {
|
||||||
|
if (Config.logDanaMessageDetail)
|
||||||
|
log.debug("Set temp basal start result: " + result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR.comm;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.Config;
|
||||||
|
|
||||||
|
public class MsgSetTempBasalStop extends MessageBase {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(MsgSetTempBasalStop.class);
|
||||||
|
|
||||||
|
public MsgSetTempBasalStop() {
|
||||||
|
SetCommand(0x0403);
|
||||||
|
if (Config.logDanaMessageDetail)
|
||||||
|
log.debug("Temp basal stop");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleMessage(byte[] bytes) {
|
||||||
|
int result = intFromBuff(bytes, 0, 1);
|
||||||
|
if (result != 1) {
|
||||||
|
failed = true;
|
||||||
|
log.debug("Set temp basal stop result: " + result + " FAILED!!!");
|
||||||
|
} else {
|
||||||
|
if (Config.logDanaMessageDetail)
|
||||||
|
log.debug("Set temp basal stop result: " + result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR.comm;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.Config;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 05.07.2016.
|
||||||
|
*/
|
||||||
|
public class MsgSettingActiveProfile extends MessageBase {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(MsgSettingBasal.class);
|
||||||
|
|
||||||
|
public MsgSettingActiveProfile() {
|
||||||
|
SetCommand(0x320C);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleMessage(byte[] bytes) {
|
||||||
|
DanaRPlugin.getDanaRPump().activeProfile = intFromBuff(bytes, 0, 1);
|
||||||
|
|
||||||
|
if (Config.logDanaMessageDetail)
|
||||||
|
log.debug("Active profile number: " + DanaRPlugin.getDanaRPump().activeProfile);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR.comm;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.Config;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.DanaRPump;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 05.07.2016.
|
||||||
|
*/
|
||||||
|
public class MsgSettingBasal extends MessageBase {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(MsgSettingBasal.class);
|
||||||
|
|
||||||
|
public MsgSettingBasal() {
|
||||||
|
SetCommand(0x3202);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleMessage(byte[] bytes) {
|
||||||
|
DanaRPump pump = DanaRPlugin.getDanaRPump();
|
||||||
|
if (pump.pumpProfiles == null) pump.pumpProfiles = new double[4][];
|
||||||
|
pump.pumpProfiles[pump.activeProfile] = new double[24];
|
||||||
|
for (int index = 0; index < 24; index++) {
|
||||||
|
int basal = intFromBuff(bytes, 2 * index, 2);
|
||||||
|
if (basal < 10) basal = 0;
|
||||||
|
pump.pumpProfiles[pump.activeProfile][index] = basal / 100d;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.logDanaMessageDetail)
|
||||||
|
for (int index = 0; index < 24; index++) {
|
||||||
|
log.debug("Basal " + String.format("%02d", index) + "h: " + DanaRPlugin.getDanaRPump().pumpProfiles[DanaRPlugin.getDanaRPump().activeProfile][index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR.comm;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.Config;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.DanaRPump;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 05.07.2016.
|
||||||
|
* <p/>
|
||||||
|
* <p/>
|
||||||
|
* THIS IS BROKEN IN PUMP... SENDING ONLY 1 PROFILE
|
||||||
|
*/
|
||||||
|
public class MsgSettingBasalProfileAll extends MessageBase {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(MsgSettingBasalProfileAll.class);
|
||||||
|
|
||||||
|
public MsgSettingBasalProfileAll() {
|
||||||
|
SetCommand(0x3206);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleMessage(byte[] bytes) {
|
||||||
|
DanaRPump pump = DanaRPlugin.getDanaRPump();
|
||||||
|
if (DanaRPlugin.getDanaRPump().basal48Enable) {
|
||||||
|
pump.pumpProfiles = new double[4][];
|
||||||
|
for (int profile = 0; profile < 4; profile++) {
|
||||||
|
int position = intFromBuff(bytes, 107 * profile, 1);
|
||||||
|
pump.pumpProfiles[position] = new double[48];
|
||||||
|
for (int index = 0; index < 48; index++) {
|
||||||
|
int basal = intFromBuff(bytes, 107 * profile + 2 * index + 1, 2);
|
||||||
|
if (basal < 10) basal = 0;
|
||||||
|
pump.pumpProfiles[position][index] = basal / 100d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pump.pumpProfiles = new double[4][];
|
||||||
|
for (int profile = 0; profile < 4; profile++) {
|
||||||
|
int position = intFromBuff(bytes, 49 * profile, 1);
|
||||||
|
log.debug("position " + position);
|
||||||
|
pump.pumpProfiles[position] = new double[24];
|
||||||
|
for (int index = 0; index < 24; index++) {
|
||||||
|
int basal = intFromBuff(bytes, 59 * profile + 2 * index + 1, 2);
|
||||||
|
if (basal < 10) basal = 0;
|
||||||
|
log.debug("position " + position + " index " + index);
|
||||||
|
pump.pumpProfiles[position][index] = basal / 100d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.logDanaMessageDetail) {
|
||||||
|
if (DanaRPlugin.getDanaRPump().basal48Enable) {
|
||||||
|
for (int profile = 0; profile < 4; profile++) {
|
||||||
|
for (int index = 0; index < 24; index++) {
|
||||||
|
log.debug("Basal profile " + profile + ": " + String.format("%02d", index) + "h: " + DanaRPlugin.getDanaRPump().pumpProfiles[profile][index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int profile = 0; profile < 4; profile++) {
|
||||||
|
for (int index = 0; index < 48; index++) {
|
||||||
|
log.debug("Basal profile " + profile + ": " +
|
||||||
|
String.format("%02d", (index / 2)) +
|
||||||
|
":" + String.format("%02d", (index % 2) * 30) + " : " +
|
||||||
|
DanaRPlugin.getDanaRPump().pumpProfiles[profile][index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR.comm;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.Config;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.DanaRPump;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 05.07.2016.
|
||||||
|
*/
|
||||||
|
public class MsgSettingGlucose extends MessageBase {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(MsgSettingGlucose.class);
|
||||||
|
|
||||||
|
public MsgSettingGlucose() {
|
||||||
|
SetCommand(0x3209);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleMessage(byte[] bytes) {
|
||||||
|
DanaRPlugin.getDanaRPump().units = intFromBuff(bytes, 0, 1);
|
||||||
|
DanaRPlugin.getDanaRPump().easyBasalMode = intFromBuff(bytes, 1, 1);
|
||||||
|
|
||||||
|
if (Config.logDanaMessageDetail) {
|
||||||
|
log.debug("Pump units: " + (DanaRPlugin.getDanaRPump().units == DanaRPump.UNITS_MGDL ? "MGDL" : "MMOL"));
|
||||||
|
log.debug("Easy basal mode: " + DanaRPlugin.getDanaRPump().easyBasalMode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR.comm;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.Config;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 05.07.2016.
|
||||||
|
*/
|
||||||
|
public class MsgSettingMaxValues extends MessageBase {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(MsgSettingMaxValues.class);
|
||||||
|
|
||||||
|
public MsgSettingMaxValues() {
|
||||||
|
SetCommand(0x3205);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleMessage(byte[] bytes) {
|
||||||
|
DanaRPlugin.getDanaRPump().maxBolus = intFromBuff(bytes, 0, 2) / 100d;
|
||||||
|
DanaRPlugin.getDanaRPump().maxBasal = intFromBuff(bytes, 2, 2) / 100d;
|
||||||
|
DanaRPlugin.getDanaRPump().maxDailyTotalUnits = intFromBuff(bytes, 4, 2) / 100;
|
||||||
|
|
||||||
|
if (Config.logDanaMessageDetail) {
|
||||||
|
log.debug("Max bolus: " + DanaRPlugin.getDanaRPump().maxBolus);
|
||||||
|
log.debug("Max basal: " + DanaRPlugin.getDanaRPump().maxBasal);
|
||||||
|
log.debug("Total daily max units: " + DanaRPlugin.getDanaRPump().maxDailyTotalUnits);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR.comm;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.Config;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.DanaRPump;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 05.07.2016.
|
||||||
|
*/
|
||||||
|
public class MsgSettingProfileRatios extends MessageBase {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(MsgSettingProfileRatios.class);
|
||||||
|
|
||||||
|
public MsgSettingProfileRatios() {
|
||||||
|
SetCommand(0x3204);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleMessage(byte[] bytes) {
|
||||||
|
if (DanaRPlugin.getDanaRPump().units == DanaRPump.UNITS_MGDL) {
|
||||||
|
DanaRPlugin.getDanaRPump().currentCIR = intFromBuff(bytes, 0, 2);
|
||||||
|
DanaRPlugin.getDanaRPump().currentCF = intFromBuff(bytes, 2, 2);
|
||||||
|
DanaRPlugin.getDanaRPump().currentAI = intFromBuff(bytes, 4, 2) / 100d;
|
||||||
|
DanaRPlugin.getDanaRPump().currentTarget = intFromBuff(bytes, 6, 2);
|
||||||
|
DanaRPlugin.getDanaRPump().currentAIDR = intFromBuff(bytes, 8, 1);
|
||||||
|
} else {
|
||||||
|
DanaRPlugin.getDanaRPump().currentCIR = intFromBuff(bytes, 0, 2);
|
||||||
|
DanaRPlugin.getDanaRPump().currentCF = intFromBuff(bytes, 2, 2) / 100d;
|
||||||
|
DanaRPlugin.getDanaRPump().currentAI = intFromBuff(bytes, 4, 2) / 100d;
|
||||||
|
DanaRPlugin.getDanaRPump().currentTarget = intFromBuff(bytes, 6, 2) / 100d;
|
||||||
|
DanaRPlugin.getDanaRPump().currentAIDR = intFromBuff(bytes, 8, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.logDanaMessageDetail) {
|
||||||
|
log.debug("Pump units (saved): " + (DanaRPlugin.getDanaRPump().units == DanaRPump.UNITS_MGDL ? "MGDL" : "MMOL"));
|
||||||
|
log.debug("Current pump CIR: " + DanaRPlugin.getDanaRPump().currentCIR);
|
||||||
|
log.debug("Current pump CF: " + DanaRPlugin.getDanaRPump().currentCF);
|
||||||
|
log.debug("Current pump AI: " + DanaRPlugin.getDanaRPump().currentAI);
|
||||||
|
log.debug("Current pump target: " + DanaRPlugin.getDanaRPump().currentTarget);
|
||||||
|
log.debug("Current pump AIDR: " + DanaRPlugin.getDanaRPump().currentAIDR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR.comm;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.Config;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.DanaRPump;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 05.07.2016.
|
||||||
|
*/
|
||||||
|
public class MsgSettingProfileRatiosAll extends MessageBase {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(MsgSettingProfileRatiosAll.class);
|
||||||
|
|
||||||
|
public MsgSettingProfileRatiosAll() {
|
||||||
|
SetCommand(0x320D);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleMessage(byte[] bytes) {
|
||||||
|
if (DanaRPlugin.getDanaRPump().units == DanaRPump.UNITS_MGDL) {
|
||||||
|
DanaRPlugin.getDanaRPump().morningCIR = intFromBuff(bytes, 0, 2);
|
||||||
|
DanaRPlugin.getDanaRPump().morningCF = intFromBuff(bytes, 2, 2);
|
||||||
|
DanaRPlugin.getDanaRPump().afternoonCIR = intFromBuff(bytes, 4, 2);
|
||||||
|
DanaRPlugin.getDanaRPump().afternoonCF = intFromBuff(bytes, 6, 2);
|
||||||
|
DanaRPlugin.getDanaRPump().eveningCIR = intFromBuff(bytes, 8, 2);
|
||||||
|
DanaRPlugin.getDanaRPump().eveningCF = intFromBuff(bytes, 10, 2);
|
||||||
|
DanaRPlugin.getDanaRPump().nightCIR = intFromBuff(bytes, 12, 2);
|
||||||
|
DanaRPlugin.getDanaRPump().nightCF = intFromBuff(bytes, 14, 2);
|
||||||
|
} else {
|
||||||
|
DanaRPlugin.getDanaRPump().morningCIR = intFromBuff(bytes, 0, 2);
|
||||||
|
DanaRPlugin.getDanaRPump().morningCF = intFromBuff(bytes, 2, 2) / 100d;
|
||||||
|
DanaRPlugin.getDanaRPump().afternoonCIR = intFromBuff(bytes, 4, 2);
|
||||||
|
DanaRPlugin.getDanaRPump().afternoonCF = intFromBuff(bytes, 6, 2) / 100d;
|
||||||
|
DanaRPlugin.getDanaRPump().eveningCIR = intFromBuff(bytes, 8, 2);
|
||||||
|
DanaRPlugin.getDanaRPump().eveningCF = intFromBuff(bytes, 10, 2) / 100d;
|
||||||
|
DanaRPlugin.getDanaRPump().nightCIR = intFromBuff(bytes, 12, 2);
|
||||||
|
DanaRPlugin.getDanaRPump().nightCF = intFromBuff(bytes, 14, 2) / 100d;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.logDanaMessageDetail) {
|
||||||
|
log.debug("Pump units: " + (DanaRPlugin.getDanaRPump().units == DanaRPump.UNITS_MGDL ? "MGDL" : "MMOL"));
|
||||||
|
log.debug("Current pump morning CIR: " + DanaRPlugin.getDanaRPump().morningCIR);
|
||||||
|
log.debug("Current pump morning CF: " + DanaRPlugin.getDanaRPump().morningCF);
|
||||||
|
log.debug("Current pump afternoon CIR: " + DanaRPlugin.getDanaRPump().afternoonCIR);
|
||||||
|
log.debug("Current pump afternoon CF: " + DanaRPlugin.getDanaRPump().afternoonCF);
|
||||||
|
log.debug("Current pump evening CIR: " + DanaRPlugin.getDanaRPump().eveningCIR);
|
||||||
|
log.debug("Current pump evening CF: " + DanaRPlugin.getDanaRPump().eveningCF);
|
||||||
|
log.debug("Current pump night CIR: " + DanaRPlugin.getDanaRPump().nightCIR);
|
||||||
|
log.debug("Current pump night CF: " + DanaRPlugin.getDanaRPump().nightCF);
|
||||||
|
}
|
||||||
|
|
||||||
|
DanaRPlugin.getDanaRPump().createConvertedProfile();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR.comm;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.Config;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin;
|
||||||
|
|
||||||
|
public class MsgSettingPumpTime extends MessageBase {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(MsgSettingPumpTime.class);
|
||||||
|
|
||||||
|
public MsgSettingPumpTime() {
|
||||||
|
SetCommand(0x320A);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleMessage(byte[] bytes) {
|
||||||
|
Date time =
|
||||||
|
new Date(
|
||||||
|
100 + intFromBuff(bytes, 5, 1),
|
||||||
|
intFromBuff(bytes, 4, 1) - 1,
|
||||||
|
intFromBuff(bytes, 3, 1),
|
||||||
|
intFromBuff(bytes, 2, 1),
|
||||||
|
intFromBuff(bytes, 1, 1),
|
||||||
|
intFromBuff(bytes, 0, 1)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (Config.logDanaMessageDetail)
|
||||||
|
log.debug("Pump time: " + time);
|
||||||
|
|
||||||
|
DanaRPlugin.getDanaRPump().pumpTime = time;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR.comm;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.Config;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 05.07.2016.
|
||||||
|
*/
|
||||||
|
public class MsgSettingShippingInfo extends MessageBase {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(MsgSettingShippingInfo.class);
|
||||||
|
|
||||||
|
public MsgSettingShippingInfo() {
|
||||||
|
SetCommand(0x3207);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleMessage(byte[] bytes) {
|
||||||
|
DanaRPlugin.getDanaRPump().serialNumber = stringFromBuff(bytes, 0, 10);
|
||||||
|
DanaRPlugin.getDanaRPump().shippingDate = dateFromBuff(bytes, 10);
|
||||||
|
DanaRPlugin.getDanaRPump().shippingCountry = asciiStringFromBuff(bytes, 13, 3);
|
||||||
|
if (DanaRPlugin.getDanaRPump().shippingDate.getTime() > new Date(116, 4, 1).getTime()) {
|
||||||
|
DanaRPlugin.getDanaRPump().isNewPump = true;
|
||||||
|
} else
|
||||||
|
DanaRPlugin.getDanaRPump().isNewPump = false;
|
||||||
|
if (Config.logDanaMessageDetail) {
|
||||||
|
log.debug("Serial number: " + DanaRPlugin.getDanaRPump().serialNumber);
|
||||||
|
log.debug("Shipping date: " + DanaRPlugin.getDanaRPump().shippingDate);
|
||||||
|
log.debug("Shipping country: " + DanaRPlugin.getDanaRPump().shippingCountry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
package info.nightscout.androidaps.plugins.DanaR.comm;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 05.07.2016.
|
||||||
|
*/
|
||||||
|
public class MsgSettingUserOptions extends MessageBase {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(MsgSettingShippingInfo.class);
|
||||||
|
|
||||||
|
public MsgSettingUserOptions() {
|
||||||
|
SetCommand(0x320B);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleMessage(byte[] bytes) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue