commit
7bcdf36ca0
263 changed files with 26193 additions and 280 deletions
|
@ -3,20 +3,16 @@
|
|||
<component name="GradleSettings">
|
||||
<option name="linkedExternalProjectsSettings">
|
||||
<GradleProjectSettings>
|
||||
<option name="distributionType" value="DEFAULT_WRAPPED" />
|
||||
<option name="distributionType" value="LOCAL" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="gradleHome" value="C:\Program Files\Android\Android Studio\gradle\gradle-2.14.1" />
|
||||
<option name="modules">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
<option value="$PROJECT_DIR$/app" />
|
||||
</set>
|
||||
</option>
|
||||
<option name="myModules">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
<option value="$PROJECT_DIR$/app" />
|
||||
</set>
|
||||
</option>
|
||||
<option name="resolveModulePerSourceSet" value="false" />
|
||||
</GradleProjectSettings>
|
||||
</option>
|
||||
</component>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0">
|
||||
<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="AndroidLintUselessParent" enabled="false" level="WARNING" 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="Remove" />
|
||||
</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" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
<option name="id" value="Android" />
|
||||
</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>
|
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: 'io.fabric'
|
||||
|
||||
repositories {
|
||||
maven { url 'https://maven.fabric.io/public' }
|
||||
}
|
||||
|
||||
|
||||
android {
|
||||
compileSdkVersion 23
|
||||
|
@ -8,8 +23,11 @@ android {
|
|||
applicationId "info.nightscout.androidaps"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 23
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
versionCode 1019
|
||||
versionName "1.0.19"
|
||||
}
|
||||
lintOptions {
|
||||
disable 'MissingTranslation'
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
|
@ -17,12 +35,64 @@ android {
|
|||
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 {
|
||||
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:support-v4:23.4.0'
|
||||
compile 'com.android.support:cardview-v7:23.0.+'
|
||||
compile 'com.android.support:recyclerview-v7:23.0.+'}
|
||||
compile 'com.android.support:cardview-v7:23.4.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 {
|
||||
# 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"
|
||||
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
|
||||
android:name=".MainApp"
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
|
@ -13,8 +29,60 @@
|
|||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
|
||||
</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>
|
||||
|
||||
</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;
|
||||
|
||||
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.v7.app.AppCompatActivity;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import info.nightscout.androidaps.tabs.*;
|
||||
import info.nightscout.androidaps.plugins.Objectives.ObjectivesFragment;
|
||||
import info.nightscout.androidaps.plugins.Test.TestFragment;
|
||||
import com.joanzapata.iconify.Iconify;
|
||||
import com.joanzapata.iconify.fonts.FontAwesomeModule;
|
||||
import com.squareup.otto.Subscribe;
|
||||
|
||||
public class MainActivity extends AppCompatActivity implements ObjectivesFragment.OnFragmentInteractionListener {
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
private Toolbar toolbar;
|
||||
private SlidingTabLayout mTabs;
|
||||
private ViewPager mPager;
|
||||
private TabPageAdapter mAdapter;
|
||||
import info.nightscout.androidaps.events.EventAppExit;
|
||||
import info.nightscout.androidaps.events.EventRefreshGui;
|
||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||
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
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
Iconify.with(new FontAwesomeModule());
|
||||
LocaleHelper.onCreate(this, "en");
|
||||
setContentView(R.layout.activity_main);
|
||||
checkEula();
|
||||
if (Config.logFunctionCalls)
|
||||
log.debug("onCreate");
|
||||
|
||||
// Register all tabs in app here
|
||||
mAdapter = new TabPageAdapter(getSupportFragmentManager());
|
||||
mAdapter.registerNewFragment("Test", TestFragment.newInstance());
|
||||
mAdapter.registerNewFragment("Objectives", ObjectivesFragment.newInstance());
|
||||
|
||||
toolbar = (Toolbar) findViewById(R.id.toolbar);
|
||||
// show version in toolbar
|
||||
try {
|
||||
setTitle(getString(R.string.app_name) + " " + getPackageManager().getPackageInfo(getPackageName(), 0).versionName);
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
mPager = (ViewPager) findViewById(R.id.pager);
|
||||
mPager.setAdapter(mAdapter);
|
||||
mTabs = (SlidingTabLayout) findViewById(R.id.tabs);
|
||||
mTabs.setViewPager(mPager);
|
||||
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
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.menu_main, menu);
|
||||
|
@ -44,13 +104,69 @@ public class MainActivity extends AppCompatActivity implements ObjectivesFragmen
|
|||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onFragmentInteraction(String param) {
|
||||
|
||||
private void registerBus() {
|
||||
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