commit
cf57fea473
6
.gitignore
vendored
6
.gitignore
vendored
|
@ -1,9 +1,9 @@
|
|||
*.iml
|
||||
wear/wear.iml
|
||||
.gradle
|
||||
/local.properties
|
||||
/.idea/workspace.xml
|
||||
/.idea/libraries
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
*.apk
|
||||
build/
|
||||
.idea/
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
AndroidAPS
|
|
@ -1,22 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<resourceExtensions />
|
||||
<wildcardResourcePatterns>
|
||||
<entry name="!?*.java" />
|
||||
<entry name="!?*.form" />
|
||||
<entry name="!?*.class" />
|
||||
<entry name="!?*.groovy" />
|
||||
<entry name="!?*.scala" />
|
||||
<entry name="!?*.flex" />
|
||||
<entry name="!?*.kt" />
|
||||
<entry name="!?*.clj" />
|
||||
<entry name="!?*.aj" />
|
||||
</wildcardResourcePatterns>
|
||||
<annotationProcessing>
|
||||
<profile default="true" name="Default" enabled="false">
|
||||
<processorPath useClasspath="true" />
|
||||
</profile>
|
||||
</annotationProcessing>
|
||||
</component>
|
||||
</project>
|
|
@ -1,3 +0,0 @@
|
|||
<component name="CopyrightManager">
|
||||
<settings default="" />
|
||||
</component>
|
|
@ -1,6 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding">
|
||||
<file url="PROJECT" charset="UTF-8" />
|
||||
</component>
|
||||
</project>
|
|
@ -1,20 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GradleSettings">
|
||||
<option name="linkedExternalProjectsSettings">
|
||||
<GradleProjectSettings>
|
||||
<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" />
|
||||
<option value="$PROJECT_DIR$/wear" />
|
||||
</set>
|
||||
</option>
|
||||
<option name="resolveModulePerSourceSet" value="false" />
|
||||
</GradleProjectSettings>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
|
@ -1,13 +0,0 @@
|
|||
<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" />
|
||||
<inspection_tool class="LoggerInitializedWithForeignClass" enabled="false" level="WARNING" enabled_by_default="false">
|
||||
<option name="loggerClassName" value="org.apache.log4j.Logger,org.slf4j.LoggerFactory,org.apache.commons.logging.LogFactory,java.util.logging.Logger" />
|
||||
<option name="loggerFactoryMethodName" value="getLogger,getLogger,getLog,getLogger" />
|
||||
</inspection_tool>
|
||||
</profile>
|
||||
</component>
|
|
@ -1,7 +0,0 @@
|
|||
<component name="InspectionProjectProfileManager">
|
||||
<settings>
|
||||
<option name="PROJECT_PROFILE" value="Project Default" />
|
||||
<option name="USE_PROJECT_PROFILE" value="true" />
|
||||
<version value="1.0" />
|
||||
</settings>
|
||||
</component>
|
|
@ -1,46 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="EntryPointsManager">
|
||||
<entry_points version="2.0" />
|
||||
</component>
|
||||
<component name="NullableNotNullManager">
|
||||
<option name="myDefaultNullable" value="android.support.annotation.Nullable" />
|
||||
<option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
|
||||
<option name="myNullables">
|
||||
<value>
|
||||
<list size="4">
|
||||
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
|
||||
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
|
||||
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
|
||||
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
<option name="myNotNulls">
|
||||
<value>
|
||||
<list size="4">
|
||||
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
|
||||
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
|
||||
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
|
||||
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectLevelVcsManager" settingsEditedManually="false">
|
||||
<OptionsSetting value="true" id="Add" />
|
||||
<OptionsSetting value="true" id="Remove" />
|
||||
<OptionsSetting value="true" id="Checkout" />
|
||||
<OptionsSetting value="true" id="Update" />
|
||||
<OptionsSetting value="true" id="Status" />
|
||||
<OptionsSetting value="true" id="Edit" />
|
||||
<ConfirmationsSetting value="0" id="Add" />
|
||||
<ConfirmationsSetting value="0" id="Remove" />
|
||||
</component>
|
||||
<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>
|
||||
</project>
|
|
@ -1,10 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/AndroidAPS.iml" filepath="$PROJECT_DIR$/AndroidAPS.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/wear/wear.iml" filepath="$PROJECT_DIR$/wear/wear.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
|
@ -1,12 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RunConfigurationProducerService">
|
||||
<option name="ignoredProducers">
|
||||
<set>
|
||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
|
||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
|
||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
|
||||
</set>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
|
@ -1,6 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
|
@ -44,7 +44,7 @@ android {
|
|||
minSdkVersion 21
|
||||
targetSdkVersion 23
|
||||
versionCode 1100
|
||||
versionName "1.1"
|
||||
versionName "1.1g"
|
||||
buildConfigField "String", "BUILDVERSION", generateGitBuild()
|
||||
}
|
||||
lintOptions {
|
||||
|
@ -70,7 +70,7 @@ android {
|
|||
dimension "limits"
|
||||
buildConfigField "int", "MAXBOLUS", "5"
|
||||
}
|
||||
full {
|
||||
full {
|
||||
dimension "standard"
|
||||
buildConfigField "boolean", "APS", "true"
|
||||
buildConfigField "boolean", "PUMPDRIVERS", "true"
|
||||
|
@ -97,25 +97,47 @@ android {
|
|||
wear {
|
||||
dimension "wear"
|
||||
buildConfigField "boolean", "WEAR", "true"
|
||||
buildConfigField "boolean", "WEAR_CONTROL", "false"
|
||||
|
||||
}
|
||||
wearcontrol {
|
||||
dimension "wear"
|
||||
buildConfigField "boolean", "WEAR", "true"
|
||||
buildConfigField "boolean", "WEAR_CONTROL", "true"
|
||||
}
|
||||
nowear {
|
||||
dimension "wear"
|
||||
buildConfigField "boolean", "WEAR", "false"
|
||||
buildConfigField "boolean", "WEAR_CONTROL", "false"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
jcenter()
|
||||
flatDir {
|
||||
dirs 'libs'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
wearWearApp project(path: ':wear', configuration: 'fullRelease')
|
||||
wearWearApp project(path: ':wear', configuration: 'restrictedRelease')
|
||||
wearcontrolWearApp project(path: ':wear', configuration: 'fullRelease')
|
||||
|
||||
compile fileTree(include: ['*.jar'], dir: 'libs')
|
||||
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.4.0'
|
||||
compile 'com.android.support:recyclerview-v7:23.4.0'
|
||||
compile 'com.android.support:gridlayout-v7:23.4.0'
|
||||
compile "com.android.support:design:23.4.0"
|
||||
compile "com.android.support:percent: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'
|
||||
|
@ -134,4 +156,6 @@ dependencies {
|
|||
androidTestCompile 'org.mockito:mockito-core:2.+'
|
||||
androidTestCompile "com.google.dexmaker:dexmaker:1.2"
|
||||
androidTestCompile "com.google.dexmaker:dexmaker-mockito:1.2"
|
||||
}
|
||||
compile(name:'android-edittext-validator-v1.3.4-mod', ext:'aar')
|
||||
|
||||
}
|
BIN
app/libs/android-edittext-validator-v1.3.4-mod.aar
Normal file
BIN
app/libs/android-edittext-validator-v1.3.4-mod.aar
Normal file
Binary file not shown.
|
@ -33,9 +33,12 @@
|
|||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name=".PreferencesActivity" />
|
||||
<activity android:name=".plugins.Overview.Dialogs.BolusProgressHelperActivity" android:theme="@style/Theme.AppCompat.Translucent" />
|
||||
<activity android:name=".AgreementActivity" />
|
||||
<activity android:name=".plugins.DanaR.History.DanaRHistoryActivity" />
|
||||
<activity android:name=".plugins.DanaRKorean.History.DanaRHistoryActivity" />
|
||||
<activity android:name=".plugins.DanaR.History.DanaRStatsActivity" />
|
||||
<activity android:name=".plugins.DanaRKorean.History.DanaRStatsActivity" />
|
||||
<activity android:name=".plugins.Overview.activities.QuickWizardListActivity">
|
||||
<intent-filter>
|
||||
<action android:name="info.nightscout.androidaps.plugins.Overview.activities.QuickWizardListActivity" />
|
||||
|
|
61
app/src/main/assets/OpenAPSAMA/basal-set-temp.js
Normal file
61
app/src/main/assets/OpenAPSAMA/basal-set-temp.js
Normal file
|
@ -0,0 +1,61 @@
|
|||
'use strict';
|
||||
|
||||
function reason(rT, msg) {
|
||||
rT.reason = (rT.reason ? rT.reason + '. ' : '') + msg;
|
||||
console.error(msg);
|
||||
}
|
||||
|
||||
var tempBasalFunctions = {};
|
||||
|
||||
tempBasalFunctions.getMaxSafeBasal = function getMaxSafeBasal(profile) {
|
||||
|
||||
var max_daily_safety_multiplier = (isNaN(profile.max_daily_safety_multiplier) || profile.max_daily_safety_multiplier == null) ? 3 : profile.max_daily_safety_multiplier;
|
||||
var current_basal_safety_multiplier = (isNaN(profile.current_basal_safety_multiplier) || profile.current_basal_safety_multiplier == null) ? 4 : profile.current_basal_safety_multiplier;
|
||||
|
||||
return Math.min(profile.max_basal, max_daily_safety_multiplier * profile.max_daily_basal, current_basal_safety_multiplier * profile.current_basal);
|
||||
};
|
||||
|
||||
tempBasalFunctions.setTempBasal = function setTempBasal(rate, duration, profile, rT, currenttemp) {
|
||||
//var maxSafeBasal = Math.min(profile.max_basal, 3 * profile.max_daily_basal, 4 * profile.current_basal);
|
||||
|
||||
var maxSafeBasal = tempBasalFunctions.getMaxSafeBasal(profile);
|
||||
var round_basal = require('./round-basal');
|
||||
|
||||
if (rate < 0) {
|
||||
rate = 0;
|
||||
} // if >30m @ 0 required, zero temp will be extended to 30m instead
|
||||
else if (rate > maxSafeBasal) {
|
||||
rate = maxSafeBasal;
|
||||
}
|
||||
|
||||
var suggestedRate = round_basal(rate, profile);
|
||||
if (typeof(currenttemp) !== 'undefined' && typeof(currenttemp.duration) !== 'undefined' && typeof(currenttemp.rate) !== 'undefined' && currenttemp.duration > 20 && suggestedRate <= currenttemp.rate * 1.2 && suggestedRate >= currenttemp.rate * 0.8) {
|
||||
rT.reason += ", but "+currenttemp.duration+"m left and " + currenttemp.rate + " ~ req " + suggestedRate + "U/hr: no action required";
|
||||
return rT;
|
||||
}
|
||||
|
||||
if (suggestedRate === profile.current_basal) {
|
||||
if (profile.skip_neutral_temps) {
|
||||
if (typeof(currenttemp) !== 'undefined' && typeof(currenttemp.duration) !== 'undefined' && currenttemp.duration > 0) {
|
||||
reason(rT, 'Suggested rate is same as profile rate, a temp basal is active, canceling current temp');
|
||||
rT.duration = 0;
|
||||
rT.rate = 0;
|
||||
return rT;
|
||||
} else {
|
||||
reason(rT, 'Suggested rate is same as profile rate, no temp basal is active, doing nothing');
|
||||
return rT;
|
||||
}
|
||||
} else {
|
||||
reason(rT, 'Setting neutral temp basal of ' + profile.current_basal + 'U/hr');
|
||||
rT.duration = duration;
|
||||
rT.rate = suggestedRate;
|
||||
return rT;
|
||||
}
|
||||
} else {
|
||||
rT.duration = duration;
|
||||
rT.rate = suggestedRate;
|
||||
return rT;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = tempBasalFunctions;
|
498
app/src/main/assets/OpenAPSAMA/determine-basal.js
Normal file
498
app/src/main/assets/OpenAPSAMA/determine-basal.js
Normal file
|
@ -0,0 +1,498 @@
|
|||
/*
|
||||
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 round_basal = require('../round-basal')
|
||||
|
||||
// Rounds value to 'digits' decimal places
|
||||
function round(value, digits)
|
||||
{
|
||||
var scale = Math.pow(10, digits);
|
||||
return Math.round(value * scale) / scale;
|
||||
}
|
||||
|
||||
// we expect BG to rise or fall at the rate of BGI,
|
||||
// adjusted by the rate at which BG would need to rise /
|
||||
// fall to get eventualBG to target over DIA/2 hours
|
||||
function calculate_expected_delta(dia, target_bg, eventual_bg, bgi) {
|
||||
// (hours * mins_per_hour) / 5 = how many 5 minute periods in dia/2
|
||||
var dia_in_5min_blocks = (dia/2 * 60) / 5;
|
||||
var target_delta = target_bg - eventual_bg;
|
||||
var expectedDelta = round(bgi + (target_delta / dia_in_5min_blocks), 1);
|
||||
return expectedDelta;
|
||||
}
|
||||
|
||||
|
||||
function convert_bg(value, profile)
|
||||
{
|
||||
if (profile.out_units == "mmol/L")
|
||||
{
|
||||
return round(value / 18, 1).toFixed(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
return value.toFixed(0);
|
||||
}
|
||||
}
|
||||
|
||||
var determine_basal = function determine_basal(glucose_status, currenttemp, iob_data, profile, autosens_data, meal_data, tempBasalFunctions) {
|
||||
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 basal = profile.current_basal;
|
||||
if (typeof autosens_data !== 'undefined' ) {
|
||||
basal = profile.current_basal * autosens_data.ratio;
|
||||
basal = round_basal(basal, profile);
|
||||
if (basal != profile.current_basal) {
|
||||
console.error("Adjusting basal from "+profile.current_basal+" to "+basal);
|
||||
}
|
||||
}
|
||||
|
||||
var bg = glucose_status.glucose;
|
||||
// TODO: figure out how to use raw isig data to estimate BG
|
||||
if (bg < 39) { //Dexcom is in ??? mode or calibrating
|
||||
rT.reason = "CGM is calibrating or in ??? state";
|
||||
if (basal <= currenttemp.rate * 1.2) { // high temp is running
|
||||
rT.reason += "; setting current basal of " + basal + " as temp";
|
||||
return tempBasalFunctions.setTempBasal(basal, 30, profile, rT, currenttemp);
|
||||
} else { //do nothing.
|
||||
rT.reason += ", temp " + currenttemp.rate + " <~ current basal " + basal + "U/hr";
|
||||
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;
|
||||
var min_bg;
|
||||
var max_bg;
|
||||
if (typeof profile.min_bg !== 'undefined') {
|
||||
min_bg = profile.min_bg;
|
||||
}
|
||||
if (typeof profile.max_bg !== 'undefined') {
|
||||
max_bg = profile.max_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;
|
||||
}
|
||||
}
|
||||
|
||||
// adjust min, max, and target BG for sensitivity, such that 50% increase in ISF raises target from 100 to 120
|
||||
if (typeof autosens_data !== 'undefined' && profile.autosens_adjust_targets) {
|
||||
if (profile.temptargetSet) {
|
||||
console.error("Temp Target set, not adjusting with autosens");
|
||||
} else {
|
||||
min_bg = Math.round((min_bg - 60) / autosens_data.ratio) + 60;
|
||||
max_bg = Math.round((max_bg - 60) / autosens_data.ratio) + 60;
|
||||
new_target_bg = Math.round((target_bg - 60) / autosens_data.ratio) + 60;
|
||||
if (target_bg == new_target_bg) {
|
||||
console.error("target_bg unchanged:", new_target_bg);
|
||||
} else {
|
||||
console.error("Adjusting target_bg from", target_bg, "to", new_target_bg);
|
||||
}
|
||||
target_bg = new_target_bg;
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof iob_data === 'undefined' ) {
|
||||
rT.error ='Error: iob_data undefined';
|
||||
return rT;
|
||||
}
|
||||
|
||||
var iobArray = iob_data;
|
||||
if (typeof(iob_data.length) && iob_data.length > 1) {
|
||||
iob_data = iobArray[0];
|
||||
//console.error(JSON.stringify(iob_data[0]));
|
||||
}
|
||||
|
||||
if (typeof iob_data.activity === 'undefined' || typeof iob_data.iob === 'undefined' ) {
|
||||
rT.error ='Error: iob_data missing some property';
|
||||
return rT;
|
||||
}
|
||||
|
||||
var tick;
|
||||
|
||||
if (glucose_status.delta > -0.5) {
|
||||
tick = "+" + round(glucose_status.delta,0);
|
||||
} else {
|
||||
tick = round(glucose_status.delta,0);
|
||||
}
|
||||
var minDelta = Math.min(glucose_status.delta, glucose_status.short_avgdelta, glucose_status.long_avgdelta);
|
||||
var minAvgDelta = Math.min(glucose_status.short_avgdelta, glucose_status.long_avgdelta);
|
||||
|
||||
var sens = profile.sens;
|
||||
if (typeof autosens_data !== 'undefined' ) {
|
||||
sens = profile.sens / autosens_data.ratio;
|
||||
sens = round(sens, 1);
|
||||
if (sens != profile.sens) {
|
||||
console.error("Adjusting sens from "+profile.sens+" to "+sens);
|
||||
}
|
||||
}
|
||||
|
||||
//calculate BG impact: the amount BG "should" be rising or falling based on insulin activity alone
|
||||
var bgi = round(( -iob_data.activity * sens * 5 ), 2);
|
||||
// project deviations for 30 minutes
|
||||
var deviation = Math.round( 30 / 5 * ( minDelta - bgi ) );
|
||||
// don't overreact to a big negative delta: use minAvgDelta if deviation is negative
|
||||
if (deviation < 0) {
|
||||
deviation = Math.round( (30 / 5) * ( minAvgDelta - bgi ) );
|
||||
}
|
||||
|
||||
// calculate the naive (bolus calculator math) eventual BG based on net IOB and sensitivity
|
||||
if (iob_data.iob > 0) {
|
||||
var naive_eventualBG = Math.round( bg - (iob_data.iob * sens) );
|
||||
} else { // if IOB is negative, be more conservative and use the lower of sens, profile.sens
|
||||
var naive_eventualBG = Math.round( bg - (iob_data.iob * Math.min(sens, 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 * 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;
|
||||
|
||||
var expectedDelta = calculate_expected_delta(profile.dia, target_bg, eventualBG, bgi);
|
||||
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 = min_bg - 0.5*(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; }
|
||||
|
||||
// generate predicted future BGs based on IOB, COB, and current absorption rate
|
||||
|
||||
var COBpredBGs = [];
|
||||
var aCOBpredBGs = [];
|
||||
var IOBpredBGs = [];
|
||||
COBpredBGs.push(bg);
|
||||
aCOBpredBGs.push(bg);
|
||||
IOBpredBGs.push(bg);
|
||||
//console.error(meal_data);
|
||||
// carb impact and duration are 0 unless changed below
|
||||
var ci = 0;
|
||||
var cid = 0;
|
||||
// calculate current carb absorption rate, and how long to absorb all carbs
|
||||
// CI = current carb impact on BG in mg/dL/5m
|
||||
ci = Math.round((minDelta - bgi)*10)/10;
|
||||
if (meal_data.mealCOB * 2 > meal_data.carbs) {
|
||||
// set ci to a minimum of 3mg/dL/5m (default) if less than half of carbs have absorbed
|
||||
ci = Math.max(profile.min_5m_carbimpact, ci);
|
||||
}
|
||||
aci = 10;
|
||||
//5m data points = g * (1U/10g) * (40mg/dL/1U) / (mg/dL/5m)
|
||||
cid = meal_data.mealCOB * ( sens / profile.carb_ratio ) / ci;
|
||||
acid = meal_data.mealCOB * ( sens / profile.carb_ratio ) / aci;
|
||||
console.error("Carb Impact:",ci,"mg/dL per 5m; CI Duration:",Math.round(10*cid/6)/10,"hours");
|
||||
console.error("Accel. Carb Impact:",aci,"mg/dL per 5m; ACI Duration:",Math.round(10*acid/6)/10,"hours");
|
||||
var minPredBG = 999;
|
||||
var maxPredBG = bg;
|
||||
var eventualPredBG = bg;
|
||||
try {
|
||||
iobArray.forEach(function(iobTick) {
|
||||
//console.error(iobTick);
|
||||
predBGI = round(( -iobTick.activity * sens * 5 ), 2);
|
||||
// predicted deviation impact drops linearly from current deviation down to zero
|
||||
// over 60 minutes (data points every 5m)
|
||||
predDev = ci * ( 1 - Math.min(1,IOBpredBGs.length/(60/5)) );
|
||||
IOBpredBG = IOBpredBGs[IOBpredBGs.length-1] + predBGI + predDev;
|
||||
//IOBpredBG = IOBpredBGs[IOBpredBGs.length-1] + predBGI;
|
||||
// predicted carb impact drops linearly from current carb impact down to zero
|
||||
// eventually accounting for all carbs (if they can be absorbed over DIA)
|
||||
predCI = Math.max(0, ci * ( 1 - COBpredBGs.length/Math.max(cid*2,1) ) );
|
||||
predACI = Math.max(0, aci * ( 1 - COBpredBGs.length/Math.max(acid*2,1) ) );
|
||||
COBpredBG = COBpredBGs[COBpredBGs.length-1] + predBGI + Math.min(0,predDev) + predCI;
|
||||
aCOBpredBG = aCOBpredBGs[aCOBpredBGs.length-1] + predBGI + Math.min(0,predDev) + predACI;
|
||||
//console.error(predBGI, predCI, predBG);
|
||||
IOBpredBGs.push(IOBpredBG);
|
||||
COBpredBGs.push(COBpredBG);
|
||||
aCOBpredBGs.push(aCOBpredBG);
|
||||
// wait 45m before setting minPredBG
|
||||
if ( COBpredBGs.length > 9 && (COBpredBG < minPredBG) ) { minPredBG = COBpredBG; }
|
||||
if ( COBpredBG > maxPredBG ) { maxPredBG = COBpredBG; }
|
||||
});
|
||||
// set eventualBG to include effect of carbs
|
||||
//console.error("PredBGs:",JSON.stringify(predBGs));
|
||||
} catch (e) {
|
||||
console.error("Problem with iobArray. Optional feature Advanced Meal Assist disabled.");
|
||||
}
|
||||
rT.predBGs = {};
|
||||
IOBpredBGs.forEach(function(p, i, theArray) {
|
||||
theArray[i] = Math.round(Math.min(401,Math.max(39,p)));
|
||||
});
|
||||
for (var i=IOBpredBGs.length-1; i > 12; i--) {
|
||||
if (IOBpredBGs[i-1] != IOBpredBGs[i]) { break; }
|
||||
else { IOBpredBGs.pop(); }
|
||||
}
|
||||
rT.predBGs.IOB = IOBpredBGs;
|
||||
if (meal_data.mealCOB > 0) {
|
||||
aCOBpredBGs.forEach(function(p, i, theArray) {
|
||||
theArray[i] = Math.round(Math.min(401,Math.max(39,p)));
|
||||
});
|
||||
for (var i=aCOBpredBGs.length-1; i > 12; i--) {
|
||||
if (aCOBpredBGs[i-1] != aCOBpredBGs[i]) { break; }
|
||||
else { aCOBpredBGs.pop(); }
|
||||
}
|
||||
rT.predBGs.aCOB = aCOBpredBGs;
|
||||
}
|
||||
if (meal_data.mealCOB > 0 && ci > 0 ) {
|
||||
COBpredBGs.forEach(function(p, i, theArray) {
|
||||
theArray[i] = Math.round(Math.min(401,Math.max(39,p)));
|
||||
});
|
||||
for (var i=COBpredBGs.length-1; i > 12; i--) {
|
||||
if (COBpredBGs[i-1] != COBpredBGs[i]) { break; }
|
||||
else { COBpredBGs.pop(); }
|
||||
}
|
||||
rT.predBGs.COB = COBpredBGs;
|
||||
eventualBG = Math.max(eventualBG, Math.round(COBpredBGs[COBpredBGs.length-1]) );
|
||||
rT.eventualBG = eventualBG;
|
||||
minPredBG = Math.min(minPredBG, eventualBG);
|
||||
// set snoozeBG to minPredBG
|
||||
snoozeBG = Math.round(Math.max(snoozeBG,minPredBG));
|
||||
rT.snoozeBG = snoozeBG;
|
||||
}
|
||||
|
||||
rT.COB=meal_data.mealCOB;
|
||||
rT.IOB=iob_data.iob;
|
||||
rT.reason="COB: " + meal_data.mealCOB + ", Dev: " + deviation + ", BGI: " + bgi + ", ISF: " + convert_bg(sens, profile) + ", Target: " + convert_bg(target_bg, profile) + "; ";
|
||||
if (bg < threshold) { // low glucose suspend mode: BG is < ~80
|
||||
rT.reason += "BG " + convert_bg(bg, profile) + "<" + convert_bg(threshold, profile);
|
||||
if ((glucose_status.delta <= 0 && minDelta <= 0) || (glucose_status.delta < expectedDelta && minDelta < expectedDelta) || bg < 60 ) {
|
||||
// BG is still falling / rising slower than predicted
|
||||
return tempBasalFunctions.setTempBasal(0, 30, profile, rT, currenttemp);
|
||||
}
|
||||
if (glucose_status.delta > minDelta) {
|
||||
rT.reason += ", delta " + glucose_status.delta + ">0";
|
||||
} else {
|
||||
rT.reason += ", min delta " + minDelta.toFixed(2) + ">0";
|
||||
}
|
||||
if (currenttemp.duration > 15 && (round_basal(basal, profile) === round_basal(currenttemp.rate, profile))) {
|
||||
rT.reason += ", temp " + currenttemp.rate + " ~ req " + basal + "U/hr";
|
||||
return rT;
|
||||
} else {
|
||||
rT.reason += "; setting current basal of " + basal + " as temp";
|
||||
return tempBasalFunctions.setTempBasal(basal, 30, profile, rT, currenttemp);
|
||||
}
|
||||
}
|
||||
|
||||
if (eventualBG < min_bg) { // if eventual BG is below target:
|
||||
rT.reason += "Eventual BG " + convert_bg(eventualBG, profile) + " < " + convert_bg(min_bg, profile);
|
||||
// if 5m or 30m avg BG is rising faster than expected delta
|
||||
if (minDelta > expectedDelta && minDelta > 0) {
|
||||
if (glucose_status.delta > minDelta) {
|
||||
rT.reason += ", but Delta " + tick + " > Exp. Delta " + expectedDelta;
|
||||
} else {
|
||||
rT.reason += ", but Min. Delta " + minDelta.toFixed(2) + " > Exp. Delta " + expectedDelta;
|
||||
}
|
||||
if (currenttemp.duration > 15 && (round_basal(basal, profile) === round_basal(currenttemp.rate, profile))) {
|
||||
rT.reason += ", temp " + currenttemp.rate + " ~ req " + basal + "U/hr";
|
||||
return rT;
|
||||
} else {
|
||||
rT.reason += "; setting current basal of " + basal + " as temp";
|
||||
return tempBasalFunctions.setTempBasal(basal, 30, profile, rT, currenttemp);
|
||||
}
|
||||
}
|
||||
|
||||
if (eventualBG < min_bg) {
|
||||
// if we've bolused recently, we can snooze until the bolus IOB decays (at double speed)
|
||||
if (snoozeBG > min_bg) { // if adding back in the bolus contribution BG would be above min
|
||||
rT.reason += ", bolus snooze: eventual BG range " + convert_bg(eventualBG, profile) + "-" + convert_bg(snoozeBG, profile);
|
||||
//console.error(currenttemp, basal );
|
||||
if (currenttemp.duration > 15 && (round_basal(basal, profile) === round_basal(currenttemp.rate, profile))) {
|
||||
rT.reason += ", temp " + currenttemp.rate + " ~ req " + basal + "U/hr";
|
||||
return rT;
|
||||
} else {
|
||||
rT.reason += "; setting current basal of " + basal + " as temp";
|
||||
return tempBasalFunctions.setTempBasal(basal, 30, profile, rT, currenttemp);
|
||||
}
|
||||
} 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) / sens);
|
||||
insulinReq = round( insulinReq , 2);
|
||||
if (minDelta < 0 && minDelta > expectedDelta) {
|
||||
// if we're barely falling, newinsulinReq should be barely negative
|
||||
rT.reason += ", Snooze BG " + convert_bg(snoozeBG, profile);
|
||||
var newinsulinReq = round(( insulinReq * (minDelta / expectedDelta) ), 2);
|
||||
//console.error("Increasing insulinReq from " + insulinReq + " to " + newinsulinReq);
|
||||
insulinReq = newinsulinReq;
|
||||
}
|
||||
// rate required to deliver insulinReq less insulin over 30m:
|
||||
var rate = basal + (2 * insulinReq);
|
||||
rate = round_basal(rate, profile);
|
||||
// if required temp < existing temp basal
|
||||
var insulinScheduled = currenttemp.duration * (currenttemp.rate - basal) / 60;
|
||||
if (insulinScheduled < insulinReq - basal*0.3) { // if current temp would deliver a lot (30% of basal) less than the required insulin, raise the rate
|
||||
rT.reason += ", "+currenttemp.duration + "m@" + (currenttemp.rate - basal).toFixed(3) + " = " + insulinScheduled.toFixed(3) + " < req " + insulinReq + "-" + basal*0.3;
|
||||
return tempBasalFunctions.setTempBasal(rate, 30, profile, rT, currenttemp);
|
||||
}
|
||||
if (typeof currenttemp.rate !== 'undefined' && (currenttemp.duration > 5 && rate >= currenttemp.rate * 0.8)) {
|
||||
rT.reason += ", temp " + currenttemp.rate + " ~< req " + rate + "U/hr";
|
||||
return rT;
|
||||
} else {
|
||||
rT.reason += ", setting " + rate + "U/hr";
|
||||
return tempBasalFunctions.setTempBasal(rate, 30, profile, rT, currenttemp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var minutes_running;
|
||||
if (typeof currenttemp.duration == 'undefined' || currenttemp.duration == 0) {
|
||||
minutes_running = 30;
|
||||
} else if (typeof currenttemp.minutesrunning !== 'undefined'){
|
||||
// If the time the current temp is running is not defined, use default request duration of 30 minutes.
|
||||
minutes_running = currenttemp.minutesrunning;
|
||||
} else {
|
||||
minutes_running = 30 - currenttemp.duration;
|
||||
}
|
||||
|
||||
// if there is a low-temp running, and eventualBG would be below min_bg without it, let it run
|
||||
if (round_basal(currenttemp.rate, profile) < round_basal(basal, profile) ) {
|
||||
var lowtempimpact = (currenttemp.rate - basal) * ((30-minutes_running)/60) * sens;
|
||||
var adjEventualBG = eventualBG + lowtempimpact;
|
||||
if ( adjEventualBG < min_bg ) {
|
||||
rT.reason += "letting low temp of " + currenttemp.rate + " run.";
|
||||
return rT;
|
||||
}
|
||||
}
|
||||
|
||||
// if eventual BG is above min but BG is falling faster than expected Delta
|
||||
if (minDelta < expectedDelta) {
|
||||
if (glucose_status.delta < minDelta) {
|
||||
rT.reason += "Eventual BG " + convert_bg(eventualBG, profile) + " > " + convert_bg(min_bg, profile) + " but Delta " + tick + " < Exp. Delta " + expectedDelta;
|
||||
} else {
|
||||
rT.reason += "Eventual BG " + convert_bg(eventualBG, profile) + " > " + convert_bg(min_bg, profile) + " but Min. Delta " + minDelta.toFixed(2) + " < Exp. Delta " + expectedDelta;
|
||||
}
|
||||
if (currenttemp.duration > 15 && (round_basal(basal, profile) === round_basal(currenttemp.rate, profile))) {
|
||||
rT.reason += ", temp " + currenttemp.rate + " ~ req " + basal + "U/hr";
|
||||
return rT;
|
||||
} else {
|
||||
rT.reason += "; setting current basal of " + basal + " as temp";
|
||||
return tempBasalFunctions.setTempBasal(basal, 30, profile, rT, currenttemp);
|
||||
}
|
||||
}
|
||||
// eventualBG or snoozeBG (from minPredBG) is below max_bg
|
||||
if (eventualBG < max_bg || snoozeBG < max_bg) {
|
||||
// if there is a high-temp running and eventualBG > max_bg, let it run
|
||||
if (eventualBG > max_bg && round_basal(currenttemp.rate, profile) > round_basal(basal, profile) ) {
|
||||
rT.reason += ", " + eventualBG + " > " + max_bg + ": no action required (letting high temp of " + currenttemp.rate + " run)."
|
||||
return rT;
|
||||
}
|
||||
|
||||
rT.reason += convert_bg(eventualBG, profile)+"-"+convert_bg(snoozeBG, profile)+" in range: no temp required";
|
||||
if (currenttemp.duration > 15 && (round_basal(basal, profile) === round_basal(currenttemp.rate, profile))) {
|
||||
rT.reason += ", temp " + currenttemp.rate + " ~ req " + basal + "U/hr";
|
||||
return rT;
|
||||
} else {
|
||||
rT.reason += "; setting current basal of " + basal + " as temp";
|
||||
return tempBasalFunctions.setTempBasal(basal, 30, profile, rT, currenttemp);
|
||||
}
|
||||
}
|
||||
|
||||
// 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 " + convert_bg(eventualBG, profile) + " >= " + convert_bg(max_bg, profile) + ", ";
|
||||
if (basaliob > max_iob) {
|
||||
rT.reason += "basaliob " + round(basaliob,2) + " > max_iob " + max_iob;
|
||||
if (currenttemp.duration > 15 && (round_basal(basal, profile) === round_basal(currenttemp.rate, profile))) {
|
||||
rT.reason += ", temp " + currenttemp.rate + " ~ req " + basal + "U/hr";
|
||||
return rT;
|
||||
} else {
|
||||
rT.reason += "; setting current basal of " + basal + " as temp";
|
||||
return tempBasalFunctions.setTempBasal(basal, 30, profile, rT, currenttemp);
|
||||
}
|
||||
} 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 = round( (Math.min(snoozeBG,eventualBG) - target_bg) / sens, 2);
|
||||
if (minDelta < 0 && minDelta > expectedDelta) {
|
||||
var newinsulinReq = round(( insulinReq * (1 - (minDelta / expectedDelta)) ), 2);
|
||||
//console.error("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 = basal + (2 * insulinReq);
|
||||
rate = round_basal(rate, profile);
|
||||
|
||||
// var maxSafeBasal = Math.min(profile.max_basal, 3 * profile.max_daily_basal, 4 * basal);
|
||||
|
||||
var maxSafeBasal = tempBasalFunctions.getMaxSafeBasal(profile);
|
||||
|
||||
if (rate > maxSafeBasal) {
|
||||
rT.reason += "adj. req. rate: "+rate+" to maxSafeBasal: "+maxSafeBasal+", ";
|
||||
rate = round_basal(maxSafeBasal, profile);
|
||||
}
|
||||
|
||||
var insulinScheduled = currenttemp.duration * (currenttemp.rate - basal) / 60;
|
||||
if (insulinScheduled >= insulinReq * 2) { // if current temp would deliver >2x more than the required insulin, lower the rate
|
||||
rT.reason += currenttemp.duration + "m@" + (currenttemp.rate - basal).toFixed(3) + " = " + insulinScheduled.toFixed(3) + " > 2 * req " + insulinReq + ". Setting temp basal of " + rate + "U/hr";
|
||||
return tempBasalFunctions.setTempBasal(rate, 30, profile, rT, currenttemp);
|
||||
}
|
||||
|
||||
if (typeof currenttemp.duration == 'undefined' || currenttemp.duration == 0) { // no temp is set
|
||||
rT.reason += "no temp, setting " + rate + "U/hr";
|
||||
return tempBasalFunctions.setTempBasal(rate, 30, profile, rT, currenttemp);
|
||||
}
|
||||
|
||||
if (currenttemp.duration > 5 && (round_basal(rate, profile) <= round_basal(currenttemp.rate, profile))) { // 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 tempBasalFunctions.setTempBasal(rate, 30, profile, rT, currenttemp);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
module.exports = determine_basal;
|
|
@ -7,7 +7,7 @@ public class Config {
|
|||
// MAIN FUCTIONALITY
|
||||
public static final boolean APS = BuildConfig.APS;
|
||||
// PLUGINS
|
||||
public static final boolean OPENAPSMAENABLED = APS;
|
||||
public static final boolean OPENAPSENABLED = APS;
|
||||
public static final boolean LOOPENABLED = APS;
|
||||
public static final boolean WEAR = BuildConfig.WEAR;
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ 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 MGDL = "mg/dl"; // This is Nightscout's representation
|
||||
public static final String MMOL = "mmol";
|
||||
|
||||
public static final double MMOLL_TO_MGDL = 18; // 18.0182;
|
||||
|
@ -24,5 +24,32 @@ public class Constants {
|
|||
|
||||
public static final long keepAliveMsecs = 5 * 60 * 1000L;
|
||||
|
||||
// SMS COMMUNICATOR
|
||||
public static final long remoteBolusMinDistance = 15 * 60 * 1000L;
|
||||
|
||||
// Circadian Percentage Profile
|
||||
public static final int CPP_MIN_PERCENTAGE = 50;
|
||||
public static final int CPP_MAX_PERCENTAGE = 200;
|
||||
|
||||
// Defaults for settings
|
||||
public static final String MAX_BG_DEFAULT_MGDL = "180";
|
||||
public static final String MAX_BG_DEFAULT_MMOL = "10";
|
||||
public static final String MIN_BG_DEFAULT_MGDL = "100";
|
||||
public static final String MIN_BG_DEFAULT_MMOL = "5";
|
||||
public static final String TARGET_BG_DEFAULT_MGDL = "150";
|
||||
public static final String TARGET_BG_DEFAULT_MMOL = "7";
|
||||
|
||||
// Very Hard Limits Ranges
|
||||
// First value is the Lowest and second value is the Highest a Limit can define
|
||||
public static final int[] VERY_HARD_LIMIT_MIN_BG = {72,180};
|
||||
public static final int[] VERY_HARD_LIMIT_MAX_BG = {90,270};
|
||||
public static final int[] VERY_HARD_LIMIT_TARGET_BG = {80,200};
|
||||
|
||||
// Very Hard Limits Ranges for Temp Targets
|
||||
public static final int[] VERY_HARD_LIMIT_TEMP_MIN_BG = {72,180};
|
||||
public static final int[] VERY_HARD_LIMIT_TEMP_MAX_BG = {72,270};
|
||||
public static final int[] VERY_HARD_LIMIT_TEMP_TARGET_BG = {72,200};
|
||||
|
||||
//DanaR
|
||||
public static final double dailyLimitWarning = 0.95d;
|
||||
}
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
package info.nightscout.androidaps;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.v4.app.ActivityCompat;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
|
@ -17,6 +18,10 @@ import android.support.v7.app.AppCompatActivity;
|
|||
import android.support.v7.widget.Toolbar;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.EditText;
|
||||
|
||||
import com.joanzapata.iconify.Iconify;
|
||||
import com.joanzapata.iconify.fonts.FontAwesomeModule;
|
||||
|
@ -29,12 +34,12 @@ import info.nightscout.androidaps.events.EventAppExit;
|
|||
import info.nightscout.androidaps.events.EventPreferenceChange;
|
||||
import info.nightscout.androidaps.events.EventRefreshGui;
|
||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||
import info.nightscout.androidaps.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.LogDialog;
|
||||
import info.nightscout.utils.ImportExportPrefs;
|
||||
import info.nightscout.utils.LocaleHelper;
|
||||
import info.nightscout.utils.PasswordProtection;
|
||||
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
private static Logger log = LoggerFactory.getLogger(MainActivity.class);
|
||||
|
@ -121,8 +126,13 @@ public class MainActivity extends AppCompatActivity {
|
|||
int id = item.getItemId();
|
||||
switch (id) {
|
||||
case R.id.nav_preferences:
|
||||
Intent i = new Intent(getApplicationContext(), PreferencesActivity.class);
|
||||
startActivity(i);
|
||||
PasswordProtection.QueryPassword(this, R.string.settings_password, "settings_password", new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Intent i = new Intent(getApplicationContext(), PreferencesActivity.class);
|
||||
startActivity(i);
|
||||
}
|
||||
}, null);
|
||||
break;
|
||||
case R.id.nav_resetdb:
|
||||
new AlertDialog.Builder(this)
|
||||
|
@ -145,6 +155,9 @@ public class MainActivity extends AppCompatActivity {
|
|||
ImportExportPrefs.verifyStoragePermissions(this);
|
||||
ImportExportPrefs.importSharedPreferences(this);
|
||||
break;
|
||||
case R.id.nav_show_logcat:
|
||||
LogDialog.showLogcat(this);
|
||||
break;
|
||||
// case R.id.nav_test_alarm:
|
||||
// final int REQUEST_CODE_ASK_PERMISSIONS = 2355;
|
||||
// int permission = ActivityCompat.checkSelfPermission(this, Manifest.permission.SYSTEM_ALERT_WINDOW);
|
||||
|
@ -258,4 +271,21 @@ public class MainActivity extends AppCompatActivity {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchTouchEvent(MotionEvent event) {
|
||||
if (event.getAction() == MotionEvent.ACTION_DOWN) {
|
||||
View v = getCurrentFocus();
|
||||
if ( v instanceof EditText) {
|
||||
Rect outRect = new Rect();
|
||||
v.getGlobalVisibleRect(outRect);
|
||||
if (!outRect.contains((int)event.getRawX(), (int)event.getRawY())) {
|
||||
v.clearFocus();
|
||||
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.dispatchTouchEvent(event);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ import info.nightscout.androidaps.plugins.Loop.LoopFragment;
|
|||
import info.nightscout.androidaps.plugins.MDI.MDIFragment;
|
||||
import info.nightscout.androidaps.plugins.NSProfile.NSProfileFragment;
|
||||
import info.nightscout.androidaps.plugins.Objectives.ObjectivesFragment;
|
||||
import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAFragment;
|
||||
import info.nightscout.androidaps.plugins.OpenAPSMA.OpenAPSMAFragment;
|
||||
import info.nightscout.androidaps.plugins.Overview.OverviewFragment;
|
||||
import info.nightscout.androidaps.plugins.SafetyFragment.SafetyFragment;
|
||||
|
@ -38,6 +39,7 @@ import info.nightscout.androidaps.plugins.SourceMM640g.SourceMM640gFragment;
|
|||
import info.nightscout.androidaps.plugins.SourceNSClient.SourceNSClientFragment;
|
||||
import info.nightscout.androidaps.plugins.SourceXdrip.SourceXdripFragment;
|
||||
import info.nightscout.androidaps.plugins.TempBasals.TempBasalsFragment;
|
||||
import info.nightscout.androidaps.plugins.TempTargetRange.TempTargetRangeFragment;
|
||||
import info.nightscout.androidaps.plugins.Treatments.TreatmentsFragment;
|
||||
import info.nightscout.androidaps.plugins.VirtualPump.VirtualPumpFragment;
|
||||
import info.nightscout.androidaps.plugins.Wear.WearFragment;
|
||||
|
@ -82,11 +84,13 @@ public class MainApp extends Application {
|
|||
pluginsList.add(MDIFragment.getPlugin());
|
||||
pluginsList.add(VirtualPumpFragment.getPlugin());
|
||||
if (Config.LOOPENABLED) pluginsList.add(LoopFragment.getPlugin());
|
||||
if (Config.OPENAPSMAENABLED) pluginsList.add(OpenAPSMAFragment.getPlugin());
|
||||
if (Config.OPENAPSENABLED) pluginsList.add(OpenAPSMAFragment.getPlugin());
|
||||
if (Config.OPENAPSENABLED) pluginsList.add(OpenAPSAMAFragment.getPlugin());
|
||||
pluginsList.add(NSProfileFragment.getPlugin());
|
||||
pluginsList.add(SimpleProfileFragment.getPlugin());
|
||||
pluginsList.add(LocalProfileFragment.getPlugin());
|
||||
pluginsList.add(CircadianPercentageProfileFragment.getPlugin());
|
||||
if (Config.APS) pluginsList.add(TempTargetRangeFragment.getPlugin());
|
||||
pluginsList.add(TreatmentsFragment.getPlugin());
|
||||
pluginsList.add(TempBasalsFragment.getPlugin());
|
||||
pluginsList.add(SafetyFragment.getPlugin());
|
||||
|
|
|
@ -11,13 +11,15 @@ 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.androidaps.plugins.DanaRKorean.DanaRKoreanPlugin;
|
||||
import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin;
|
||||
import info.nightscout.androidaps.plugins.VirtualPump.VirtualPumpPlugin;
|
||||
import info.nightscout.utils.LocaleHelper;
|
||||
|
||||
public class PreferencesActivity extends PreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
@ -40,6 +42,9 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
|
|||
recreate();
|
||||
MainApp.bus().post(new EventRefreshGui(true));
|
||||
}
|
||||
if (key.equals("short_tabtitles")) {
|
||||
MainApp.bus().post(new EventRefreshGui(true));
|
||||
}
|
||||
updatePrefSummary(myPreferenceFragment.getPreference(key));
|
||||
}
|
||||
|
||||
|
@ -50,10 +55,10 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
|
|||
}
|
||||
if (pref instanceof EditTextPreference) {
|
||||
EditTextPreference editTextPref = (EditTextPreference) pref;
|
||||
if (pref.getTitle().toString().toLowerCase().contains("password"))
|
||||
{
|
||||
if (pref.getKey().contains("password")) {
|
||||
pref.setSummary("******");
|
||||
} else if (editTextPref.getText() != null && !editTextPref.getText().equals("")){
|
||||
} else if (editTextPref.getText() != null && !editTextPref.getText().equals("")) {
|
||||
((EditTextPreference) pref).setDialogMessage(editTextPref.getDialogMessage());
|
||||
pref.setSummary(editTextPref.getText());
|
||||
}
|
||||
}
|
||||
|
@ -78,6 +83,7 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
|
|||
@Override
|
||||
public void onCreate(final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
addPreferencesFromResource(R.xml.pref_password);
|
||||
addPreferencesFromResource(R.xml.pref_quickwizard);
|
||||
addPreferencesFromResource(R.xml.pref_language);
|
||||
if (Config.CAREPORTALENABLED)
|
||||
|
@ -85,20 +91,29 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
|
|||
addPreferencesFromResource(R.xml.pref_treatments);
|
||||
if (Config.APS)
|
||||
addPreferencesFromResource(R.xml.pref_closedmode);
|
||||
if (Config.OPENAPSMAENABLED)
|
||||
if (Config.OPENAPSENABLED)
|
||||
addPreferencesFromResource(R.xml.pref_openapsma);
|
||||
addPreferencesFromResource(R.xml.pref_nightscout);
|
||||
if (MainApp.getSpecificPlugin(OpenAPSAMAPlugin.class) != null && MainApp.getSpecificPlugin(OpenAPSAMAPlugin.class).isEnabled(PluginBase.APS))
|
||||
addPreferencesFromResource(R.xml.pref_openapsama);
|
||||
addPreferencesFromResource(R.xml.pref_profile);
|
||||
if (Config.DANAR) {
|
||||
DanaRPlugin danaRPlugin = (DanaRPlugin) MainApp.getSpecificPlugin(DanaRPlugin.class);
|
||||
DanaRKoreanPlugin danaRKoreanPlugin = (DanaRKoreanPlugin) MainApp.getSpecificPlugin(DanaRKoreanPlugin.class);
|
||||
if (danaRPlugin.isEnabled(PluginBase.PUMP) || danaRKoreanPlugin.isEnabled(PluginBase.PUMP)) {
|
||||
addPreferencesFromResource(R.xml.pref_danar);
|
||||
}
|
||||
if (danaRPlugin.isEnabled(PluginBase.PROFILE) || danaRKoreanPlugin.isEnabled(PluginBase.PROFILE)) {
|
||||
addPreferencesFromResource(R.xml.pref_danarprofile);
|
||||
}
|
||||
}
|
||||
VirtualPumpPlugin virtualPumpPlugin = (VirtualPumpPlugin) MainApp.getSpecificPlugin(VirtualPumpPlugin.class);
|
||||
if (virtualPumpPlugin != null && virtualPumpPlugin.isEnabled(PluginBase.PUMP)) {
|
||||
addPreferencesFromResource(R.xml.pref_virtualpump);
|
||||
}
|
||||
if (Config.SMSCOMMUNICATORENABLED)
|
||||
addPreferencesFromResource(R.xml.pref_smscommunicator);
|
||||
addPreferencesFromResource(R.xml.pref_others);
|
||||
addPreferencesFromResource(R.xml.pref_advanced);
|
||||
initSummary(getPreferenceScreen());
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@ 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;
|
||||
|
@ -29,26 +28,29 @@ 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.TempTarget;
|
||||
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.PluginBase;
|
||||
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.DanaR.History.DanaRNSHistorySync;
|
||||
import info.nightscout.androidaps.plugins.NSProfile.NSProfilePlugin;
|
||||
import info.nightscout.androidaps.plugins.Objectives.ObjectivesPlugin;
|
||||
import info.nightscout.androidaps.plugins.Overview.Notification;
|
||||
import info.nightscout.androidaps.plugins.Overview.OverviewPlugin;
|
||||
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
|
||||
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
|
||||
import info.nightscout.androidaps.plugins.SmsCommunicator.SmsCommunicatorPlugin;
|
||||
import info.nightscout.androidaps.plugins.SmsCommunicator.events.EventNewSMS;
|
||||
import info.nightscout.androidaps.plugins.SourceMM640g.SourceMM640gPlugin;
|
||||
import info.nightscout.androidaps.plugins.SourceNSClient.SourceNSClientPlugin;
|
||||
import info.nightscout.androidaps.plugins.SourceXdrip.SourceXdripPlugin;
|
||||
import info.nightscout.androidaps.plugins.TempTargetRange.events.EventTempTargetRangeChange;
|
||||
import info.nightscout.androidaps.receivers.DataReceiver;
|
||||
import info.nightscout.client.data.NSProfile;
|
||||
import info.nightscout.client.data.NSSgv;
|
||||
import info.nightscout.utils.ToastUtils;
|
||||
|
||||
|
||||
public class DataService extends IntentService {
|
||||
|
@ -251,10 +253,15 @@ public class DataService extends IntentService {
|
|||
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));
|
||||
if (ConfigBuilderPlugin.nsClientVersionCode < 121) {
|
||||
Notification notification = new Notification(Notification.OLD_NSCLIENT, MainApp.sResources.getString(R.string.unsupportedclientver), Notification.URGENT);
|
||||
MainApp.bus().post(new EventNewNotification(notification));
|
||||
} else {
|
||||
MainApp.bus().post(new EventDismissNotification(Notification.OLD_NSCLIENT));
|
||||
}
|
||||
} else {
|
||||
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.unsupportedclientver));
|
||||
Notification notification = new Notification(Notification.OLD_NSCLIENT, MainApp.sResources.getString(R.string.unsupportedclientver), Notification.URGENT);
|
||||
MainApp.bus().post(new EventNewNotification(notification));
|
||||
}
|
||||
if (bundles.containsKey("status")) {
|
||||
try {
|
||||
|
@ -378,7 +385,8 @@ public class DataService extends IntentService {
|
|||
String trstring = bundles.getString("treatment");
|
||||
JSONObject trJson = new JSONObject(trstring);
|
||||
String _id = trJson.getString("_id");
|
||||
removeTreatmentFromDb(_id);
|
||||
MainApp.getDbHelper().delete(_id);
|
||||
handleRemoveTempTargetRecord(trJson);
|
||||
}
|
||||
|
||||
if (bundles.containsKey("treatments")) {
|
||||
|
@ -387,7 +395,8 @@ public class DataService extends IntentService {
|
|||
for (int i = 0; i < jsonArray.length(); i++) {
|
||||
JSONObject trJson = jsonArray.getJSONObject(i);
|
||||
String _id = trJson.getString("_id");
|
||||
removeTreatmentFromDb(_id);
|
||||
MainApp.getDbHelper().delete(_id);
|
||||
handleRemoveTempTargetRecord(trJson);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
@ -443,6 +452,7 @@ public class DataService extends IntentService {
|
|||
private void handleAddedTreatment(String trstring) throws JSONException, SQLException {
|
||||
JSONObject trJson = new JSONObject(trstring);
|
||||
handleDanaRHistoryRecords(trJson); // update record _id in history
|
||||
handleAddChangeTempTargetRecord(trJson);
|
||||
if (!trJson.has("insulin") && !trJson.has("carbs")) {
|
||||
if (Config.logIncommingData)
|
||||
log.debug("ADD: Uninterested treatment: " + trstring);
|
||||
|
@ -455,9 +465,9 @@ public class DataService extends IntentService {
|
|||
if (trJson.has("timeIndex")) {
|
||||
if (Config.logIncommingData)
|
||||
log.debug("ADD: timeIndex found: " + trstring);
|
||||
stored = findByTimeIndex(trJson.getLong("timeIndex"));
|
||||
stored = MainApp.getDbHelper().findTreatmentByTimeIndex(trJson.getLong("timeIndex"));
|
||||
} else {
|
||||
stored = findById(_id);
|
||||
stored = MainApp.getDbHelper().findTreatmentById(_id);
|
||||
}
|
||||
|
||||
if (stored != null) {
|
||||
|
@ -465,10 +475,9 @@ public class DataService extends IntentService {
|
|||
log.debug("ADD: Existing treatment: " + trstring);
|
||||
if (trJson.has("timeIndex")) {
|
||||
stored._id = _id;
|
||||
int updated = MainApp.getDbHelper().getDaoTreatments().update(stored);
|
||||
int updated = MainApp.getDbHelper().update(stored);
|
||||
if (Config.logIncommingData)
|
||||
log.debug("Records updated: " + updated);
|
||||
scheduleTreatmentChange();
|
||||
}
|
||||
} else {
|
||||
if (Config.logIncommingData)
|
||||
|
@ -480,25 +489,29 @@ public class DataService extends IntentService {
|
|||
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)
|
||||
if (trJson.get("eventType").equals("Correction Bolus"))
|
||||
treatment.mealBolus = false;
|
||||
double carbs = treatment.carbs;
|
||||
if (trJson.has("boluscalc")) {
|
||||
JSONObject boluscalc = trJson.getJSONObject("boluscalc");
|
||||
if (boluscalc.has("carbs")) {
|
||||
carbs = Math.max(boluscalc.getDouble("carbs"), carbs);
|
||||
}
|
||||
}
|
||||
if (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();
|
||||
}
|
||||
scheduleTreatmentChange();
|
||||
MainApp.getDbHelper().createOrUpdate(treatment);
|
||||
if (Config.logIncommingData)
|
||||
log.debug("ADD: Stored treatment: " + treatment.log());
|
||||
}
|
||||
}
|
||||
|
||||
private void handleChangedTreatment(String trstring) throws JSONException, SQLException {
|
||||
JSONObject trJson = new JSONObject(trstring);
|
||||
handleDanaRHistoryRecords(trJson); // update record _id in history
|
||||
handleAddChangeTempTargetRecord(trJson);
|
||||
if (!trJson.has("insulin") && !trJson.has("carbs")) {
|
||||
if (Config.logIncommingData)
|
||||
log.debug("CHANGE: Uninterested treatment: " + trstring);
|
||||
|
@ -511,15 +524,15 @@ public class DataService extends IntentService {
|
|||
if (trJson.has("timeIndex")) {
|
||||
if (Config.logIncommingData)
|
||||
log.debug("ADD: timeIndex found: " + trstring);
|
||||
stored = findByTimeIndex(trJson.getLong("timeIndex"));
|
||||
stored = MainApp.getDbHelper().findTreatmentByTimeIndex(trJson.getLong("timeIndex"));
|
||||
} else {
|
||||
stored = findById(_id);
|
||||
stored = MainApp.getDbHelper().findTreatmentById(_id);
|
||||
}
|
||||
|
||||
if (stored != null) {
|
||||
if (Config.logIncommingData)
|
||||
log.debug("CHANGE: Removing old: " + trstring);
|
||||
removeTreatmentFromDb(_id);
|
||||
MainApp.getDbHelper().delete(_id);
|
||||
}
|
||||
|
||||
if (Config.logIncommingData)
|
||||
|
@ -532,21 +545,24 @@ public class DataService extends IntentService {
|
|||
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)
|
||||
if (trJson.get("eventType").equals("Correction Bolus"))
|
||||
treatment.mealBolus = false;
|
||||
double carbs = treatment.carbs;
|
||||
if (trJson.has("boluscalc")) {
|
||||
JSONObject boluscalc = trJson.getJSONObject("boluscalc");
|
||||
if (boluscalc.has("carbs")) {
|
||||
carbs = Math.max(boluscalc.getDouble("carbs"), carbs);
|
||||
}
|
||||
}
|
||||
if (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();
|
||||
}
|
||||
scheduleTreatmentChange();
|
||||
Dao.CreateOrUpdateStatus status = MainApp.getDbHelper().createOrUpdate(treatment);
|
||||
if (Config.logIncommingData)
|
||||
log.debug("Records updated: " + status.getNumLinesChanged());
|
||||
if (Config.logIncommingData)
|
||||
log.debug("CHANGE: Stored treatment: " + treatment.log());
|
||||
}
|
||||
|
||||
public void handleDanaRHistoryRecords(JSONObject trJson) throws JSONException, SQLException {
|
||||
|
@ -573,63 +589,83 @@ public class DataService extends IntentService {
|
|||
}
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
/*
|
||||
{
|
||||
"_id": "58795998aa86647ba4d68ce7",
|
||||
"enteredBy": "",
|
||||
"eventType": "Temporary Target",
|
||||
"reason": "Eating Soon",
|
||||
"targetTop": 80,
|
||||
"targetBottom": 80,
|
||||
"duration": 120,
|
||||
"created_at": "2017-01-13T22:50:00.782Z",
|
||||
"carbs": null,
|
||||
"insulin": 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);
|
||||
public void handleAddChangeTempTargetRecord(JSONObject trJson) throws JSONException, SQLException {
|
||||
if (trJson.has("eventType") && trJson.getString("eventType").equals("Temporary Target")) {
|
||||
if (Config.logIncommingData)
|
||||
log.debug("Records removed: " + removed);
|
||||
scheduleTreatmentChange();
|
||||
} else {
|
||||
log.debug("REMOVE: Not stored treatment (ignoring): " + _id);
|
||||
log.debug("Processing TempTarget record: " + trJson.toString());
|
||||
Dao<TempTarget, Long> daoTempTargets = MainApp.getDbHelper().getDaoTempTargets();
|
||||
QueryBuilder<TempTarget, Long> queryBuilder = daoTempTargets.queryBuilder();
|
||||
Where where = queryBuilder.where();
|
||||
where.eq("_id", trJson.getString("_id")).or().eq("timeIndex", trJson.getLong("mills"));
|
||||
PreparedQuery<TempTarget> preparedQuery = queryBuilder.prepare();
|
||||
List<TempTarget> list = daoTempTargets.query(preparedQuery);
|
||||
NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile();
|
||||
if (profile == null) return; // no profile data, better ignore than do something wrong
|
||||
String units = profile.getUnits();
|
||||
if (list.size() == 0) {
|
||||
// Record does not exists. add
|
||||
TempTarget newRecord = new TempTarget();
|
||||
newRecord.timeStart = new Date(trJson.getLong("mills"));
|
||||
newRecord.duration = trJson.getInt("duration");
|
||||
newRecord.low = NSProfile.toMgdl(trJson.getDouble("targetBottom"), units);
|
||||
newRecord.high = NSProfile.toMgdl(trJson.getDouble("targetTop"), units);
|
||||
newRecord.reason = trJson.getString("reason");
|
||||
newRecord._id = trJson.getString("_id");
|
||||
newRecord.setTimeIndex(newRecord.getTimeIndex());
|
||||
daoTempTargets.createIfNotExists(newRecord);
|
||||
if (Config.logIncommingData)
|
||||
log.debug("Adding TempTarget record to database: " + newRecord.log());
|
||||
MainApp.bus().post(new EventTempTargetRangeChange());
|
||||
} else if (list.size() == 1) {
|
||||
if (Config.logIncommingData)
|
||||
log.debug("Updating TempTarget record in database: " + trJson.getString("_id"));
|
||||
TempTarget record = list.get(0);
|
||||
record.timeStart = new Date(trJson.getLong("mills"));
|
||||
record.duration = trJson.getInt("duration");
|
||||
record.low = NSProfile.toMgdl(trJson.getDouble("targetBottom"), units);
|
||||
record.high = NSProfile.toMgdl(trJson.getDouble("targetTop"), units);
|
||||
record.reason = trJson.getString("reason");
|
||||
record._id = trJson.getString("_id");
|
||||
daoTempTargets.update(record);
|
||||
MainApp.bus().post(new EventTempTargetRangeChange());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void handleRemoveTempTargetRecord(JSONObject trJson) throws JSONException, SQLException {
|
||||
if (trJson.has("_id")) {
|
||||
Dao<TempTarget, Long> daoTempTargets = MainApp.getDbHelper().getDaoTempTargets();
|
||||
QueryBuilder<TempTarget, Long> queryBuilder = daoTempTargets.queryBuilder();
|
||||
Where where = queryBuilder.where();
|
||||
where.eq("_id", trJson.getString("_id"));
|
||||
PreparedQuery<TempTarget> preparedQuery = queryBuilder.prepare();
|
||||
List<TempTarget> list = daoTempTargets.query(preparedQuery);
|
||||
|
||||
if (list.size() == 1) {
|
||||
TempTarget record = list.get(0);
|
||||
if (Config.logIncommingData)
|
||||
log.debug("Removing TempTarget record from database: " + record.log());
|
||||
daoTempTargets.delete(record);
|
||||
MainApp.bus().post(new EventTempTargetRangeChange());
|
||||
} else {
|
||||
if (Config.logIncommingData)
|
||||
log.debug("TempTarget not found database: " + trJson.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -639,9 +675,4 @@ public class DataService extends IntentService {
|
|||
MainApp.bus().post(new EventNewSMS(bundle));
|
||||
}
|
||||
|
||||
public void scheduleTreatmentChange() {
|
||||
MainApp.bus().post(new EventTreatmentChange());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -31,4 +31,6 @@ public interface Intents {
|
|||
String ACTION_NEW_BG_ESTIMATE_NO_DATA = "com.eveningoutpost.dexdrip.BgEstimateNoData";
|
||||
|
||||
String NS_EMULATOR = "com.eveningoutpost.dexdrip.NS_EMULATOR";
|
||||
|
||||
String ACTION_REMOTE_CALIBRATION = "com.eveningoutpost.dexdrip.NewCalibration";
|
||||
}
|
||||
|
|
|
@ -0,0 +1,189 @@
|
|||
package info.nightscout.androidaps.data;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.Html;
|
||||
import android.text.Spanned;
|
||||
|
||||
import com.j256.ormlite.dao.Dao;
|
||||
import com.j256.ormlite.stmt.PreparedQuery;
|
||||
import com.j256.ormlite.stmt.QueryBuilder;
|
||||
|
||||
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.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.db.BgReading;
|
||||
import info.nightscout.utils.DecimalFormatter;
|
||||
import info.nightscout.utils.Round;
|
||||
|
||||
/**
|
||||
* Created by mike on 04.01.2017.
|
||||
*/
|
||||
|
||||
public class GlucoseStatus {
|
||||
private static Logger log = LoggerFactory.getLogger(GlucoseStatus.class);
|
||||
public double glucose = 0d;
|
||||
public double delta = 0d;
|
||||
public double avgdelta = 0d;
|
||||
public double short_avgdelta = 0d;
|
||||
public double long_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.short_avgdelta) + " " + DecimalFormatter.to2Decimal(short_avgdelta) + " mg/dl\n" +
|
||||
MainApp.sResources.getString(R.string.long_avgdelta) + " " + DecimalFormatter.to2Decimal(long_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.short_avgdelta) + "</b>: " + DecimalFormatter.to2Decimal(short_avgdelta) + " mg/dl<br>" +
|
||||
"<b>" + MainApp.sResources.getString(R.string.long_avgdelta) + "</b>: " + DecimalFormatter.to2Decimal(long_avgdelta) + " mg/dl");
|
||||
}
|
||||
|
||||
public GlucoseStatus() {
|
||||
}
|
||||
|
||||
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);
|
||||
this.short_avgdelta = Round.roundTo(this.short_avgdelta, 0.01);
|
||||
this.long_avgdelta = Round.roundTo(this.long_avgdelta, 0.01);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static GlucoseStatus getGlucoseStatusData() {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(MainApp.instance());
|
||||
|
||||
// load 45min
|
||||
long fromtime = (long) (new Date().getTime() - 60 * 1000L * 45);
|
||||
List<BgReading> data = MainApp.getDbHelper().getBgreadingsDataFromTime(fromtime, false);
|
||||
|
||||
int sizeRecords = data.size();
|
||||
if (sizeRecords < 4 || data.get(0).timeIndex < new Date().getTime() - 7 * 60 * 1000L) {
|
||||
return null;
|
||||
}
|
||||
|
||||
BgReading now = data.get(0);
|
||||
long now_date = now.timeIndex;
|
||||
double change;
|
||||
|
||||
ArrayList<Double> last_deltas = new ArrayList<Double>();
|
||||
ArrayList<Double> short_deltas = new ArrayList<Double>();
|
||||
ArrayList<Double> long_deltas = new ArrayList<Double>();
|
||||
|
||||
for (int i = 1; i < data.size(); i++) {
|
||||
if (data.get(i).value > 38) {
|
||||
BgReading then = data.get(i);
|
||||
long then_date = then.timeIndex;
|
||||
double avgdelta = 0;
|
||||
long minutesago;
|
||||
|
||||
minutesago = Math.round((now_date - then_date) / (1000d * 60));
|
||||
// multiply by 5 to get the same units as delta, i.e. mg/dL/5m
|
||||
change = now.value - then.value;
|
||||
avgdelta = change / minutesago * 5;
|
||||
|
||||
// use the average of all data points in the last 2.5m for all further "now" calculations
|
||||
if (0 < minutesago && minutesago < 2.5) {
|
||||
now.value = (now.value + then.value) / 2;
|
||||
now_date = (now_date + then_date) / 2;
|
||||
// short_deltas are calculated from everything ~5-15 minutes ago
|
||||
} else if (2.5 < minutesago && minutesago < 17.5) {
|
||||
//console.error(minutesago, avgdelta);
|
||||
short_deltas.add(avgdelta);
|
||||
// last_deltas are calculated from everything ~5 minutes ago
|
||||
if (2.5 < minutesago && minutesago < 7.5) {
|
||||
last_deltas.add(avgdelta);
|
||||
}
|
||||
// long_deltas are calculated from everything ~20-40 minutes ago
|
||||
} else if (17.5 < minutesago && minutesago < 42.5) {
|
||||
long_deltas.add(avgdelta);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GlucoseStatus status = new GlucoseStatus();
|
||||
status.glucose = now.value;
|
||||
|
||||
status.short_avgdelta = average(short_deltas);
|
||||
|
||||
if(prefs.getBoolean("always_use_shortavg",false) || last_deltas.isEmpty()){
|
||||
status.delta = status.short_avgdelta;
|
||||
} else {
|
||||
status.delta = average(last_deltas);
|
||||
}
|
||||
|
||||
status.long_avgdelta = average(long_deltas);
|
||||
status.avgdelta = status.short_avgdelta; // for OpenAPS MA
|
||||
|
||||
return status.round();
|
||||
}
|
||||
|
||||
/*
|
||||
* Return last BgReading from database or null if db is empty
|
||||
*/
|
||||
@Nullable
|
||||
public static 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);
|
||||
queryBuilder.where().gt("value", 38);
|
||||
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 static BgReading actualBg() {
|
||||
BgReading lastBg = lastBg();
|
||||
|
||||
if (lastBg == null)
|
||||
return null;
|
||||
|
||||
if (lastBg.timeIndex > new Date().getTime() - 9 * 60 * 1000)
|
||||
return lastBg;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static double average(ArrayList<Double> array) {
|
||||
double sum = 0d;
|
||||
|
||||
if (array.size() == 0)
|
||||
return 0d;
|
||||
|
||||
for (Double value : array) {
|
||||
sum += value;
|
||||
}
|
||||
return sum / array.size();
|
||||
}
|
||||
}
|
137
app/src/main/java/info/nightscout/androidaps/data/IobTotal.java
Normal file
137
app/src/main/java/info/nightscout/androidaps/data/IobTotal.java
Normal file
|
@ -0,0 +1,137 @@
|
|||
package info.nightscout.androidaps.data;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.client.data.NSProfile;
|
||||
import info.nightscout.utils.DateUtil;
|
||||
import info.nightscout.utils.Round;
|
||||
|
||||
public class IobTotal {
|
||||
public Double iob;
|
||||
public Double activity;
|
||||
public Double bolussnooze;
|
||||
public Double basaliob;
|
||||
public Double netbasalinsulin;
|
||||
public Double hightempinsulin;
|
||||
|
||||
public Double netInsulin = 0d; // for calculations from temp basals only
|
||||
public Double netRatio = 0d; // for calculations from temp basals only
|
||||
|
||||
long time;
|
||||
|
||||
public IobTotal(long time) {
|
||||
this.iob = 0d;
|
||||
this.activity = 0d;
|
||||
this.bolussnooze = 0d;
|
||||
this.basaliob = 0d;
|
||||
this.netbasalinsulin = 0d;
|
||||
this.hightempinsulin = 0d;
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
public IobTotal plus(IobTotal other) {
|
||||
iob += other.iob;
|
||||
activity += other.activity;
|
||||
bolussnooze += other.bolussnooze;
|
||||
basaliob += other.basaliob;
|
||||
netbasalinsulin += other.netbasalinsulin;
|
||||
hightempinsulin += other.hightempinsulin;
|
||||
netInsulin += other.netInsulin;
|
||||
netRatio += other.netRatio;
|
||||
return this;
|
||||
}
|
||||
|
||||
public static IobTotal combine(IobTotal bolusIOB, IobTotal basalIob) {
|
||||
IobTotal result = new IobTotal(bolusIOB.time);
|
||||
result.iob = bolusIOB.iob + basalIob.basaliob;
|
||||
result.activity = bolusIOB.activity + basalIob.activity;
|
||||
result.bolussnooze = bolusIOB.bolussnooze;
|
||||
result.basaliob = basalIob.basaliob;
|
||||
result.netbasalinsulin = basalIob.netbasalinsulin;
|
||||
result.hightempinsulin = basalIob.hightempinsulin;
|
||||
return result;
|
||||
}
|
||||
|
||||
public IobTotal round() {
|
||||
this.iob = Round.roundTo(this.iob, 0.001);
|
||||
this.activity = Round.roundTo(this.activity, 0.0001);
|
||||
this.bolussnooze = Round.roundTo(this.bolussnooze, 0.0001);
|
||||
this.basaliob = Round.roundTo(this.basaliob, 0.001);
|
||||
this.netbasalinsulin = Round.roundTo(this.netbasalinsulin, 0.001);
|
||||
this.hightempinsulin = Round.roundTo(this.hightempinsulin, 0.001);
|
||||
return this;
|
||||
}
|
||||
|
||||
public JSONObject json() {
|
||||
JSONObject json = new JSONObject();
|
||||
try {
|
||||
json.put("iob", iob);
|
||||
json.put("basaliob", basaliob);
|
||||
json.put("activity", activity);
|
||||
json.put("time", DateUtil.toISOString(new Date()));
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
public JSONObject determineBasalJson() {
|
||||
JSONObject json = new JSONObject();
|
||||
try {
|
||||
json.put("iob", iob);
|
||||
json.put("basaliob", basaliob);
|
||||
json.put("bolussnooze", bolussnooze);
|
||||
json.put("activity", activity);
|
||||
json.put("time", DateUtil.toISOString(new Date(time)));
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
public static IobTotal calulateFromTreatmentsAndTemps() {
|
||||
ConfigBuilderPlugin.getActiveTreatments().updateTotalIOB();
|
||||
IobTotal bolusIob = ConfigBuilderPlugin.getActiveTreatments().getLastCalculation().round();
|
||||
ConfigBuilderPlugin.getActiveTempBasals().updateTotalIOB();
|
||||
IobTotal basalIob = ConfigBuilderPlugin.getActiveTempBasals().getLastCalculation().round();
|
||||
IobTotal iobTotal = IobTotal.combine(bolusIob, basalIob).round();
|
||||
return iobTotal;
|
||||
}
|
||||
|
||||
public static IobTotal calulateFromTreatmentsAndTemps(long time) {
|
||||
IobTotal bolusIob = ConfigBuilderPlugin.getActiveTreatments().getCalculationToTime(time).round();
|
||||
IobTotal basalIob = ConfigBuilderPlugin.getActiveTempBasals().getCalculationToTime(time).round();
|
||||
IobTotal iobTotal = IobTotal.combine(bolusIob, basalIob).round();
|
||||
return iobTotal;
|
||||
}
|
||||
|
||||
public static IobTotal[] calculateIobArrayInDia() {
|
||||
NSProfile profile = ConfigBuilderPlugin.getActiveProfile().getProfile();
|
||||
// predict IOB out to DIA plus 30m
|
||||
long time = new Date().getTime();
|
||||
int len = (int) ((profile.getDia() *60 + 30) / 5);
|
||||
IobTotal[] array = new IobTotal[len];
|
||||
int pos = 0;
|
||||
for (int i = 0; i < len; i++){
|
||||
long t = time + i * 5 * 60000;
|
||||
IobTotal iob = calulateFromTreatmentsAndTemps(t);
|
||||
array[pos] = iob;
|
||||
pos++;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
public static JSONArray convertToJSONArray(IobTotal[] iobArray) {
|
||||
JSONArray array = new JSONArray();
|
||||
for (int i = 0; i < iobArray.length; i ++) {
|
||||
array.put(iobArray[i].determineBasalJson());
|
||||
}
|
||||
return array;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package info.nightscout.androidaps.data;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.db.BgReading;
|
||||
import info.nightscout.androidaps.db.Treatment;
|
||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||
import info.nightscout.androidaps.plugins.OpenAPSAMA.Autosens;
|
||||
import info.nightscout.androidaps.plugins.OpenAPSAMA.AutosensResult;
|
||||
import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin;
|
||||
import info.nightscout.client.data.NSProfile;
|
||||
|
||||
/**
|
||||
* Created by mike on 04.01.2017.
|
||||
*/
|
||||
public class MealData {
|
||||
public double boluses = 0d;
|
||||
public double carbs = 0d;
|
||||
public double mealCOB = 0.0d;
|
||||
|
||||
|
||||
public void addTreatment(Treatment treatment) {
|
||||
NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile();
|
||||
if (profile == null) return;
|
||||
|
||||
List<BgReading> bgReadings = MainApp.getDbHelper().getBgreadingsDataFromTime((long) (new Date().getTime() - 60 * 60 * 1000L * profile.getDia() * 2), false);
|
||||
|
||||
long now = new Date().getTime();
|
||||
long dia_ago = now - (new Double(1.5d * profile.getDia() * 60 * 60 * 1000l)).longValue();
|
||||
long t = treatment.created_at.getTime();
|
||||
if (t > dia_ago && t <= now) {
|
||||
if (treatment.carbs >= 1) {
|
||||
carbs += treatment.carbs;
|
||||
if (MainApp.getSpecificPlugin(OpenAPSAMAPlugin.class).isEnabled(PluginBase.APS)) {
|
||||
AutosensResult result = Autosens.detectSensitivityandCarbAbsorption(bgReadings, t);
|
||||
double myCarbsAbsorbed = result.carbsAbsorbed;
|
||||
double myMealCOB = Math.max(0, carbs - myCarbsAbsorbed);
|
||||
mealCOB = Math.max(mealCOB, myMealCOB);
|
||||
}
|
||||
}
|
||||
if (treatment.insulin > 0 && treatment.mealBolus) {
|
||||
boluses += treatment.insulin;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -14,7 +14,7 @@ import info.nightscout.client.data.NSProfile;
|
|||
import info.nightscout.utils.DecimalFormatter;
|
||||
import info.nightscout.utils.Round;
|
||||
|
||||
public class PumpEnactResult extends Object implements Parcelable {
|
||||
public class PumpEnactResult extends Object {
|
||||
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 = "";
|
||||
|
@ -85,43 +85,6 @@ public class PumpEnactResult extends Object implements Parcelable {
|
|||
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() {
|
||||
}
|
||||
|
||||
|
|
|
@ -3,11 +3,7 @@ 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;
|
||||
|
@ -24,12 +20,15 @@ import java.sql.SQLException;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
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.Constants;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.utils.DecimalFormatter;
|
||||
import info.nightscout.utils.Round;
|
||||
import info.nightscout.androidaps.events.EventTreatmentChange;
|
||||
|
||||
public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||
private static Logger log = LoggerFactory.getLogger(DatabaseHelper.class);
|
||||
|
@ -37,13 +36,20 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
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_TEMPTARGETS = "TempTargets";
|
||||
public static final String DATABASE_TREATMENTS = "Treatments";
|
||||
public static final String DATABASE_DANARHISTORY = "DanaRHistory";
|
||||
|
||||
private static final int DATABASE_VERSION = 5;
|
||||
|
||||
private long latestTreatmentChange = 0;
|
||||
|
||||
private static final ScheduledExecutorService worker = Executors.newSingleThreadScheduledExecutor();
|
||||
private static ScheduledFuture<?> scheduledPost = null;
|
||||
|
||||
public DatabaseHelper(Context context) {
|
||||
super(context, DATABASE_NAME, null, DATABASE_VERSION);
|
||||
onCreate(getWritableDatabase(), getConnectionSource());
|
||||
}
|
||||
|
||||
|
||||
|
@ -52,11 +58,12 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
try {
|
||||
log.info("onCreate");
|
||||
TableUtils.createTableIfNotExists(connectionSource, TempBasal.class);
|
||||
TableUtils.createTableIfNotExists(connectionSource, TempTarget.class);
|
||||
TableUtils.createTableIfNotExists(connectionSource, Treatment.class);
|
||||
TableUtils.createTableIfNotExists(connectionSource, BgReading.class);
|
||||
TableUtils.createTableIfNotExists(connectionSource, DanaRHistoryRecord.class);
|
||||
} catch (SQLException e) {
|
||||
log.error(DatabaseHelper.class.getName(), "Can't create database", e);
|
||||
log.error("Can't create database", e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
@ -66,12 +73,13 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
try {
|
||||
log.info(DatabaseHelper.class.getName(), "onUpgrade");
|
||||
TableUtils.dropTable(connectionSource, TempBasal.class, true);
|
||||
TableUtils.dropTable(connectionSource, TempTarget.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);
|
||||
log.error("Can't drop databases", e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
@ -87,35 +95,39 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
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);
|
||||
getWritableDatabase().delete(DATABASE_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);
|
||||
getWritableDatabase().delete(DATABASE_TEMPBASALS, "timeIndex" + " < '" + (new Date().getTime() - Constants.hoursToKeepInDatabase * 60 * 60 * 1000L) + "'", null);
|
||||
log.debug("After TempBasals size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_TEMPBASALS));
|
||||
|
||||
log.debug("Before TempTargets size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_TEMPTARGETS));
|
||||
getWritableDatabase().delete(DATABASE_TEMPTARGETS, "timeIndex" + " < '" + (new Date().getTime() - Constants.hoursToKeepInDatabase * 60 * 60 * 1000L) + "'", null);
|
||||
log.debug("After TempTargets size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_TEMPTARGETS));
|
||||
|
||||
log.debug("Before Treatments size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_TREATMENTS));
|
||||
getWritableDatabase().delete("Treatments", "timeIndex" + " < '" + (new Date().getTime() - Constants.hoursToKeepInDatabase * 60 * 60 * 1000L) + "'", null);
|
||||
getWritableDatabase().delete(DATABASE_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"));
|
||||
log.debug("Before History size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_DANARHISTORY));
|
||||
getWritableDatabase().delete(DATABASE_DANARHISTORY, "recordDate" + " < '" + (new Date().getTime() - Constants.daysToKeepHistoryInDatabase * 24 * 60 * 60 * 1000L) + "'", null);
|
||||
log.debug("After History size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_DANARHISTORY));
|
||||
}
|
||||
|
||||
public void resetDatabases() {
|
||||
try {
|
||||
TableUtils.dropTable(connectionSource, TempBasal.class, true);
|
||||
TableUtils.dropTable(connectionSource, TempTarget.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, TempTarget.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());
|
||||
latestTreatmentChange = 0;
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
@ -123,9 +135,18 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
|
||||
public void resetTreatments() {
|
||||
try {
|
||||
|
||||
TableUtils.dropTable(connectionSource, Treatment.class, true);
|
||||
TableUtils.createTableIfNotExists(connectionSource, Treatment.class);
|
||||
latestTreatmentChange = 0;
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void resetTempTargets() {
|
||||
try {
|
||||
TableUtils.dropTable(connectionSource, TempTarget.class, true);
|
||||
TableUtils.createTableIfNotExists(connectionSource, TempTarget.class);
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
@ -135,7 +156,11 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
return getDao(TempBasal.class);
|
||||
}
|
||||
|
||||
public Dao<Treatment, Long> getDaoTreatments() throws SQLException {
|
||||
public Dao<TempTarget, Long> getDaoTempTargets() throws SQLException {
|
||||
return getDao(TempTarget.class);
|
||||
}
|
||||
|
||||
private Dao<Treatment, Long> getDaoTreatments() throws SQLException {
|
||||
return getDao(Treatment.class);
|
||||
}
|
||||
|
||||
|
@ -147,54 +172,12 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
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);
|
||||
queryBuilder.where().gt("value", 38);
|
||||
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) {
|
||||
public List<BgReading> getBgreadingsDataFromTime(long mills, boolean ascending) {
|
||||
try {
|
||||
Dao<BgReading, Long> daoBgreadings = getDaoBgReadings();
|
||||
List<BgReading> bgReadings;
|
||||
QueryBuilder<BgReading, Long> queryBuilder = daoBgreadings.queryBuilder();
|
||||
queryBuilder.orderBy("timeIndex", true);
|
||||
queryBuilder.orderBy("timeIndex", ascending);
|
||||
Where where = queryBuilder.where();
|
||||
where.ge("timeIndex", mills).and().gt("value", 38);
|
||||
PreparedQuery<BgReading> preparedQuery = queryBuilder.prepare();
|
||||
|
@ -206,126 +189,191 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
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;
|
||||
// TREATMENT HANDLING
|
||||
|
||||
@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 boolean isDataUnchanged(long time) {
|
||||
if (time >= latestTreatmentChange) return true;
|
||||
else return false;
|
||||
}
|
||||
|
||||
public int update(Treatment treatment) {
|
||||
int updated = 0;
|
||||
try {
|
||||
updated = getDaoTreatments().update(treatment);
|
||||
latestTreatmentChange = treatment.getTimeIndex();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
scheduleTreatmentChange();
|
||||
return updated;
|
||||
}
|
||||
|
||||
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");
|
||||
public Dao.CreateOrUpdateStatus createOrUpdate(Treatment treatment) {
|
||||
Dao.CreateOrUpdateStatus status = null;
|
||||
try {
|
||||
status = getDaoTreatments().createOrUpdate(treatment);
|
||||
latestTreatmentChange = treatment.getTimeIndex();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
scheduleTreatmentChange();
|
||||
return status;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
public void create(Treatment treatment) {
|
||||
try {
|
||||
getDaoTreatments().create(treatment);
|
||||
latestTreatmentChange = treatment.getTimeIndex();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
scheduleTreatmentChange();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeDouble(avgdelta);
|
||||
dest.writeDouble(delta);
|
||||
dest.writeDouble(glucose);
|
||||
public void delete(Treatment treatment) {
|
||||
try {
|
||||
getDaoTreatments().delete(treatment);
|
||||
latestTreatmentChange = treatment.getTimeIndex();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
scheduleTreatmentChange();
|
||||
}
|
||||
|
||||
public final Parcelable.Creator<GlucoseStatus> CREATOR = new Parcelable.Creator<GlucoseStatus>() {
|
||||
public GlucoseStatus createFromParcel(Parcel in) {
|
||||
return new GlucoseStatus(in);
|
||||
public int delete(String _id) {
|
||||
Treatment stored = findTreatmentById(_id);
|
||||
int removed = 0;
|
||||
if (stored != null) {
|
||||
log.debug("REMOVE: Existing treatment (removing): " + _id);
|
||||
try {
|
||||
removed = getDaoTreatments().delete(stored);
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
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;
|
||||
if (Config.logIncommingData)
|
||||
log.debug("Records removed: " + removed);
|
||||
latestTreatmentChange = stored.getTimeIndex();
|
||||
scheduleTreatmentChange();
|
||||
} else {
|
||||
log.debug("REMOVE: Not stored treatment (ignoring): " + _id);
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public GlucoseStatus getGlucoseStatusData() {
|
||||
GlucoseStatus result = new GlucoseStatus();
|
||||
public Treatment findTreatmentById(String _id) {
|
||||
try {
|
||||
|
||||
Dao<BgReading, Long> daoBgreadings = null;
|
||||
daoBgreadings = getDaoBgReadings();
|
||||
List<BgReading> bgReadings;
|
||||
QueryBuilder<BgReading, Long> queryBuilder = daoBgreadings.queryBuilder();
|
||||
queryBuilder.orderBy("timeIndex", false);
|
||||
queryBuilder.where().gt("value", 38);
|
||||
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) {
|
||||
Dao<Treatment, Long> daoTreatments = getDaoTreatments();
|
||||
QueryBuilder<Treatment, Long> queryBuilder = daoTreatments.queryBuilder();
|
||||
Where where = queryBuilder.where();
|
||||
where.eq("_id", _id);
|
||||
queryBuilder.limit(10L);
|
||||
PreparedQuery<Treatment> preparedQuery = queryBuilder.prepare();
|
||||
List<Treatment> trList = daoTreatments.query(preparedQuery);
|
||||
if (trList.size() != 1) {
|
||||
//log.debug("Treatment findTreatmentById query size: " + trList.size());
|
||||
return null;
|
||||
}
|
||||
|
||||
double 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 > 38) {
|
||||
minutes = (now.timeIndex - last2.timeIndex)/(60d*1000);
|
||||
change = now.value - last2.value;
|
||||
} else if (last1.value > 38) {
|
||||
minutes = (now.timeIndex - last1.timeIndex)/(60d*1000);;
|
||||
change = now.value - last1.value;
|
||||
} else if (last.value > 38) {
|
||||
minutes = (now.timeIndex - last.timeIndex)/(60d*1000);
|
||||
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)*5*60*1000/(now.getTimeIndex() - last.getTimeIndex());
|
||||
result.avgdelta = avg;
|
||||
} else {
|
||||
//log.debug("Treatment findTreatmentById found: " + trList.get(0).log());
|
||||
return trList.get(0);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
result.round();
|
||||
return result;
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Treatment findTreatmentByTimeIndex(Long timeIndex) {
|
||||
try {
|
||||
QueryBuilder<Treatment, String> qb = null;
|
||||
Dao<Treatment, Long> daoTreatments = getDaoTreatments();
|
||||
QueryBuilder<Treatment, Long> queryBuilder = daoTreatments.queryBuilder();
|
||||
Where where = queryBuilder.where();
|
||||
where.eq("timeIndex", timeIndex);
|
||||
queryBuilder.limit(10L);
|
||||
PreparedQuery<Treatment> preparedQuery = queryBuilder.prepare();
|
||||
List<Treatment> trList = daoTreatments.query(preparedQuery);
|
||||
if (trList.size() != 1) {
|
||||
log.debug("Treatment findTreatmentByTimeIndex query size: " + trList.size());
|
||||
return null;
|
||||
} else {
|
||||
log.debug("Treatment findTreatmentByTimeIndex found: " + trList.get(0).log());
|
||||
return trList.get(0);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static public void scheduleTreatmentChange() {
|
||||
class PostRunnable implements Runnable {
|
||||
public void run() {
|
||||
MainApp.bus().post(new EventTreatmentChange());
|
||||
scheduledPost = null;
|
||||
}
|
||||
}
|
||||
// prepare task for execution in 5 sec
|
||||
// cancel waiting task to prevent sending multiple posts
|
||||
if (scheduledPost != null)
|
||||
scheduledPost.cancel(false);
|
||||
Runnable task = new PostRunnable();
|
||||
final int sec = 5;
|
||||
scheduledPost = worker.schedule(task, sec, TimeUnit.SECONDS);
|
||||
|
||||
}
|
||||
|
||||
public List<Treatment> getTreatmentDataFromTime(long mills, boolean ascending) {
|
||||
try {
|
||||
Dao<Treatment, Long> daoTreatments = getDaoTreatments();
|
||||
List<Treatment> treatments;
|
||||
QueryBuilder<Treatment, Long> queryBuilder = daoTreatments.queryBuilder();
|
||||
queryBuilder.orderBy("timeIndex", ascending);
|
||||
Where where = queryBuilder.where();
|
||||
where.ge("timeIndex", mills);
|
||||
PreparedQuery<Treatment> preparedQuery = queryBuilder.prepare();
|
||||
treatments = daoTreatments.query(preparedQuery);
|
||||
return treatments;
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return new ArrayList<Treatment>();
|
||||
}
|
||||
|
||||
public List<TempTarget> getTemptargetsDataFromTime(long mills, boolean ascending) {
|
||||
try {
|
||||
Dao<TempTarget, Long> daoTempTargets = getDaoTempTargets();
|
||||
List<TempTarget> tempTargets;
|
||||
QueryBuilder<TempTarget, Long> queryBuilder = daoTempTargets.queryBuilder();
|
||||
queryBuilder.orderBy("timeIndex", ascending);
|
||||
Where where = queryBuilder.where();
|
||||
where.ge("timeIndex", mills);
|
||||
PreparedQuery<TempTarget> preparedQuery = queryBuilder.prepare();
|
||||
tempTargets = daoTempTargets.query(preparedQuery);
|
||||
return tempTargets;
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return new ArrayList<TempTarget>();
|
||||
}
|
||||
|
||||
|
||||
public List<TempBasal> getTempbasalsDataFromTime(long mills, boolean ascending, boolean isExtended) {
|
||||
try {
|
||||
Dao<TempBasal, Long> daoTempbasals = getDaoTempBasals();
|
||||
List<TempBasal> tempbasals;
|
||||
QueryBuilder<TempBasal, Long> queryBuilder = daoTempbasals.queryBuilder();
|
||||
queryBuilder.orderBy("timeIndex", ascending);
|
||||
Where where = queryBuilder.where();
|
||||
where.ge("timeIndex", mills).and().eq("isExtended", isExtended);
|
||||
PreparedQuery<TempBasal> preparedQuery = queryBuilder.prepare();
|
||||
tempbasals = daoTempbasals.query(preparedQuery);
|
||||
return tempbasals;
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return new ArrayList<TempBasal>();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ 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.androidaps.data.IobTotal;
|
||||
import info.nightscout.client.data.NSProfile;
|
||||
import info.nightscout.utils.DateUtil;
|
||||
import info.nightscout.utils.DecimalFormatter;
|
||||
|
@ -53,7 +53,7 @@ public class TempBasal {
|
|||
|
||||
|
||||
public IobTotal iobCalc(Date time) {
|
||||
IobTotal result = new IobTotal();
|
||||
IobTotal result = new IobTotal(time.getTime());
|
||||
NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile();
|
||||
|
||||
if (profile == null)
|
||||
|
@ -131,7 +131,7 @@ public class TempBasal {
|
|||
|
||||
public int getRealDuration() {
|
||||
Long msecs = getTimeEnd().getTime() - timeStart.getTime();
|
||||
return (int) (msecs / 60 / 1000);
|
||||
return Math.round(msecs / 60f / 1000);
|
||||
}
|
||||
|
||||
public long getMillisecondsFromStart() {
|
||||
|
@ -140,8 +140,8 @@ public class TempBasal {
|
|||
|
||||
public int getPlannedRemainingMinutes() {
|
||||
if (timeEnd != null) return 0;
|
||||
long remainingMin = (getPlannedTimeEnd().getTime() - new Date().getTime()) / 1000 / 60;
|
||||
return (remainingMin < 0) ? 0 : (int) remainingMin;
|
||||
float remainingMin = (getPlannedTimeEnd().getTime() - new Date().getTime()) / 1000f / 60;
|
||||
return (remainingMin < 0) ? 0 : Math.round(remainingMin);
|
||||
}
|
||||
|
||||
public boolean isInProgress() {
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
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.util.Date;
|
||||
|
||||
import info.nightscout.androidaps.Constants;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.plugins.TempTargetRange.TempTargetRangePlugin;
|
||||
import info.nightscout.utils.DecimalFormatter;
|
||||
|
||||
@DatabaseTable(tableName = DatabaseHelper.DATABASE_TEMPTARGETS)
|
||||
public class TempTarget {
|
||||
private static Logger log = LoggerFactory.getLogger(TempTarget.class);
|
||||
|
||||
public long getTimeIndex() {
|
||||
return timeStart.getTime() - timeStart.getTime() % 1000;
|
||||
}
|
||||
|
||||
public void setTimeIndex(long timeIndex) {
|
||||
this.timeIndex = timeIndex;
|
||||
}
|
||||
|
||||
@DatabaseField(id = true, useGetSet = true)
|
||||
public long timeIndex;
|
||||
|
||||
@DatabaseField
|
||||
public Date timeStart;
|
||||
|
||||
@DatabaseField
|
||||
public double low; // in mgdl
|
||||
|
||||
@DatabaseField
|
||||
public double high; // in mgdl
|
||||
|
||||
@DatabaseField
|
||||
public String reason;
|
||||
|
||||
@DatabaseField
|
||||
public int duration; // in minutes
|
||||
|
||||
@DatabaseField
|
||||
public String _id; // NS _id
|
||||
|
||||
public Date getPlannedTimeEnd() {
|
||||
return new Date(timeStart.getTime() + 60 * 1_000 * duration);
|
||||
}
|
||||
|
||||
public String lowValueToUnitsToString(String units) {
|
||||
if (units.equals(Constants.MGDL)) return DecimalFormatter.to0Decimal(low);
|
||||
else return DecimalFormatter.to1Decimal(low * Constants.MGDL_TO_MMOLL);
|
||||
}
|
||||
|
||||
public String highValueToUnitsToString(String units) {
|
||||
if (units.equals(Constants.MGDL)) return DecimalFormatter.to0Decimal(high);
|
||||
else return DecimalFormatter.to1Decimal(low * Constants.MGDL_TO_MMOLL);
|
||||
}
|
||||
|
||||
public boolean isInProgress() {
|
||||
return ((TempTargetRangePlugin) MainApp.getSpecificPlugin(TempTargetRangePlugin.class)).getTempTargetInProgress(new Date().getTime()) == this;
|
||||
}
|
||||
|
||||
public String log() {
|
||||
return "TempTarget{" +
|
||||
"timeIndex=" + timeIndex +
|
||||
", timeStart=" + timeStart +
|
||||
", duration=" + duration +
|
||||
", reason=" + reason +
|
||||
", low=" + low +
|
||||
", high=" + high +
|
||||
'}';
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package info.nightscout.androidaps.events;
|
||||
|
||||
/**
|
||||
* Created by adrian on 07/02/17.
|
||||
*/
|
||||
|
||||
public class EventBolusRequested {
|
||||
private double amount;
|
||||
|
||||
public EventBolusRequested (double amount){
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
public double getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
public void setAmount(double amount) {
|
||||
this.amount = amount;
|
||||
}
|
||||
}
|
|
@ -11,5 +11,5 @@ public interface APSInterface {
|
|||
public APSResult getLastAPSResult();
|
||||
public Date getLastAPSRun();
|
||||
|
||||
public void invoke();
|
||||
public void invoke(String initiator);
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ public interface PluginBase {
|
|||
String getFragmentClass();
|
||||
|
||||
String getName();
|
||||
String getNameShort();
|
||||
boolean isEnabled(int type);
|
||||
boolean isVisibleInTabs(int type);
|
||||
boolean canBeHidden(int type);
|
||||
|
|
|
@ -17,6 +17,8 @@ import info.nightscout.client.data.NSProfile;
|
|||
public interface PumpInterface {
|
||||
|
||||
boolean isInitialized();
|
||||
boolean isSuspended();
|
||||
boolean isBusy();
|
||||
|
||||
boolean isTempBasalInProgress();
|
||||
boolean isExtendedBoluslInProgress();
|
||||
|
@ -28,6 +30,9 @@ public interface PumpInterface {
|
|||
int setNewBasalProfile(NSProfile profile);
|
||||
boolean isThisProfileSet(NSProfile profile);
|
||||
|
||||
Date lastStatusTime();
|
||||
void updateStatus(String reason);
|
||||
|
||||
double getBaseBasalRate(); // base basal rate, not temp basal
|
||||
double getTempBasalAbsoluteRate();
|
||||
double getTempBasalRemainingMinutes();
|
||||
|
@ -48,4 +53,6 @@ public interface PumpInterface {
|
|||
String deviceID();
|
||||
|
||||
PumpDescription getPumpDescription();
|
||||
|
||||
public String shortStatus(boolean veryShort);
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ package info.nightscout.androidaps.interfaces;
|
|||
import java.util.Date;
|
||||
|
||||
import info.nightscout.androidaps.db.TempBasal;
|
||||
import info.nightscout.androidaps.plugins.OpenAPSMA.IobTotal;
|
||||
import info.nightscout.androidaps.data.IobTotal;
|
||||
|
||||
/**
|
||||
* Created by mike on 14.06.2016.
|
||||
|
@ -11,7 +11,10 @@ import info.nightscout.androidaps.plugins.OpenAPSMA.IobTotal;
|
|||
public interface TempBasalsInterface {
|
||||
void updateTotalIOB();
|
||||
IobTotal getLastCalculation();
|
||||
IobTotal getCalculationToTime(long time);
|
||||
|
||||
TempBasal getTempBasal (Date time);
|
||||
TempBasal getExtendedBolus (Date time);
|
||||
|
||||
long oldestDataAvaialable();
|
||||
}
|
||||
|
|
|
@ -2,10 +2,9 @@ package info.nightscout.androidaps.interfaces;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import info.nightscout.androidaps.data.MealData;
|
||||
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;
|
||||
import info.nightscout.androidaps.data.IobTotal;
|
||||
|
||||
/**
|
||||
* Created by mike on 14.06.2016.
|
||||
|
@ -14,6 +13,7 @@ public interface TreatmentsInterface {
|
|||
|
||||
void updateTotalIOB();
|
||||
IobTotal getLastCalculation();
|
||||
TreatmentsPlugin.MealData getMealData();
|
||||
IobTotal getCalculationToTime(long time);
|
||||
MealData getMealData();
|
||||
List<Treatment> getTreatments();
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import android.widget.Button;
|
|||
|
||||
import com.squareup.otto.Subscribe;
|
||||
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.events.EventInitializationChanged;
|
||||
|
@ -35,6 +36,7 @@ public class ActionsFragment extends Fragment implements FragmentBase, View.OnCl
|
|||
}
|
||||
|
||||
Button profileSwitch;
|
||||
Button tempTarget;
|
||||
Button extendedBolus;
|
||||
Button tempBasal;
|
||||
Button fill;
|
||||
|
@ -49,11 +51,13 @@ public class ActionsFragment extends Fragment implements FragmentBase, View.OnCl
|
|||
View view = inflater.inflate(R.layout.actions_fragment, container, false);
|
||||
|
||||
profileSwitch = (Button) view.findViewById(R.id.actions_profileswitch);
|
||||
tempTarget = (Button) view.findViewById(R.id.actions_temptarget);
|
||||
extendedBolus = (Button) view.findViewById(R.id.actions_extendedbolus);
|
||||
tempBasal = (Button) view.findViewById(R.id.actions_settempbasal);
|
||||
fill = (Button) view.findViewById(R.id.actions_fill);
|
||||
|
||||
profileSwitch.setOnClickListener(this);
|
||||
tempTarget.setOnClickListener(this);
|
||||
extendedBolus.setOnClickListener(this);
|
||||
tempBasal.setOnClickListener(this);
|
||||
fill.setOnClickListener(this);
|
||||
|
@ -90,22 +94,26 @@ public class ActionsFragment extends Fragment implements FragmentBase, View.OnCl
|
|||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!MainApp.getConfigBuilder().getPumpDescription().isSetBasalProfileCapable || !MainApp.getConfigBuilder().isInitialized())
|
||||
if (!MainApp.getConfigBuilder().getPumpDescription().isSetBasalProfileCapable || !MainApp.getConfigBuilder().isInitialized() || MainApp.getConfigBuilder().isSuspended())
|
||||
profileSwitch.setVisibility(View.GONE);
|
||||
else
|
||||
profileSwitch.setVisibility(View.VISIBLE);
|
||||
if (!MainApp.getConfigBuilder().getPumpDescription().isExtendedBolusCapable || !MainApp.getConfigBuilder().isInitialized())
|
||||
if (!MainApp.getConfigBuilder().getPumpDescription().isExtendedBolusCapable || !MainApp.getConfigBuilder().isInitialized() || MainApp.getConfigBuilder().isSuspended())
|
||||
extendedBolus.setVisibility(View.GONE);
|
||||
else
|
||||
extendedBolus.setVisibility(View.VISIBLE);
|
||||
if (!MainApp.getConfigBuilder().getPumpDescription().isTempBasalCapable || !MainApp.getConfigBuilder().isInitialized())
|
||||
if (!MainApp.getConfigBuilder().getPumpDescription().isTempBasalCapable || !MainApp.getConfigBuilder().isInitialized() || MainApp.getConfigBuilder().isSuspended())
|
||||
tempBasal.setVisibility(View.GONE);
|
||||
else
|
||||
tempBasal.setVisibility(View.VISIBLE);
|
||||
if (!MainApp.getConfigBuilder().getPumpDescription().isRefillingCapable || !MainApp.getConfigBuilder().isInitialized())
|
||||
if (!MainApp.getConfigBuilder().getPumpDescription().isRefillingCapable || !MainApp.getConfigBuilder().isInitialized() || MainApp.getConfigBuilder().isSuspended())
|
||||
fill.setVisibility(View.GONE);
|
||||
else
|
||||
fill.setVisibility(View.VISIBLE);
|
||||
if (!Config.APS)
|
||||
tempTarget.setVisibility(View.GONE);
|
||||
else
|
||||
tempTarget.setVisibility(View.VISIBLE);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -117,11 +125,18 @@ public class ActionsFragment extends Fragment implements FragmentBase, View.OnCl
|
|||
switch (view.getId()) {
|
||||
case R.id.actions_profileswitch:
|
||||
NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog();
|
||||
final OptionsToShow profileswitch = new OptionsToShow(R.id.careportal_profileswitch, R.string.careportal_profileswitch, true, false, false, false, false, false, false, true, false);
|
||||
final OptionsToShow profileswitch = new OptionsToShow(R.id.careportal_profileswitch, R.string.careportal_profileswitch, true, false, false, false, false, false, false, true, false, false);
|
||||
profileswitch.executeProfileSwitch = true;
|
||||
newDialog.setOptions(profileswitch);
|
||||
newDialog.show(manager, "NewNSTreatmentDialog");
|
||||
break;
|
||||
case R.id.actions_temptarget:
|
||||
NewNSTreatmentDialog newTTDialog = new NewNSTreatmentDialog();
|
||||
final OptionsToShow temptarget = new OptionsToShow(R.id.careportal_temporarytarget, R.string.careportal_temporarytarget, false, false, false, false, true, false, false, false, false, true);
|
||||
temptarget.executeTempTarget = true;
|
||||
newTTDialog.setOptions(temptarget);
|
||||
newTTDialog.show(manager, "NewNSTreatmentDialog");
|
||||
break;
|
||||
case R.id.actions_extendedbolus:
|
||||
NewExtendedBolusDialog newExtendedDialog = new NewExtendedBolusDialog();
|
||||
newExtendedDialog.show(manager, "NewExtendedDialog");
|
||||
|
|
|
@ -28,6 +28,17 @@ public class ActionsPlugin implements PluginBase {
|
|||
return MainApp.sResources.getString(R.string.actions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNameShort() {
|
||||
String name = MainApp.sResources.getString(R.string.actions_shortname);
|
||||
if (!name.trim().isEmpty()){
|
||||
//only if translation exists
|
||||
return name;
|
||||
}
|
||||
// use long name as fallback
|
||||
return getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(int type) {
|
||||
return type == GENERAL && fragmentEnabled;
|
||||
|
|
|
@ -151,7 +151,7 @@ public class NewTempBasalDialog extends DialogFragment implements View.OnClickLi
|
|||
}
|
||||
if (!result.success) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||
builder.setTitle(MainApp.sResources.getString(R.string.treatmentdeliveryerror));
|
||||
builder.setTitle(MainApp.sResources.getString(R.string.tempbasaldeliveryerror));
|
||||
builder.setMessage(result.comment);
|
||||
builder.setPositiveButton(MainApp.sResources.getString(R.string.ok), null);
|
||||
builder.show();
|
||||
|
|
|
@ -8,10 +8,8 @@ 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 {
|
||||
|
@ -25,25 +23,26 @@ public class CareportalFragment extends Fragment implements FragmentBase, View.O
|
|||
return careportalPlugin;
|
||||
}
|
||||
|
||||
// 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);
|
||||
// bg,insulin,carbs,prebolus,duration,percent,absolute,profile,split,temptarget
|
||||
final OptionsToShow bgcheck = new OptionsToShow(R.id.careportal_bgcheck, R.string.careportal_bgcheck, true, true, true, false, 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, false);
|
||||
final OptionsToShow mealbolus = new OptionsToShow(R.id.careportal_mealbolus, R.string.careportal_mealbolus, true, true, true, true, false, 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, false);
|
||||
final OptionsToShow carbcorrection = new OptionsToShow(R.id.careportal_carbscorrection, R.string.careportal_carbscorrection, true, false, true, false, 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, false);
|
||||
final OptionsToShow announcement = new OptionsToShow(R.id.careportal_announcement, R.string.careportal_announcement, true, false, 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, false);
|
||||
final OptionsToShow question = new OptionsToShow(R.id.careportal_question, R.string.careportal_question, true, false, 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, false);
|
||||
final OptionsToShow sitechange = new OptionsToShow(R.id.careportal_pumpsitechange, R.string.careportal_pumpsitechange, true, true, false, 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, false);
|
||||
final OptionsToShow sensorchange = new OptionsToShow(R.id.careportal_cgmsensorinsert, R.string.careportal_cgmsensorinsert, true, false, 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, false);
|
||||
final OptionsToShow tempbasalstart = new OptionsToShow(R.id.careportal_tempbasalstart, R.string.careportal_tempbasalstart, true, false, false, false, true, true, true, false, false, false);
|
||||
final OptionsToShow tempbasalend = new OptionsToShow(R.id.careportal_tempbasalend, R.string.careportal_tempbasalend, true, false, 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, false);
|
||||
final OptionsToShow openapsoffline = new OptionsToShow(R.id.careportal_openapsoffline, R.string.careportal_openapsoffline, false, false, false, false, true, false, false, false, false, false);
|
||||
final OptionsToShow temptarget = new OptionsToShow(R.id.careportal_temporarytarget, R.string.careportal_temporarytarget, false, false, false, false, true, false, false, false, false, true);
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
|
@ -68,6 +67,7 @@ public class CareportalFragment extends Fragment implements FragmentBase, View.O
|
|||
view.findViewById(R.id.careportal_tempbasalend).setOnClickListener(this);
|
||||
view.findViewById(R.id.careportal_tempbasalstart).setOnClickListener(this);
|
||||
view.findViewById(R.id.careportal_openapsoffline).setOnClickListener(this);
|
||||
view.findViewById(R.id.careportal_temporarytarget).setOnClickListener(this);
|
||||
return view;
|
||||
}
|
||||
|
||||
|
@ -130,6 +130,9 @@ public class CareportalFragment extends Fragment implements FragmentBase, View.O
|
|||
case R.id.careportal_openapsoffline:
|
||||
newDialog.setOptions(openapsoffline);
|
||||
break;
|
||||
case R.id.careportal_temporarytarget:
|
||||
newDialog.setOptions(temptarget);
|
||||
break;
|
||||
default:
|
||||
newDialog = null;
|
||||
}
|
||||
|
|
|
@ -24,6 +24,17 @@ public class CareportalPlugin implements PluginBase {
|
|||
return MainApp.sResources.getString(R.string.careportal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNameShort() {
|
||||
String name = MainApp.sResources.getString(R.string.careportal_shortname);
|
||||
if (!name.trim().isEmpty()){
|
||||
//only if translation exists
|
||||
return name;
|
||||
}
|
||||
// use long name as fallback
|
||||
return getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(int type) {
|
||||
return type == GENERAL && fragmentEnabled;
|
||||
|
|
|
@ -13,17 +13,20 @@ import android.support.v4.app.FragmentActivity;
|
|||
import android.support.v7.app.AlertDialog;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.text.format.DateFormat;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.Button;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.EditText;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.RadioButton;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.j256.ormlite.dao.Dao;
|
||||
import com.wdullaer.materialdatetimepicker.date.DatePickerDialog;
|
||||
import com.wdullaer.materialdatetimepicker.time.RadialPickerLayout;
|
||||
import com.wdullaer.materialdatetimepicker.time.TimePickerDialog;
|
||||
|
@ -33,6 +36,7 @@ import org.json.JSONObject;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
|
@ -42,10 +46,14 @@ import java.util.Date;
|
|||
import info.nightscout.androidaps.Constants;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.data.GlucoseStatus;
|
||||
import info.nightscout.androidaps.db.TempTarget;
|
||||
import info.nightscout.androidaps.events.EventNewBasalProfile;
|
||||
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||
import info.nightscout.androidaps.plugins.Careportal.OptionsToShow;
|
||||
import info.nightscout.androidaps.plugins.CircadianPercentageProfile.CircadianPercentageProfilePlugin;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.TempTargetRange.events.EventTempTargetRangeChange;
|
||||
import info.nightscout.client.data.NSProfile;
|
||||
import info.nightscout.utils.DateUtil;
|
||||
import info.nightscout.utils.PlusMinusEditText;
|
||||
|
@ -73,6 +81,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
|
|||
LinearLayout layoutAbsolute;
|
||||
LinearLayout layoutCarbTime;
|
||||
LinearLayout layoutProfile;
|
||||
LinearLayout layoutTempTarget;
|
||||
Button dateButton;
|
||||
Button timeButton;
|
||||
Button okButton;
|
||||
|
@ -91,6 +100,9 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
|
|||
EditText carbTimeEdit;
|
||||
EditText splitEdit;
|
||||
Spinner profileSpinner;
|
||||
EditText low;
|
||||
EditText high;
|
||||
Spinner reasonSpinner;
|
||||
|
||||
PlusMinusEditText editBg;
|
||||
PlusMinusEditText editCarbs;
|
||||
|
@ -142,6 +154,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
|
|||
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);
|
||||
layoutTempTarget = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_temptarget_layout);
|
||||
|
||||
bgUnitsView = (TextView) view.findViewById(R.id.careportal_newnstreatment_bgunits);
|
||||
meterRadioButton = (RadioButton) view.findViewById(R.id.careportal_newnstreatment_meter);
|
||||
|
@ -193,6 +206,10 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
|
|||
notesEdit = (EditText) view.findViewById(R.id.careportal_newnstreatment_notes);
|
||||
splitEdit = (EditText) view.findViewById(R.id.careportal_newnstreatment_splitinput);
|
||||
|
||||
reasonSpinner = (Spinner) view.findViewById(R.id.careportal_newnstreatment_temptarget_reason);
|
||||
low = (EditText) view.findViewById(R.id.careportal_temptarget_low);
|
||||
high = (EditText) view.findViewById(R.id.careportal_temptarget_high);
|
||||
|
||||
eventTime = new Date();
|
||||
dateButton = (Button) view.findViewById(R.id.careportal_newnstreatment_eventdate);
|
||||
timeButton = (Button) view.findViewById(R.id.careportal_newnstreatment_eventtime);
|
||||
|
@ -204,7 +221,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
|
|||
okButton = (Button) view.findViewById(R.id.careportal_newnstreatment_ok);
|
||||
okButton.setOnClickListener(this);
|
||||
|
||||
// BG
|
||||
// profile
|
||||
profile = MainApp.getConfigBuilder().getActiveProfile().getProfile();
|
||||
ArrayList<CharSequence> profileList;
|
||||
units = Constants.MGDL;
|
||||
|
@ -227,6 +244,17 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
|
|||
}
|
||||
}
|
||||
|
||||
// temp target
|
||||
ArrayList<CharSequence> reasonList = new ArrayList<CharSequence>();
|
||||
reasonList.add(MainApp.sResources.getString(R.string.eatingsoon));
|
||||
reasonList.add(MainApp.sResources.getString(R.string.activity));
|
||||
reasonList.add(MainApp.sResources.getString(R.string.manual));
|
||||
ArrayAdapter<CharSequence> adapterReason = new ArrayAdapter<CharSequence>(getContext(),
|
||||
android.R.layout.simple_spinner_item, reasonList);
|
||||
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
reasonSpinner.setAdapter(adapterReason);
|
||||
|
||||
// bg
|
||||
bgUnitsView.setText(units);
|
||||
|
||||
// Set BG if not old
|
||||
|
@ -239,10 +267,32 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
|
|||
// 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);
|
||||
Double bg = NSProfile.fromMgdlToUnits(GlucoseStatus.getGlucoseStatusData() != null ? GlucoseStatus.getGlucoseStatusData().glucose : 0d, profile != null ? profile.getUnits() : Constants.MGDL);
|
||||
if (profile == null)
|
||||
editBg = new PlusMinusEditText(view, R.id.careportal_newnstreatment_bginput, R.id.careportal_newnstreatment_bg_plus, R.id.careportal_newnstreatment_bg_minus, bg, 0d, 500d, 0.1d, new DecimalFormat("0.0"), false);
|
||||
else if (profile.getUnits().equals(Constants.MMOL))
|
||||
editBg = new PlusMinusEditText(view, R.id.careportal_newnstreatment_bginput, R.id.careportal_newnstreatment_bg_plus, R.id.careportal_newnstreatment_bg_minus, bg, 0d, 30d, 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);
|
||||
editBg = new PlusMinusEditText(view, R.id.careportal_newnstreatment_bginput, R.id.careportal_newnstreatment_bg_plus, R.id.careportal_newnstreatment_bg_minus, bg, 0d, 500d, 1d, new DecimalFormat("0"), false);
|
||||
bgInputEdit.addTextChangedListener(new TextWatcher() {
|
||||
|
||||
public void afterTextChanged(Editable s) {}
|
||||
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
||||
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
if (sensorRadioButton.isChecked()) meterRadioButton.setChecked(true);
|
||||
}
|
||||
});
|
||||
sensorRadioButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||
NSProfile profile = ConfigBuilderPlugin.getActiveProfile().getProfile();
|
||||
if (profile == null) return;
|
||||
Double bg = NSProfile.fromMgdlToUnits(GlucoseStatus.getGlucoseStatusData() != null ? GlucoseStatus.getGlucoseStatusData().glucose : 0d, profile.getUnits());
|
||||
editBg.setValue(bg);
|
||||
}
|
||||
});
|
||||
|
||||
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);
|
||||
|
@ -271,6 +321,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
|
|||
showOrHide(layoutAbsolute, options.absolute);
|
||||
showOrHide(layoutCarbTime, options.prebolus);
|
||||
showOrHide(layoutProfile, options.profile);
|
||||
showOrHide(layoutTempTarget, options.tempTarget);
|
||||
|
||||
return view;
|
||||
}
|
||||
|
@ -304,7 +355,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
|
|||
this,
|
||||
calendar.get(Calendar.HOUR_OF_DAY),
|
||||
calendar.get(Calendar.MINUTE),
|
||||
df.is24HourFormat(context)
|
||||
DateFormat.is24HourFormat(context)
|
||||
);
|
||||
tpd.setThemeDark(true);
|
||||
tpd.dismissOnPause(true);
|
||||
|
@ -344,6 +395,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
|
|||
String enteredBy = SP.getString("careportal_enteredby", "");
|
||||
JSONObject data = new JSONObject();
|
||||
try {
|
||||
boolean allowZeroDuration = false;
|
||||
data.put("created_at", DateUtil.toISOString(eventTime));
|
||||
switch (options.eventType) {
|
||||
case R.id.careportal_bgcheck:
|
||||
|
@ -403,6 +455,16 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
|
|||
case R.id.careportal_openapsoffline:
|
||||
data.put("eventType", "OpenAPS Offline");
|
||||
break;
|
||||
case R.id.careportal_temporarytarget:
|
||||
data.put("eventType", "Temporary Target");
|
||||
if (!reasonSpinner.getSelectedItem().toString().equals(""))
|
||||
data.put("reason", reasonSpinner.getSelectedItem().toString());
|
||||
if (SafeParse.stringToDouble(low.getText().toString()) != 0d)
|
||||
data.put("targetBottom", SafeParse.stringToDouble(low.getText().toString()));
|
||||
if (SafeParse.stringToDouble(high.getText().toString()) != 0d)
|
||||
data.put("targetTop", SafeParse.stringToDouble(high.getText().toString()));
|
||||
allowZeroDuration = true;
|
||||
break;
|
||||
}
|
||||
if (SafeParse.stringToDouble(bgInputEdit.getText().toString()) != 0d) {
|
||||
data.put("glucose", SafeParse.stringToDouble(bgInputEdit.getText().toString()));
|
||||
|
@ -414,7 +476,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
|
|||
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)
|
||||
if (allowZeroDuration || 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()));
|
||||
|
@ -509,6 +571,14 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
|
|||
ret += data.get("profile");
|
||||
ret += "\n";
|
||||
}
|
||||
if (data.has("targetBottom") && data.has("targetTop")) {
|
||||
ret += getString(R.string.target_range);
|
||||
ret += " ";
|
||||
ret += data.get("targetBottom");
|
||||
ret += " - ";
|
||||
ret += data.get("targetTop");
|
||||
ret += "\n";
|
||||
}
|
||||
if (data.has("created_at")) {
|
||||
ret += getString(R.string.careportal_newnstreatment_eventtime_label);
|
||||
ret += ": ";
|
||||
|
@ -543,7 +613,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
|
|||
public void run() {
|
||||
try {
|
||||
String profile = data.getString("profile");
|
||||
NSProfile nsProfile = MainApp.getConfigBuilder().getActiveProfile().getProfile();
|
||||
NSProfile nsProfile = ConfigBuilderPlugin.getActiveProfile().getProfile();
|
||||
nsProfile.setActiveProfile(profile);
|
||||
PumpInterface pump = MainApp.getConfigBuilder();
|
||||
if (pump != null) {
|
||||
|
@ -553,6 +623,12 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
|
|||
} else {
|
||||
log.error("No active pump selected");
|
||||
}
|
||||
if (ConfigBuilderPlugin.getActiveProfile() instanceof CircadianPercentageProfilePlugin) {
|
||||
CircadianPercentageProfilePlugin cpp = (CircadianPercentageProfilePlugin) ConfigBuilderPlugin.getActiveProfile();
|
||||
data.put("CircadianPercentageProfile", true);
|
||||
data.put("timeshift", cpp.timeshift);
|
||||
data.put("percentage", cpp.percentage);
|
||||
}
|
||||
ConfigBuilderPlugin.uploadCareportalEntryToNS(data);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
|
@ -560,6 +636,39 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
|
|||
}
|
||||
});
|
||||
}
|
||||
} else if (options.executeTempTarget) {
|
||||
try {
|
||||
if ((data.has("targetBottom") && data.has("targetTop")) || (data.has("duration")&& data.getInt("duration") == 0)) {
|
||||
sHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
TempTarget tempTarget = new TempTarget();
|
||||
tempTarget.timeStart = eventTime;
|
||||
tempTarget.duration = data.getInt("duration");
|
||||
tempTarget.reason = data.getString("reason");
|
||||
if(tempTarget.duration != 0) {
|
||||
tempTarget.low = NSProfile.toMgdl(data.getDouble("targetBottom"), ConfigBuilderPlugin.getActiveProfile().getProfile().getUnits());
|
||||
tempTarget.high = NSProfile.toMgdl(data.getDouble("targetTop"), ConfigBuilderPlugin.getActiveProfile().getProfile().getUnits());
|
||||
} else {
|
||||
tempTarget.low = 0;
|
||||
tempTarget.high = 0;
|
||||
}
|
||||
tempTarget.setTimeIndex(tempTarget.getTimeIndex());
|
||||
Dao<TempTarget, Long> dao = MainApp.getDbHelper().getDaoTempTargets();
|
||||
log.debug("Creating new TempTarget db record: " + tempTarget.log());
|
||||
dao.createIfNotExists(tempTarget);
|
||||
MainApp.bus().post(new EventTempTargetRangeChange());
|
||||
ConfigBuilderPlugin.uploadCareportalEntryToNS(data);
|
||||
} catch (JSONException | SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
ConfigBuilderPlugin.uploadCareportalEntryToNS(data);
|
||||
}
|
||||
|
|
|
@ -16,9 +16,11 @@ public class OptionsToShow {
|
|||
public boolean absolute;
|
||||
public boolean profile;
|
||||
public boolean split;
|
||||
public boolean tempTarget;
|
||||
|
||||
// perform direct actions
|
||||
public boolean executeProfileSwitch = false;
|
||||
public boolean executeTempTarget = false;
|
||||
|
||||
public OptionsToShow(int eventType,
|
||||
int eventName,
|
||||
|
@ -30,7 +32,8 @@ public class OptionsToShow {
|
|||
boolean percent,
|
||||
boolean absolute,
|
||||
boolean profile,
|
||||
boolean split) {
|
||||
boolean split,
|
||||
boolean tempTarget) {
|
||||
this.eventType = eventType;
|
||||
this.eventName = eventName;
|
||||
this.bg = bg;
|
||||
|
@ -42,5 +45,6 @@ public class OptionsToShow {
|
|||
this.absolute = absolute;
|
||||
this.profile = profile;
|
||||
this.split = split;
|
||||
this.tempTarget = tempTarget;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,22 +4,27 @@ package info.nightscout.androidaps.plugins.CircadianPercentageProfile;
|
|||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.text.Editable;
|
||||
import android.text.Html;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.Gravity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.RadioButton;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.andreabaccega.widget.FormEditText;
|
||||
import com.squareup.otto.Subscribe;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
|
@ -34,25 +39,24 @@ import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialo
|
|||
import info.nightscout.androidaps.plugins.Careportal.OptionsToShow;
|
||||
import info.nightscout.utils.DecimalFormatter;
|
||||
import info.nightscout.utils.SafeParse;
|
||||
import info.nightscout.utils.ToastUtils;
|
||||
|
||||
public class CircadianPercentageProfileFragment extends Fragment implements FragmentBase {
|
||||
private static Logger log = LoggerFactory.getLogger(CircadianPercentageProfileFragment.class);
|
||||
|
||||
private static CircadianPercentageProfilePlugin circadianPercentageProfilePlugin = new CircadianPercentageProfilePlugin();
|
||||
private Object snackbarCaller;
|
||||
|
||||
public static CircadianPercentageProfilePlugin getPlugin() {
|
||||
return circadianPercentageProfilePlugin;
|
||||
}
|
||||
|
||||
EditText diaView;
|
||||
FormEditText diaView;
|
||||
RadioButton mgdlView;
|
||||
RadioButton mmolView;
|
||||
EditText carView;
|
||||
EditText targetlowView;
|
||||
EditText targethighView;
|
||||
EditText percentageView;
|
||||
EditText timeshiftView;
|
||||
FormEditText targetlowView;
|
||||
FormEditText targethighView;
|
||||
FormEditText percentageView;
|
||||
FormEditText timeshiftView;
|
||||
TextView profileView;
|
||||
TextView baseprofileIC;
|
||||
TextView baseprofileBasal;
|
||||
|
@ -65,20 +69,25 @@ public class CircadianPercentageProfileFragment extends Fragment implements Frag
|
|||
ImageView iceditIcon;
|
||||
ImageView isfeditIcon;
|
||||
BasalEditDialog basalEditDialog;
|
||||
FrameLayout fl;
|
||||
Snackbar mSnackBar;
|
||||
|
||||
static Boolean percentageViewHint = true;
|
||||
static Boolean timeshiftViewHint = true;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
View layout = inflater.inflate(R.layout.circadianpercentageprofile_fragment, container, false);
|
||||
diaView = (EditText) layout.findViewById(R.id.circadianpercentageprofile_dia);
|
||||
fl = (FrameLayout) layout.findViewById(R.id.circadianpercentageprofile_framelayout);
|
||||
fl.requestFocusFromTouch();
|
||||
diaView = (FormEditText) layout.findViewById(R.id.circadianpercentageprofile_dia);
|
||||
mgdlView = (RadioButton) layout.findViewById(R.id.circadianpercentageprofile_mgdl);
|
||||
mmolView = (RadioButton) layout.findViewById(R.id.circadianpercentageprofile_mmol);
|
||||
carView = (EditText) layout.findViewById(R.id.circadianpercentageprofile_car);
|
||||
targetlowView = (EditText) layout.findViewById(R.id.circadianpercentageprofile_targetlow);
|
||||
targethighView = (EditText) layout.findViewById(R.id.circadianpercentageprofile_targethigh);
|
||||
percentageView = (EditText) layout.findViewById(R.id.circadianpercentageprofile_percentage);
|
||||
timeshiftView = (EditText) layout.findViewById(R.id.circadianpercentageprofile_timeshift);
|
||||
targetlowView = (FormEditText) layout.findViewById(R.id.circadianpercentageprofile_targetlow);
|
||||
targethighView = (FormEditText) layout.findViewById(R.id.circadianpercentageprofile_targethigh);
|
||||
percentageView = (FormEditText) layout.findViewById(R.id.circadianpercentageprofile_percentage);
|
||||
timeshiftView = (FormEditText) layout.findViewById(R.id.circadianpercentageprofile_timeshift);
|
||||
profileView = (TextView) layout.findViewById(R.id.circadianpercentageprofile_profileview);
|
||||
baseprofileBasal = (TextView) layout.findViewById(R.id.circadianpercentageprofile_baseprofilebasal);
|
||||
baseprofileBasalLayout = (LinearLayout) layout.findViewById(R.id.circadianpercentageprofile_baseprofilebasal_layout);
|
||||
|
@ -101,7 +110,6 @@ public class CircadianPercentageProfileFragment extends Fragment implements Frag
|
|||
mgdlView.setChecked(circadianPercentageProfilePlugin.mgdl);
|
||||
mmolView.setChecked(circadianPercentageProfilePlugin.mmol);
|
||||
diaView.setText(circadianPercentageProfilePlugin.dia.toString());
|
||||
carView.setText(circadianPercentageProfilePlugin.car.toString());
|
||||
targetlowView.setText(circadianPercentageProfilePlugin.targetLow.toString());
|
||||
targethighView.setText(circadianPercentageProfilePlugin.targetHigh.toString());
|
||||
percentageView.setText("" + circadianPercentageProfilePlugin.percentage);
|
||||
|
@ -133,30 +141,13 @@ public class CircadianPercentageProfileFragment extends Fragment implements Frag
|
|||
@Override
|
||||
public void onClick(View view) {
|
||||
NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog();
|
||||
final OptionsToShow profileswitch = new OptionsToShow(R.id.careportal_profileswitch, R.string.careportal_profileswitch, true, false, false, false, false, false, false, true, false);
|
||||
final OptionsToShow profileswitch = new OptionsToShow(R.id.careportal_profileswitch, R.string.careportal_profileswitch, true, false, false, false, false, false, false, true, false, false);
|
||||
profileswitch.executeProfileSwitch = true;
|
||||
newDialog.setOptions(profileswitch);
|
||||
newDialog.show(getFragmentManager(), "NewNSTreatmentDialog");
|
||||
}
|
||||
});
|
||||
|
||||
timeshiftView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
|
||||
@Override
|
||||
public void onFocusChange(View view, boolean b) {
|
||||
if (b)
|
||||
ToastUtils.showToastInUiThread(getContext(), getString(R.string.timeshift_hint));
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
percentageView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
|
||||
@Override
|
||||
public void onFocusChange(View view, boolean b) {
|
||||
if (b)
|
||||
ToastUtils.showToastInUiThread(getContext(), getString(R.string.percentagefactor_hint));
|
||||
}
|
||||
});
|
||||
|
||||
timeIcon.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
|
@ -204,6 +195,76 @@ public class CircadianPercentageProfileFragment extends Fragment implements Frag
|
|||
}
|
||||
});
|
||||
|
||||
timeshiftView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
|
||||
|
||||
@Override
|
||||
public void onFocusChange(View view, boolean hasFocus) {
|
||||
if (!hasFocus) {
|
||||
if(mSnackBar!=null && snackbarCaller == timeshiftView){
|
||||
mSnackBar.dismiss();
|
||||
}
|
||||
timeshiftView.clearFocus();
|
||||
fl.requestFocusFromTouch();
|
||||
}
|
||||
else {
|
||||
if (timeshiftViewHint) {
|
||||
customSnackbar(view, getString(R.string.timeshift_hint), timeshiftView);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
percentageView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
|
||||
|
||||
@Override
|
||||
public void onFocusChange(View view, boolean hasFocus) {
|
||||
if (!hasFocus) {
|
||||
if(mSnackBar!=null && snackbarCaller == percentageView){
|
||||
mSnackBar.dismiss();
|
||||
}
|
||||
percentageView.clearFocus();
|
||||
fl.requestFocusFromTouch();
|
||||
}
|
||||
else {
|
||||
if (percentageViewHint) {
|
||||
customSnackbar(view, getString(R.string.percentagefactor_hint), percentageView);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
diaView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
|
||||
|
||||
@Override
|
||||
public void onFocusChange(View view, boolean hasFocus) {
|
||||
if (!hasFocus) {
|
||||
diaView.clearFocus();
|
||||
fl.requestFocusFromTouch();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
targethighView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
|
||||
|
||||
@Override
|
||||
public void onFocusChange(View view, boolean hasFocus) {
|
||||
if (!hasFocus) {
|
||||
targethighView.clearFocus();
|
||||
fl.requestFocusFromTouch();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
targetlowView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
|
||||
|
||||
@Override
|
||||
public void onFocusChange(View view, boolean hasFocus) {
|
||||
if (!hasFocus) {
|
||||
targetlowView.clearFocus();
|
||||
fl.requestFocusFromTouch();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
TextWatcher textWatch = new TextWatcher() {
|
||||
|
||||
|
@ -220,23 +281,36 @@ public class CircadianPercentageProfileFragment extends Fragment implements Frag
|
|||
public void onTextChanged(CharSequence s, int start,
|
||||
int before, int count) {
|
||||
|
||||
if (SafeParse.stringToInt(percentageView.getText().toString()) == 0) {
|
||||
circadianPercentageProfilePlugin.percentage = 100;
|
||||
} else {
|
||||
circadianPercentageProfilePlugin.percentage = SafeParse.stringToInt(percentageView.getText().toString());
|
||||
if (percentageView.testValidity()) {
|
||||
if (SafeParse.stringToInt(percentageView.getText().toString()) == 0) {
|
||||
circadianPercentageProfilePlugin.percentage = 100;
|
||||
} else {
|
||||
circadianPercentageProfilePlugin.percentage = SafeParse.stringToInt(percentageView.getText().toString());
|
||||
}
|
||||
updateProfileInfo();
|
||||
}
|
||||
if (timeshiftView.testValidity()) {
|
||||
circadianPercentageProfilePlugin.timeshift = SafeParse.stringToInt(timeshiftView.getText().toString());
|
||||
updateProfileInfo();
|
||||
}
|
||||
if (diaView.testValidity()) {
|
||||
circadianPercentageProfilePlugin.dia = SafeParse.stringToDouble(diaView.getText().toString());
|
||||
updateProfileInfo();
|
||||
}
|
||||
if (targethighView.testValidity()) {
|
||||
circadianPercentageProfilePlugin.targetLow = SafeParse.stringToDouble(targetlowView.getText().toString());
|
||||
updateProfileInfo();
|
||||
}
|
||||
if (targetlowView.testValidity()) {
|
||||
circadianPercentageProfilePlugin.targetHigh = SafeParse.stringToDouble(targethighView.getText().toString());
|
||||
updateProfileInfo();
|
||||
}
|
||||
circadianPercentageProfilePlugin.dia = SafeParse.stringToDouble(diaView.getText().toString());
|
||||
circadianPercentageProfilePlugin.car = SafeParse.stringToDouble(carView.getText().toString());
|
||||
circadianPercentageProfilePlugin.targetLow = SafeParse.stringToDouble(targetlowView.getText().toString());
|
||||
circadianPercentageProfilePlugin.targetHigh = SafeParse.stringToDouble(targethighView.getText().toString());
|
||||
circadianPercentageProfilePlugin.timeshift = SafeParse.stringToInt(timeshiftView.getText().toString());
|
||||
circadianPercentageProfilePlugin.storeSettings();
|
||||
updateProfileInfo();
|
||||
}
|
||||
};
|
||||
|
||||
diaView.addTextChangedListener(textWatch);
|
||||
carView.addTextChangedListener(textWatch);
|
||||
targetlowView.addTextChangedListener(textWatch);
|
||||
targethighView.addTextChangedListener(textWatch);
|
||||
percentageView.addTextChangedListener(textWatch);
|
||||
|
@ -247,6 +321,35 @@ public class CircadianPercentageProfileFragment extends Fragment implements Frag
|
|||
return layout;
|
||||
}
|
||||
|
||||
private void customSnackbar(View view, final String Msg, Object snackbarCaller) {
|
||||
if(mSnackBar!= null) mSnackBar.dismiss();
|
||||
|
||||
this.snackbarCaller = snackbarCaller;
|
||||
if (timeshiftViewHint || percentageViewHint) {
|
||||
//noinspection WrongConstant
|
||||
mSnackBar = Snackbar.make(view, Msg, 7000)
|
||||
.setActionTextColor(ContextCompat.getColor(MainApp.instance(), R.color.notificationInfo))
|
||||
.setAction(getString(R.string.dont_show_again), new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (Msg.equals(getString(R.string.percentagefactor_hint))) {
|
||||
percentageViewHint = false;
|
||||
} else if (Msg.equals(getString(R.string.timeshift_hint))) {
|
||||
timeshiftViewHint = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
view = mSnackBar.getView();
|
||||
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) view.getLayoutParams();
|
||||
params.gravity = Gravity.CENTER_HORIZONTAL | Gravity.TOP;
|
||||
view.setLayoutParams(params);
|
||||
view.setBackgroundColor(ContextCompat.getColor(MainApp.instance(), R.color.cardview_dark_background));
|
||||
TextView mainTextView = (TextView) (view).findViewById(android.support.design.R.id.snackbar_text);
|
||||
mainTextView.setTextColor(ContextCompat.getColor(MainApp.instance(), R.color.mdtp_white));
|
||||
mSnackBar.show();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateProfileInfo() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("<h3>");
|
||||
|
@ -279,6 +382,7 @@ public class CircadianPercentageProfileFragment extends Fragment implements Frag
|
|||
basalEditDialog.dismiss();
|
||||
}
|
||||
basalEditDialog = null;
|
||||
fl.requestFocusFromTouch();
|
||||
}
|
||||
|
||||
public static class BasalEditDialog extends DialogFragment {
|
||||
|
@ -359,6 +463,7 @@ public class CircadianPercentageProfileFragment extends Fragment implements Frag
|
|||
basalEditDialog = null;
|
||||
|
||||
MainApp.bus().unregister(this);
|
||||
fl.requestFocusFromTouch();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -366,6 +471,7 @@ public class CircadianPercentageProfileFragment extends Fragment implements Frag
|
|||
super.onResume();
|
||||
MainApp.bus().register(this);
|
||||
onStatusEvent(null);
|
||||
fl.requestFocusFromTouch();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
|
@ -375,7 +481,7 @@ public class CircadianPercentageProfileFragment extends Fragment implements Frag
|
|||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!MainApp.getConfigBuilder().isInitialized() || !MainApp.getConfigBuilder().getPumpDescription().isSetBasalProfileCapable) {
|
||||
if (!MainApp.getConfigBuilder().isInitialized() || MainApp.getConfigBuilder().isSuspended() || !MainApp.getConfigBuilder().getPumpDescription().isSetBasalProfileCapable) {
|
||||
profileswitchButton.setVisibility(View.GONE);
|
||||
} else {
|
||||
profileswitchButton.setVisibility(View.VISIBLE);
|
||||
|
|
|
@ -15,7 +15,6 @@ import info.nightscout.androidaps.MainApp;
|
|||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||
import info.nightscout.androidaps.interfaces.ProfileInterface;
|
||||
import info.nightscout.androidaps.plugins.OpenAPSMA.OpenAPSMAPlugin;
|
||||
import info.nightscout.client.data.NSProfile;
|
||||
import info.nightscout.utils.DecimalFormatter;
|
||||
import info.nightscout.utils.SafeParse;
|
||||
|
@ -27,8 +26,6 @@ import info.nightscout.utils.ToastUtils;
|
|||
*/
|
||||
public class CircadianPercentageProfilePlugin implements PluginBase, ProfileInterface {
|
||||
public static final String SETTINGS_PREFIX = "CircadianPercentageProfile";
|
||||
public static final int MIN_PERCENTAGE = 50;
|
||||
public static final int MAX_PERCENTAGE = 200;
|
||||
private static Logger log = LoggerFactory.getLogger(CircadianPercentageProfilePlugin.class);
|
||||
|
||||
private static boolean fragmentEnabled = true;
|
||||
|
@ -39,11 +36,10 @@ public class CircadianPercentageProfilePlugin implements PluginBase, ProfileInte
|
|||
boolean mgdl;
|
||||
boolean mmol;
|
||||
Double dia;
|
||||
Double car;
|
||||
Double targetLow;
|
||||
Double targetHigh;
|
||||
int percentage;
|
||||
int timeshift;
|
||||
public int percentage;
|
||||
public int timeshift;
|
||||
double[] basebasal = new double[]{1d, 1d, 1d, 1d, 1d, 1d, 1d, 1d, 1d, 1d, 1d, 1d, 1d, 1d, 1d, 1d, 1d, 1d, 1d, 1d, 1d, 1d, 1d, 1d};
|
||||
double[] baseisf = new double[]{35d, 35d, 35d, 35d, 35d, 35d, 35d, 35d, 35d, 35d, 35d, 35d, 35d, 35d, 35d, 35d, 35d, 35d, 35d, 35d, 35d, 35d, 35d, 35d};
|
||||
double[] baseic = new double[]{4d, 4d, 4d, 4d, 4d, 4d, 4d, 4d, 4d, 4d, 4d, 4d, 4d, 4d, 4d, 4d, 4d, 4d, 4d, 4d, 4d, 4d, 4d, 4d};
|
||||
|
@ -67,6 +63,17 @@ public class CircadianPercentageProfilePlugin implements PluginBase, ProfileInte
|
|||
return MainApp.instance().getString(R.string.circadian_percentage_profile);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNameShort() {
|
||||
String name = MainApp.sResources.getString(R.string.circadian_percentage_profile_shortname);
|
||||
if (!name.trim().isEmpty()){
|
||||
//only if translation exists
|
||||
return name;
|
||||
}
|
||||
// use long name as fallback
|
||||
return getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(int type) {
|
||||
return type == PROFILE && fragmentEnabled;
|
||||
|
@ -100,7 +107,6 @@ public class CircadianPercentageProfilePlugin implements PluginBase, ProfileInte
|
|||
editor.putBoolean(SETTINGS_PREFIX + "mmol", mmol);
|
||||
editor.putBoolean(SETTINGS_PREFIX + "mgdl", mgdl);
|
||||
editor.putString(SETTINGS_PREFIX + "dia", dia.toString());
|
||||
editor.putString(SETTINGS_PREFIX + "car", car.toString());
|
||||
editor.putString(SETTINGS_PREFIX + "targetlow", targetLow.toString());
|
||||
editor.putString(SETTINGS_PREFIX + "targethigh", targetHigh.toString());
|
||||
editor.putString(SETTINGS_PREFIX + "timeshift", timeshift + "");
|
||||
|
@ -142,13 +148,6 @@ public class CircadianPercentageProfilePlugin implements PluginBase, ProfileInte
|
|||
log.debug(e.getMessage());
|
||||
}
|
||||
else dia = 3d;
|
||||
if (settings.contains(SETTINGS_PREFIX + "car"))
|
||||
try {
|
||||
car = SafeParse.stringToDouble(settings.getString(SETTINGS_PREFIX + "car", "20"));
|
||||
} catch (Exception e) {
|
||||
log.debug(e.getMessage());
|
||||
}
|
||||
else car = 20d;
|
||||
if (settings.contains(SETTINGS_PREFIX + "targetlow"))
|
||||
try {
|
||||
targetLow = SafeParse.stringToDouble(settings.getString(SETTINGS_PREFIX + "targetlow", "80"));
|
||||
|
@ -228,9 +227,7 @@ public class CircadianPercentageProfilePlugin implements PluginBase, ProfileInte
|
|||
}
|
||||
profile.put("carbratio", icArray);
|
||||
|
||||
profile.put("carbs_hr", car);
|
||||
|
||||
JSONArray isfArray = new JSONArray();
|
||||
JSONArray isfArray = new JSONArray();
|
||||
for (int i = 0; i < 24; i++) {
|
||||
isfArray.put(new JSONObject().put("timeAsSeconds", i * 60 * 60).put("value", baseisf[(offset + i) % 24] * 100d / percentage));
|
||||
}
|
||||
|
@ -262,13 +259,13 @@ public class CircadianPercentageProfilePlugin implements PluginBase, ProfileInte
|
|||
}
|
||||
|
||||
private void performLimitCheck() {
|
||||
if (percentage < MIN_PERCENTAGE || percentage > MAX_PERCENTAGE){
|
||||
if (percentage < Constants.CPP_MIN_PERCENTAGE || percentage > Constants.CPP_MAX_PERCENTAGE){
|
||||
String msg = String.format(MainApp.sResources.getString(R.string.openapsma_valueoutofrange), "Profile-Percentage");
|
||||
log.error(msg);
|
||||
MainApp.getConfigBuilder().uploadError(msg);
|
||||
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), msg, R.raw.error);
|
||||
percentage = Math.max(percentage, MIN_PERCENTAGE);
|
||||
percentage = Math.min(percentage, MAX_PERCENTAGE);
|
||||
percentage = Math.max(percentage, Constants.CPP_MIN_PERCENTAGE);
|
||||
percentage = Math.min(percentage, Constants.CPP_MAX_PERCENTAGE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,9 @@ import android.view.LayoutInflater;
|
|||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.Button;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ListAdapter;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
|
@ -28,6 +30,7 @@ import info.nightscout.androidaps.interfaces.ProfileInterface;
|
|||
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||
import info.nightscout.androidaps.plugins.NSProfile.NSProfilePlugin;
|
||||
import info.nightscout.androidaps.plugins.VirtualPump.VirtualPumpPlugin;
|
||||
import info.nightscout.utils.PasswordProtection;
|
||||
|
||||
|
||||
public class ConfigBuilderFragment extends Fragment implements FragmentBase {
|
||||
|
@ -62,9 +65,10 @@ public class ConfigBuilderFragment extends Fragment implements FragmentBase {
|
|||
PluginCustomAdapter constraintsDataAdapter = null;
|
||||
PluginCustomAdapter generalDataAdapter = null;
|
||||
|
||||
LinearLayout mainLayout;
|
||||
Button unlock;
|
||||
|
||||
// TODO: sorting
|
||||
// TODO: Toast and sound when command failed
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
|
@ -90,6 +94,25 @@ public class ConfigBuilderFragment extends Fragment implements FragmentBase {
|
|||
if (ConfigBuilderPlugin.nightscoutVersionCode < 900)
|
||||
nightscoutVerView.setTextColor(Color.RED);
|
||||
setViews();
|
||||
|
||||
unlock = (Button) view.findViewById(R.id.configbuilder_unlock);
|
||||
mainLayout = (LinearLayout) view.findViewById(R.id.configbuilder_mainlayout);
|
||||
|
||||
if (PasswordProtection.isLocked("settings_password")) {
|
||||
mainLayout.setVisibility(View.GONE);
|
||||
unlock.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
PasswordProtection.QueryPassword(getContext(), R.string.settings_password, "settings_password", new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mainLayout.setVisibility(View.VISIBLE);
|
||||
unlock.setVisibility(View.GONE);
|
||||
}
|
||||
}, null);
|
||||
}
|
||||
});
|
||||
}
|
||||
return view;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,9 +16,12 @@ 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 java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
|
@ -27,6 +30,7 @@ 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.EventBolusRequested;
|
||||
import info.nightscout.androidaps.events.EventNewBG;
|
||||
import info.nightscout.androidaps.events.EventTempBasalChange;
|
||||
import info.nightscout.androidaps.events.EventTreatmentChange;
|
||||
|
@ -43,13 +47,13 @@ import info.nightscout.androidaps.plugins.DanaR.comm.MsgError;
|
|||
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.OpenAPSAMA.DetermineBasalResultAMA;
|
||||
import info.nightscout.androidaps.plugins.OpenAPSMA.DetermineBasalResultMA;
|
||||
import info.nightscout.androidaps.plugins.Overview.Dialogs.BolusProgressDialog;
|
||||
import info.nightscout.androidaps.plugins.Actions.dialogs.NewExtendedBolusDialog;
|
||||
import info.nightscout.androidaps.plugins.Overview.Dialogs.BolusProgressHelperActivity;
|
||||
import info.nightscout.androidaps.plugins.Overview.Notification;
|
||||
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
|
||||
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
|
||||
import info.nightscout.androidaps.plugins.SmsCommunicator.SmsCommunicatorPlugin;
|
||||
import info.nightscout.client.data.DbLogger;
|
||||
import info.nightscout.client.data.NSProfile;
|
||||
import info.nightscout.utils.DateUtil;
|
||||
|
@ -75,14 +79,16 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
|
|||
|
||||
static ArrayList<PluginBase> pluginList;
|
||||
|
||||
static Date lastDeviceStatusUpload = new Date(0);
|
||||
private static final ScheduledExecutorService worker = Executors.newSingleThreadScheduledExecutor();
|
||||
private static ScheduledFuture<?> scheduledPost = null;
|
||||
|
||||
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");;
|
||||
mWakeLock = powerManager.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "ConfigBuilderPlugin");
|
||||
;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -100,6 +106,17 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
|
|||
return MainApp.instance().getString(R.string.configbuilder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNameShort() {
|
||||
String name = MainApp.sResources.getString(R.string.configbuilder_shortname);
|
||||
if (!name.trim().isEmpty()) {
|
||||
//only if translation exists
|
||||
return name;
|
||||
}
|
||||
// use long name as fallback
|
||||
return getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(int type) {
|
||||
return type == GENERAL && true;
|
||||
|
@ -199,14 +216,14 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
|
|||
public void logPluginStatus() {
|
||||
for (PluginBase p : pluginList) {
|
||||
log.debug(p.getName() + ":" +
|
||||
(p.isEnabled(1) ? " GENERAL" : "") +
|
||||
(p.isEnabled(2) ? " TREATMENT" : "") +
|
||||
(p.isEnabled(3) ? " TEMPBASAL" : "") +
|
||||
(p.isEnabled(4) ? " PROFILE" : "") +
|
||||
(p.isEnabled(5) ? " APS" : "") +
|
||||
(p.isEnabled(6) ? " PUMP" : "") +
|
||||
(p.isEnabled(7) ? " CONSTRAINTS" : "") +
|
||||
(p.isEnabled(8) ? " LOOP" : "") +
|
||||
(p.isEnabled(1) ? " GENERAL" : "") +
|
||||
(p.isEnabled(2) ? " TREATMENT" : "") +
|
||||
(p.isEnabled(3) ? " TEMPBASAL" : "") +
|
||||
(p.isEnabled(4) ? " PROFILE" : "") +
|
||||
(p.isEnabled(5) ? " APS" : "") +
|
||||
(p.isEnabled(6) ? " PUMP" : "") +
|
||||
(p.isEnabled(7) ? " CONSTRAINTS" : "") +
|
||||
(p.isEnabled(8) ? " LOOP" : "") +
|
||||
(p.isEnabled(9) ? " BGSOURCE" : "")
|
||||
);
|
||||
}
|
||||
|
@ -324,6 +341,16 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
|
|||
return activePump.isInitialized();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSuspended() {
|
||||
return activePump.isSuspended();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBusy() {
|
||||
return activePump.isBusy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTempBasalInProgress() {
|
||||
return activePump.isTempBasalInProgress();
|
||||
|
@ -362,6 +389,16 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
|
|||
return activePump.isThisProfileSet(profile);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date lastStatusTime() {
|
||||
return activePump.lastStatusTime();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateStatus(String reason) {
|
||||
activePump.updateStatus(reason);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getBaseBasalRate() {
|
||||
return activePump.getBaseBasalRate();
|
||||
|
@ -404,6 +441,8 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
|
|||
bolusProgressDialog.show(((AppCompatActivity) context).getSupportFragmentManager(), "BolusProgress");
|
||||
}
|
||||
|
||||
MainApp.bus().post(new EventBolusRequested(insulin));
|
||||
|
||||
PumpEnactResult result = activePump.deliverTreatment(insulin, carbs, context);
|
||||
|
||||
BolusProgressDialog.bolusEnded = true;
|
||||
|
@ -423,15 +462,10 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
|
|||
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();
|
||||
}
|
||||
MainApp.getDbHelper().create(t);
|
||||
t.setTimeIndex(t.getTimeIndex());
|
||||
t.carbs = (double) result.carbsDelivered;
|
||||
uploadBolusWizardRecord(t, glucose, glucoseType, carbTime, boluscalc);
|
||||
MainApp.bus().post(new EventTreatmentChange());
|
||||
}
|
||||
mWakeLock.release();
|
||||
return result;
|
||||
|
@ -448,12 +482,20 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
|
|||
carbs = applyCarbsConstraints(carbs);
|
||||
|
||||
BolusProgressDialog bolusProgressDialog = null;
|
||||
if (context != null) {
|
||||
if (context != null ) {
|
||||
bolusProgressDialog = new BolusProgressDialog();
|
||||
bolusProgressDialog.setInsulin(insulin);
|
||||
bolusProgressDialog.show(((AppCompatActivity) context).getSupportFragmentManager(), "BolusProgress");
|
||||
} else {
|
||||
Intent i = new Intent();
|
||||
i.putExtra("insulin", insulin.doubleValue());
|
||||
i.setClass(MainApp.instance(), BolusProgressHelperActivity.class);
|
||||
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
MainApp.instance().startActivity(i);
|
||||
}
|
||||
|
||||
MainApp.bus().post(new EventBolusRequested(insulin));
|
||||
|
||||
PumpEnactResult result = activePump.deliverTreatment(insulin, carbs, context);
|
||||
|
||||
BolusProgressDialog.bolusEnded = true;
|
||||
|
@ -475,21 +517,15 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
|
|||
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();
|
||||
}
|
||||
MainApp.getDbHelper().create(t);
|
||||
t.setTimeIndex(t.getTimeIndex());
|
||||
t.sendToNSClient();
|
||||
MainApp.bus().post(new EventTreatmentChange());
|
||||
}
|
||||
mWakeLock.release();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void stopBolusDelivering() {
|
||||
activePump.stopBolusDelivering();
|
||||
|
@ -587,6 +623,17 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
|
|||
result.comment = MainApp.sResources.getString(R.string.pumpNotInitialized);
|
||||
result.enacted = false;
|
||||
result.success = false;
|
||||
log.debug("applyAPSRequest: " + MainApp.sResources.getString(R.string.pumpNotInitialized));
|
||||
return result;
|
||||
}
|
||||
|
||||
if (isSuspended()) {
|
||||
result = new PumpEnactResult();
|
||||
result.comment = MainApp.sResources.getString(R.string.pumpsuspended);
|
||||
result.enacted = false;
|
||||
result.success = false;
|
||||
log.debug("applyAPSRequest: " + MainApp.sResources.getString(R.string.pumpsuspended));
|
||||
return result;
|
||||
}
|
||||
|
||||
if (Config.logCongigBuilderActions)
|
||||
|
@ -647,12 +694,21 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
|
|||
emptyDescription.isBolusCapable = false;
|
||||
emptyDescription.isExtendedBolusCapable = false;
|
||||
emptyDescription.isSetBasalProfileCapable = false;
|
||||
emptyDescription.isTempBasalCapable = false;
|
||||
emptyDescription.isTempBasalCapable = true; // needs to be true before real driver is selected
|
||||
emptyDescription.isRefillingCapable = false;
|
||||
return emptyDescription;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String shortStatus(boolean veryShort) {
|
||||
if (activePump != null) {
|
||||
return activePump.shortStatus(veryShort);
|
||||
} else {
|
||||
return "No Pump active!";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constraints interface
|
||||
**/
|
||||
|
@ -697,7 +753,8 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
|
|||
|
||||
@Override
|
||||
public boolean isAMAModeEnabled() {
|
||||
boolean result = true;
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
|
||||
boolean result = preferences.getBoolean("openapsama_useautosens", false);
|
||||
|
||||
ArrayList<PluginBase> constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
|
||||
for (PluginBase p : constraintsPlugins) {
|
||||
|
@ -770,22 +827,7 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
|
|||
|
||||
@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();
|
||||
uploadDeviceStatus(120);
|
||||
}
|
||||
|
||||
public void uploadTempBasalStartAbsolute(Double absolute, double durationInMinutes) {
|
||||
|
@ -797,7 +839,7 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
|
|||
data.put("absolute", absolute);
|
||||
data.put("created_at", DateUtil.toISOString(new Date()));
|
||||
data.put("enteredBy", MainApp.instance().getString(R.string.app_name));
|
||||
data.put("notes", MainApp.sResources.getString(R.string.androidaps_tempbasalstartnote) + " " + absolute + "u/h " + durationInMinutes +" min"); // ECOR
|
||||
data.put("notes", MainApp.sResources.getString(R.string.androidaps_tempbasalstartnote) + " " + absolute + "u/h " + durationInMinutes + " min"); // ECOR
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString("action", "dbAdd");
|
||||
bundle.putString("collection", "treatments");
|
||||
|
@ -827,7 +869,7 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
|
|||
data.put("percent", percent - 100);
|
||||
data.put("created_at", DateUtil.toISOString(new Date()));
|
||||
data.put("enteredBy", MainApp.instance().getString(R.string.app_name));
|
||||
data.put("notes", MainApp.sResources.getString(R.string.androidaps_tempbasalstartnote) + " " + percent + "% " + durationInMinutes +" min"); // ECOR
|
||||
data.put("notes", MainApp.sResources.getString(R.string.androidaps_tempbasalstartnote) + " " + percent + "% " + durationInMinutes + " min"); // ECOR
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString("action", "dbAdd");
|
||||
bundle.putString("collection", "treatments");
|
||||
|
@ -891,18 +933,24 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
|
|||
}
|
||||
}
|
||||
|
||||
public void uploadDeviceStatus() {
|
||||
public void doUploadDeviceStatus() {
|
||||
DeviceStatus deviceStatus = new DeviceStatus();
|
||||
try {
|
||||
LoopPlugin.LastRun lastRun = LoopPlugin.lastRun;
|
||||
if (lastRun != null && lastRun.lastAPSRun.getTime() > new Date().getTime() - 60 * 1000L) {
|
||||
if (lastRun != null && lastRun.lastAPSRun.getTime() > new Date().getTime() - 300 * 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;
|
||||
if (lastRun.request instanceof DetermineBasalResultMA) {
|
||||
DetermineBasalResultMA result = (DetermineBasalResultMA) lastRun.request;
|
||||
deviceStatus.iob = result.iob.json();
|
||||
deviceStatus.iob.put("time", DateUtil.toISOString(lastRun.lastAPSRun));
|
||||
}
|
||||
|
||||
if (lastRun.request instanceof DetermineBasalResultAMA) {
|
||||
DetermineBasalResultAMA result = (DetermineBasalResultAMA) lastRun.request;
|
||||
deviceStatus.iob = result.iob.json();
|
||||
deviceStatus.iob.put("time", DateUtil.toISOString(lastRun.lastAPSRun));
|
||||
}
|
||||
|
@ -921,18 +969,36 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
|
|||
}
|
||||
if (activePump != null) {
|
||||
deviceStatus.device = "openaps://" + deviceID();
|
||||
deviceStatus.pump = getJSONStatus();
|
||||
JSONObject pumpstatus = getJSONStatus();
|
||||
if (pumpstatus != null) {
|
||||
deviceStatus.pump = getJSONStatus();
|
||||
}
|
||||
|
||||
deviceStatus.created_at = DateUtil.toISOString(new Date());
|
||||
|
||||
deviceStatus.sendToNSClient();
|
||||
lastDeviceStatusUpload = new Date();
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
static public void uploadDeviceStatus(int sec) {
|
||||
class PostRunnable implements Runnable {
|
||||
public void run() {
|
||||
MainApp.getConfigBuilder().doUploadDeviceStatus();
|
||||
scheduledPost = null;
|
||||
}
|
||||
}
|
||||
// prepare task for execution
|
||||
// cancel waiting task to prevent sending multiple posts
|
||||
if (scheduledPost != null)
|
||||
scheduledPost.cancel(false);
|
||||
Runnable task = new PostRunnable();
|
||||
scheduledPost = worker.schedule(task, sec, TimeUnit.SECONDS);
|
||||
log.debug("Scheduling devicestatus upload in " + sec + " sec");
|
||||
}
|
||||
|
||||
public void uploadBolusWizardRecord(Treatment t, double glucose, String glucoseType, int carbTime, JSONObject boluscalc) {
|
||||
JSONObject data = new JSONObject();
|
||||
try {
|
||||
|
@ -974,7 +1040,25 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
|
|||
intent.putExtras(bundle);
|
||||
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
|
||||
context.sendBroadcast(intent);
|
||||
DbLogger.dbAdd(intent, data.toString(), NewExtendedBolusDialog.class);
|
||||
DbLogger.dbAdd(intent, data.toString(), ConfigBuilderPlugin.class);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void removeCareportalEntryFromNS(String _id) {
|
||||
try {
|
||||
Context context = MainApp.instance().getApplicationContext();
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString("action", "dbRemove");
|
||||
bundle.putString("collection", "treatments");
|
||||
bundle.putString("_id", _id);
|
||||
Intent intent = new Intent(Intents.ACTION_DATABASE);
|
||||
intent.putExtras(bundle);
|
||||
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
|
||||
context.sendBroadcast(intent);
|
||||
DbLogger.dbRemove(intent, _id, ConfigBuilderPlugin.class);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ 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.History.DanaRStatsActivity;
|
||||
import info.nightscout.androidaps.plugins.DanaR.events.EventDanaRConnectionStatus;
|
||||
import info.nightscout.androidaps.plugins.DanaR.events.EventDanaRNewStatus;
|
||||
import info.nightscout.utils.DateUtil;
|
||||
|
@ -63,8 +64,11 @@ public class DanaRFragment extends Fragment implements FragmentBase {
|
|||
TextView batteryView;
|
||||
TextView reservoirView;
|
||||
TextView iobView;
|
||||
TextView firmwareView;
|
||||
Button viewProfileButton;
|
||||
Button historyButton;
|
||||
Button statsButton;
|
||||
|
||||
|
||||
public DanaRFragment() {
|
||||
if (sHandlerThread == null) {
|
||||
|
@ -103,8 +107,11 @@ public class DanaRFragment extends Fragment implements FragmentBase {
|
|||
batteryView = (TextView) view.findViewById(R.id.danar_battery);
|
||||
reservoirView = (TextView) view.findViewById(R.id.danar_reservoir);
|
||||
iobView = (TextView) view.findViewById(R.id.danar_iob);
|
||||
firmwareView = (TextView) view.findViewById(R.id.danar_firmware);
|
||||
viewProfileButton = (Button) view.findViewById(R.id.danar_viewprofile);
|
||||
historyButton = (Button) view.findViewById(R.id.danar_history);
|
||||
statsButton = (Button) view.findViewById(R.id.danar_stats);
|
||||
|
||||
|
||||
viewProfileButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
|
@ -122,6 +129,13 @@ public class DanaRFragment extends Fragment implements FragmentBase {
|
|||
}
|
||||
});
|
||||
|
||||
statsButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
startActivity(new Intent(getContext(), DanaRStatsActivity.class));
|
||||
}
|
||||
});
|
||||
|
||||
btConnectionView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
|
@ -194,24 +208,24 @@ public class DanaRFragment extends Fragment implements FragmentBase {
|
|||
@SuppressLint("SetTextI18n")
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
if (DanaRPlugin.getDanaRPump().lastConnection.getTime() != 0) {
|
||||
Long agoMsec = new Date().getTime() - DanaRPlugin.getDanaRPump().lastConnection.getTime();
|
||||
DanaRPump pump = DanaRPlugin.getDanaRPump();
|
||||
if (pump.lastConnection.getTime() != 0) {
|
||||
Long agoMsec = new Date().getTime() - pump.lastConnection.getTime();
|
||||
int agoMin = (int) (agoMsec / 60d / 1000d);
|
||||
lastConnectionView.setText(DateUtil.timeString(DanaRPlugin.getDanaRPump().lastConnection) + " (" + String.format(MainApp.sResources.getString(R.string.minago), agoMin) + ")");
|
||||
lastConnectionView.setText(DateUtil.timeString(pump.lastConnection) + " (" + String.format(MainApp.sResources.getString(R.string.minago), agoMin) + ")");
|
||||
SetWarnColor.setColor(lastConnectionView, agoMin, 16d, 31d);
|
||||
}
|
||||
if (DanaRPlugin.getDanaRPump().lastBolusTime.getTime() != 0) {
|
||||
Long agoMsec = new Date().getTime() - DanaRPlugin.getDanaRPump().lastBolusTime.getTime();
|
||||
if (pump.lastBolusTime.getTime() != 0) {
|
||||
Long agoMsec = new Date().getTime() - pump.lastBolusTime.getTime();
|
||||
double agoHours = agoMsec / 60d / 60d / 1000d;
|
||||
if (agoHours < 6) // max 6h back
|
||||
lastBolusView.setText(DateUtil.timeString(DanaRPlugin.getDanaRPump().lastBolusTime) + " (" + DecimalFormatter.to1Decimal(agoHours) + " " + getString(R.string.hoursago) + ") " + DecimalFormatter.to2Decimal(getPlugin().getDanaRPump().lastBolusAmount) + " U");
|
||||
lastBolusView.setText(DateUtil.timeString(pump.lastBolusTime) + " (" + DecimalFormatter.to1Decimal(agoHours) + " " + MainApp.sResources.getString(R.string.hoursago) + ") " + DecimalFormatter.to2Decimal(getPlugin().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(getPlugin().getBaseBasalRate()) + " U/h");
|
||||
dailyUnitsView.setText(DecimalFormatter.to0Decimal(pump.dailyTotalUnits) + " / " + pump.maxDailyTotalUnits + " U");
|
||||
SetWarnColor.setColor(dailyUnitsView, pump.dailyTotalUnits, pump.maxDailyTotalUnits * 0.75d, pump.maxDailyTotalUnits * 0.9d);
|
||||
basaBasalRateView.setText("( " + (pump.activeProfile + 1) + " ) " + DecimalFormatter.to2Decimal(getPlugin().getBaseBasalRate()) + " U/h");
|
||||
if (getPlugin().isRealTempBasalInProgress()) {
|
||||
tempBasalView.setText(getPlugin().getRealTempBasal().toString());
|
||||
} else {
|
||||
|
@ -222,11 +236,16 @@ public class DanaRFragment extends Fragment implements FragmentBase {
|
|||
} 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");
|
||||
reservoirView.setText(DecimalFormatter.to0Decimal(pump.reservoirRemainingUnits) + " / 300 U");
|
||||
SetWarnColor.setColorInverse(reservoirView, pump.reservoirRemainingUnits, 50d, 20d);
|
||||
batteryView.setText("{fa-battery-" + (pump.batteryRemaining / 25) + "}");
|
||||
SetWarnColor.setColorInverse(batteryView, pump.batteryRemaining, 51d, 26d);
|
||||
iobView.setText(pump.iob + " U");
|
||||
if (pump.isNewPump) {
|
||||
firmwareView.setText(String.format(MainApp.sResources.getString(R.string.danar_model), pump.model, pump.protocol, pump.productCode));
|
||||
} else {
|
||||
firmwareView.setText("OLD");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf
|
|||
private static DanaRPump sDanaRPump = new DanaRPump();
|
||||
private static boolean useExtendedBoluses = false;
|
||||
|
||||
private static PumpDescription pumpDescription = new PumpDescription();
|
||||
public static PumpDescription pumpDescription = new PumpDescription();
|
||||
|
||||
public static DanaRPump getDanaRPump() {
|
||||
return sDanaRPump;
|
||||
|
@ -85,7 +85,7 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf
|
|||
pumpDescription.bolusStep = 0.05d;
|
||||
|
||||
pumpDescription.isExtendedBolusCapable = true;
|
||||
pumpDescription.extendedBolusStep = 0.1d;
|
||||
pumpDescription.extendedBolusStep = 0.05d;
|
||||
|
||||
pumpDescription.isTempBasalCapable = true;
|
||||
pumpDescription.lowTempBasalStyle = PumpDescription.PERCENT;
|
||||
|
@ -154,6 +154,17 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf
|
|||
return MainApp.instance().getString(R.string.danarpump);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNameShort() {
|
||||
String name = MainApp.sResources.getString(R.string.danarpump_shortname);
|
||||
if (!name.trim().isEmpty()){
|
||||
//only if translation exists
|
||||
return name;
|
||||
}
|
||||
// use long name as fallback
|
||||
return getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(int type) {
|
||||
if (type == PluginBase.PROFILE) return fragmentProfileEnabled && fragmentPumpEnabled;
|
||||
|
@ -200,6 +211,17 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf
|
|||
return getDanaRPump().lastConnection.getTime() > 0 && getDanaRPump().isExtendedBolusEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSuspended() {
|
||||
return getDanaRPump().pumpSuspended;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBusy() {
|
||||
if (sExecutionService == null) return false;
|
||||
return sExecutionService.isConnected() || sExecutionService.isConnecting();
|
||||
}
|
||||
|
||||
// Pump interface
|
||||
@Override
|
||||
public boolean isTempBasalInProgress() {
|
||||
|
@ -247,12 +269,14 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf
|
|||
if (!isInitialized())
|
||||
return true; // TODO: not sure what's better. so far TRUE to prevent too many SMS
|
||||
DanaRPump pump = getDanaRPump();
|
||||
if (pump.pumpProfiles == null)
|
||||
return true; // TODO: not sure what's better. so far TRUE to prevent too many SMS
|
||||
int basalValues = pump.basal48Enable ? 48 : 24;
|
||||
int basalIncrement = pump.basal48Enable ? 30 * 60 : 60 * 60;
|
||||
for (int h = 0; h < basalValues; h++) {
|
||||
Double pumpValue = pump.pumpProfiles[pump.activeProfile][h];
|
||||
Double profileValue = profile.getBasal(h * basalIncrement);
|
||||
if (!pumpValue.equals(profileValue)) {
|
||||
if (Math.abs(pumpValue - profileValue) > getPumpDescription().basalStep) {
|
||||
log.debug("Diff found. Hour: " + h + " Pump: " + pumpValue + " Profile: " + profileValue);
|
||||
return false;
|
||||
}
|
||||
|
@ -260,6 +284,18 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date lastStatusTime() {
|
||||
return getDanaRPump().lastConnection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateStatus(String reason) {
|
||||
if (!isConnected() && !isConnecting()) {
|
||||
doConnect(reason);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getBaseBasalRate() {
|
||||
return getDanaRPump().currentBasal;
|
||||
|
@ -267,17 +303,19 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf
|
|||
|
||||
@Override
|
||||
public double getTempBasalAbsoluteRate() {
|
||||
if (isRealTempBasalInProgress()) {
|
||||
if (getRealTempBasal().isAbsolute) {
|
||||
return getRealTempBasal().absolute;
|
||||
TempBasal tb = getRealTempBasal();
|
||||
if (tb != null) {
|
||||
if (tb.isAbsolute) {
|
||||
return tb.absolute;
|
||||
} else {
|
||||
Double baseRate = getBaseBasalRate();
|
||||
Double tempRate = baseRate * (getRealTempBasal().percent / 100d);
|
||||
Double tempRate = baseRate * (tb.percent / 100d);
|
||||
return tempRate;
|
||||
}
|
||||
}
|
||||
if (isExtendedBoluslInProgress() && useExtendedBoluses) {
|
||||
return getBaseBasalRate() + getExtendedBolus().absolute;
|
||||
TempBasal eb = getExtendedBolus();
|
||||
if (eb != null && useExtendedBoluses) {
|
||||
return getBaseBasalRate() + eb.absolute;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -469,7 +507,7 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf
|
|||
}
|
||||
|
||||
// Compare with extended rate in progress
|
||||
if (Math.abs(getDanaRPump().extendedBolusAbsoluteRate - extendedRateToSet) < 0.02D) { // Allow some rounding diff
|
||||
if (isExtendedBoluslInProgress() && Math.abs(getDanaRPump().extendedBolusAbsoluteRate - extendedRateToSet) < getPumpDescription().extendedBolusStep) {
|
||||
// correct extended already set
|
||||
result.success = true;
|
||||
result.absolute = getDanaRPump().extendedBolusAbsoluteRate;
|
||||
|
@ -678,17 +716,18 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf
|
|||
JSONObject extended = new JSONObject();
|
||||
try {
|
||||
battery.put("percent", getDanaRPump().batteryRemaining);
|
||||
status.put("status", "normal");
|
||||
status.put("status", getDanaRPump().pumpSuspended ? "suspended" : "normal");
|
||||
status.put("timestamp", DateUtil.toISOString(getDanaRPump().lastConnection));
|
||||
extended.put("Version", BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION);
|
||||
extended.put("PumpIOB", getDanaRPump().iob);
|
||||
extended.put("LastBolus", getDanaRPump().lastBolusTime.toLocaleString());
|
||||
extended.put("LastBolusAmount", getDanaRPump().lastBolusAmount);
|
||||
if (isTempBasalInProgress()) {
|
||||
TempBasal tb = getTempBasal();
|
||||
if (tb != null) {
|
||||
extended.put("TempBasalAbsoluteRate", getTempBasalAbsoluteRate());
|
||||
extended.put("TempBasalStart", getTempBasal().timeStart.toLocaleString());
|
||||
extended.put("TempBasalRemaining", getTempBasal().getPlannedRemainingMinutes());
|
||||
extended.put("IsExtended", getTempBasal().isExtended);
|
||||
extended.put("TempBasalStart", tb.timeStart.toLocaleString());
|
||||
extended.put("TempBasalRemaining", tb.getPlannedRemainingMinutes());
|
||||
extended.put("IsExtended", tb.isExtended);
|
||||
}
|
||||
extended.put("BaseBasalRate", getBaseBasalRate());
|
||||
try {
|
||||
|
@ -800,7 +839,7 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf
|
|||
}
|
||||
|
||||
// Reply for sms communicator
|
||||
public String shortStatus() {
|
||||
public String shortStatus(boolean veryShort) {
|
||||
String ret = "";
|
||||
if (getDanaRPump().lastConnection.getTime() != 0) {
|
||||
Long agoMsec = new Date().getTime() - getDanaRPump().lastConnection.getTime();
|
||||
|
@ -816,6 +855,9 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf
|
|||
if (isExtendedBoluslInProgress()) {
|
||||
ret += "Extended: " + getExtendedBolus().toString() + "\n";
|
||||
}
|
||||
if (!veryShort){
|
||||
ret += "TDD: " + DecimalFormatter.to0Decimal(getDanaRPump().dailyTotalUnits) + " / " + getDanaRPump().maxDailyTotalUnits + " U\n";
|
||||
}
|
||||
ret += "IOB: " + getDanaRPump().iob + "U\n";
|
||||
ret += "Reserv: " + DecimalFormatter.to0Decimal(getDanaRPump().reservoirRemainingUnits) + "U\n";
|
||||
ret += "Batt: " + getDanaRPump().batteryRemaining + "\n";
|
||||
|
|
|
@ -36,7 +36,7 @@ public class DanaRPump {
|
|||
public String serialNumber = "";
|
||||
public Date shippingDate = new Date(0);
|
||||
public String shippingCountry = "";
|
||||
public boolean isNewPump = false;
|
||||
public boolean isNewPump = true;
|
||||
public int password = -1;
|
||||
public Date pumpTime = new Date(0);
|
||||
|
||||
|
@ -124,7 +124,6 @@ public class DanaRPump {
|
|||
|
||||
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", PROFILE_PREFIX + (activeProfile + 1));
|
||||
|
@ -139,8 +138,6 @@ public class DanaRPump {
|
|||
carbratios.put(new JSONObject().put("time", "22:00").put("timeAsSeconds", 22 * 3600).put("value", nightCIR));
|
||||
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", nightCF));
|
||||
sens.put(new JSONObject().put("time", "06:00").put("timeAsSeconds", 6 * 3600).put("value", morningCF));
|
||||
|
|
|
@ -0,0 +1,571 @@
|
|||
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.content.SharedPreferences;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.IBinder;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.text.TextUtils;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TableLayout;
|
||||
import android.widget.TableRow;
|
||||
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.text.DecimalFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.db.DanaRHistoryRecord;
|
||||
import info.nightscout.androidaps.interfaces.ProfileInterface;
|
||||
import info.nightscout.androidaps.plugins.CircadianPercentageProfile.CircadianPercentageProfilePlugin;
|
||||
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.utils.DecimalFormatter;
|
||||
import info.nightscout.utils.SafeParse;
|
||||
import info.nightscout.utils.ToastUtils;
|
||||
|
||||
public class DanaRStatsActivity extends Activity {
|
||||
private static Logger log = LoggerFactory.getLogger(DanaRStatsActivity.class);
|
||||
|
||||
private boolean mBounded;
|
||||
private static ExecutionService mExecutionService;
|
||||
|
||||
private Handler mHandler;
|
||||
private static HandlerThread mHandlerThread;
|
||||
|
||||
TextView statusView, statsMessage,totalBaseBasal2;
|
||||
EditText totalBaseBasal;
|
||||
Button reloadButton;
|
||||
LinearLayoutManager llm;
|
||||
TableLayout tl,ctl,etl;
|
||||
String TBB;
|
||||
double magicNumber;
|
||||
DecimalFormat decimalFormat;
|
||||
|
||||
List<DanaRHistoryRecord> historyList = new ArrayList<>();
|
||||
|
||||
public DanaRStatsActivity() {
|
||||
super();
|
||||
mHandlerThread = new HandlerThread(DanaRStatsActivity.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;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchTouchEvent(MotionEvent event) {
|
||||
if (event.getAction() == MotionEvent.ACTION_DOWN) {
|
||||
View myView = getCurrentFocus();
|
||||
if ( myView instanceof EditText) {
|
||||
Rect rect = new Rect();
|
||||
myView.getGlobalVisibleRect(rect);
|
||||
if (!rect.contains((int)event.getRawX(), (int)event.getRawY())) {
|
||||
myView.clearFocus();
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.dispatchTouchEvent( event );
|
||||
}
|
||||
|
||||
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_statsactivity);
|
||||
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
|
||||
statusView = (TextView) findViewById(R.id.danar_stats_connection_status);
|
||||
reloadButton = (Button) findViewById(R.id.danar_statsreload);
|
||||
totalBaseBasal = (EditText) findViewById(R.id.danar_stats_editTotalBaseBasal);
|
||||
totalBaseBasal2 = (TextView) findViewById(R.id.danar_stats_editTotalBaseBasal2);
|
||||
statsMessage = (TextView) findViewById(R.id.danar_stats_Message);
|
||||
|
||||
statusView.setVisibility(View.GONE);
|
||||
statsMessage.setVisibility(View.GONE);
|
||||
|
||||
totalBaseBasal2.setEnabled(false);
|
||||
totalBaseBasal2.setClickable(false);
|
||||
totalBaseBasal2.setFocusable(false);
|
||||
totalBaseBasal2.setInputType(0);
|
||||
|
||||
decimalFormat = new DecimalFormat("0.000");
|
||||
llm = new LinearLayoutManager(this);
|
||||
|
||||
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
TBB = preferences.getString("TBB", "10.00");
|
||||
totalBaseBasal.setText(TBB);
|
||||
|
||||
ProfileInterface pi = ConfigBuilderPlugin.getActiveProfile();
|
||||
if (pi != null && pi instanceof CircadianPercentageProfilePlugin){
|
||||
double cppTBB = ((CircadianPercentageProfilePlugin)pi).baseBasalSum();
|
||||
totalBaseBasal.setText(decimalFormat.format(cppTBB));
|
||||
SharedPreferences.Editor edit = preferences.edit();
|
||||
edit.putString("TBB",totalBaseBasal.getText().toString());
|
||||
edit.commit();
|
||||
TBB = preferences.getString("TBB", "");
|
||||
}
|
||||
|
||||
// stats table
|
||||
tl = (TableLayout) findViewById(R.id.main_table);
|
||||
TableRow tr_head = new TableRow(this);
|
||||
tr_head.setBackgroundColor(Color.DKGRAY);
|
||||
tr_head.setLayoutParams(new TableLayout.LayoutParams(
|
||||
TableLayout.LayoutParams.MATCH_PARENT,
|
||||
TableLayout.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
TextView label_date = new TextView(this);
|
||||
label_date.setText(getString(R.string.danar_stats_date));
|
||||
label_date.setTextColor(Color.WHITE);
|
||||
tr_head.addView(label_date);
|
||||
|
||||
TextView label_basalrate = new TextView(this);
|
||||
label_basalrate.setText(getString(R.string.danar_stats_basalrate));
|
||||
label_basalrate.setTextColor(Color.WHITE);
|
||||
tr_head.addView(label_basalrate);
|
||||
|
||||
TextView label_bolus = new TextView(this);
|
||||
label_bolus.setText(getString(R.string.danar_stats_bolus));
|
||||
label_bolus.setTextColor(Color.WHITE);
|
||||
tr_head.addView(label_bolus);
|
||||
|
||||
TextView label_tdd = new TextView(this);
|
||||
label_tdd.setText(getString(R.string.danar_stats_tdd));
|
||||
label_tdd.setTextColor(Color.WHITE);
|
||||
tr_head.addView(label_tdd);
|
||||
|
||||
TextView label_ratio = new TextView(this);
|
||||
label_ratio.setText(getString(R.string.danar_stats_ratio));
|
||||
label_ratio.setTextColor(Color.WHITE);
|
||||
tr_head.addView(label_ratio);
|
||||
|
||||
// add stats headers to tables
|
||||
tl.addView(tr_head, new TableLayout.LayoutParams(
|
||||
TableLayout.LayoutParams.MATCH_PARENT,
|
||||
TableLayout.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
// cumulative table
|
||||
ctl = (TableLayout) findViewById(R.id.cumulative_table);
|
||||
TableRow ctr_head = new TableRow(this);
|
||||
ctr_head.setBackgroundColor(Color.DKGRAY);
|
||||
ctr_head.setLayoutParams(new TableLayout.LayoutParams(
|
||||
TableLayout.LayoutParams.MATCH_PARENT,
|
||||
TableLayout.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
TextView label_cum_amount_days = new TextView(this);
|
||||
label_cum_amount_days.setText(getString(R.string.danar_stats_amount_days));
|
||||
label_cum_amount_days.setTextColor(Color.WHITE);
|
||||
ctr_head.addView(label_cum_amount_days);
|
||||
|
||||
TextView label_cum_tdd = new TextView(this);
|
||||
label_cum_tdd.setText(getString(R.string.danar_stats_tdd));
|
||||
label_cum_tdd.setTextColor(Color.WHITE);
|
||||
ctr_head.addView(label_cum_tdd);
|
||||
|
||||
TextView label_cum_ratio = new TextView(this);
|
||||
label_cum_ratio.setText(getString(R.string.danar_stats_ratio));
|
||||
label_cum_ratio.setTextColor(Color.WHITE);
|
||||
ctr_head.addView(label_cum_ratio);
|
||||
|
||||
// add cummulative headers to tables
|
||||
ctl.addView(ctr_head, new TableLayout.LayoutParams(
|
||||
TableLayout.LayoutParams.MATCH_PARENT,
|
||||
TableLayout.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
// expontial table
|
||||
etl = (TableLayout) findViewById(R.id.expweight_table);
|
||||
TableRow etr_head = new TableRow(this);
|
||||
etr_head.setBackgroundColor(Color.DKGRAY);
|
||||
etr_head.setLayoutParams(new TableLayout.LayoutParams(
|
||||
TableLayout.LayoutParams.MATCH_PARENT,
|
||||
TableLayout.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
TextView label_exp_weight = new TextView(this);
|
||||
label_exp_weight.setText(getString(R.string.danar_stats_weight));
|
||||
label_exp_weight.setTextColor(Color.WHITE);
|
||||
etr_head.addView(label_exp_weight);
|
||||
|
||||
TextView label_exp_tdd = new TextView(this);
|
||||
label_exp_tdd.setText(getString(R.string.danar_stats_tdd));
|
||||
label_exp_tdd.setTextColor(Color.WHITE);
|
||||
etr_head.addView(label_exp_tdd);
|
||||
|
||||
TextView label_exp_ratio = new TextView(this);
|
||||
label_exp_ratio.setText(getString(R.string.danar_stats_ratio));
|
||||
label_exp_ratio.setTextColor(Color.WHITE);
|
||||
etr_head.addView(label_exp_ratio);
|
||||
|
||||
// add expontial headers to tables
|
||||
etl.addView(etr_head, new TableLayout.LayoutParams(
|
||||
TableLayout.LayoutParams.MATCH_PARENT,
|
||||
TableLayout.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
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() {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
reloadButton.setVisibility(View.GONE);
|
||||
statusView.setVisibility(View.VISIBLE);
|
||||
statsMessage.setVisibility(View.VISIBLE);
|
||||
statsMessage.setText(getString(R.string.danar_stats_warning_Message));
|
||||
}
|
||||
});
|
||||
mExecutionService.loadHistory(RecordTypes.RECORD_TYPE_DAILY);
|
||||
loadDataFromDB(RecordTypes.RECORD_TYPE_DAILY);
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
reloadButton.setVisibility(View.VISIBLE);
|
||||
statusView.setVisibility(View.GONE);
|
||||
statsMessage.setVisibility(View.GONE);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
totalBaseBasal.setOnEditorActionListener(new TextView.OnEditorActionListener() {
|
||||
@Override
|
||||
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
|
||||
if(actionId== EditorInfo.IME_ACTION_DONE){
|
||||
totalBaseBasal.clearFocus();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
totalBaseBasal.setOnFocusChangeListener(new View.OnFocusChangeListener() {
|
||||
@Override
|
||||
public void onFocusChange(View v, boolean hasFocus) {
|
||||
if(hasFocus){
|
||||
totalBaseBasal.getText().clear();
|
||||
} else {
|
||||
SharedPreferences.Editor edit = preferences.edit();
|
||||
edit.putString("TBB",totalBaseBasal.getText().toString());
|
||||
edit.commit();
|
||||
TBB = preferences.getString("TBB", "");
|
||||
loadDataFromDB(RecordTypes.RECORD_TYPE_DAILY);
|
||||
InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
|
||||
imm.hideSoftInputFromWindow(totalBaseBasal.getWindowToken(), 0);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
loadDataFromDB(RecordTypes.RECORD_TYPE_DAILY);
|
||||
}
|
||||
|
||||
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(10L);
|
||||
PreparedQuery<DanaRHistoryRecord> preparedQuery = queryBuilder.prepare();
|
||||
historyList = dao.query(preparedQuery);
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
historyList = new ArrayList<>();
|
||||
}
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
cleanTable(tl);
|
||||
cleanTable(ctl);
|
||||
cleanTable(etl);
|
||||
DateFormat df = new SimpleDateFormat("dd.MM.");
|
||||
|
||||
if(TextUtils.isEmpty(TBB)) {
|
||||
totalBaseBasal.setError("Please Enter Total Base Basal");
|
||||
return;
|
||||
}
|
||||
else {
|
||||
magicNumber = SafeParse.stringToDouble(TBB);
|
||||
}
|
||||
|
||||
magicNumber *=2;
|
||||
totalBaseBasal2.setText(decimalFormat.format(magicNumber));
|
||||
|
||||
int i = 0;
|
||||
double sum = 0d;
|
||||
double weighted03 = 0d;
|
||||
double weighted05 = 0d;
|
||||
double weighted07 = 0d;
|
||||
|
||||
for (DanaRHistoryRecord record: historyList) {
|
||||
double tdd= record.getRecordDailyBolus() + record.getRecordDailyBasal();
|
||||
|
||||
// Create the table row
|
||||
TableRow tr = new TableRow(DanaRStatsActivity.this);
|
||||
if(i%2!=0) tr.setBackgroundColor(Color.DKGRAY);
|
||||
tr.setId(100+i);
|
||||
tr.setLayoutParams(new TableLayout.LayoutParams(
|
||||
TableLayout.LayoutParams.MATCH_PARENT,
|
||||
TableLayout.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
// Here create the TextView dynamically
|
||||
TextView labelDATE = new TextView(DanaRStatsActivity.this);
|
||||
labelDATE.setId(200+i);
|
||||
labelDATE.setText(df.format(new Date(record.getRecordDate())));
|
||||
labelDATE.setTextColor(Color.WHITE);
|
||||
tr.addView(labelDATE);
|
||||
|
||||
TextView labelBASAL = new TextView(DanaRStatsActivity.this);
|
||||
labelBASAL.setId(300+i);
|
||||
labelBASAL.setText(DecimalFormatter.to2Decimal(record.getRecordDailyBasal()) + " U");
|
||||
labelBASAL.setTextColor(Color.WHITE);
|
||||
tr.addView(labelBASAL);
|
||||
|
||||
TextView labelBOLUS = new TextView(DanaRStatsActivity.this);
|
||||
labelBOLUS.setId(400+i);
|
||||
labelBOLUS.setText(DecimalFormatter.to2Decimal(record.getRecordDailyBolus()) + " U");
|
||||
labelBOLUS.setTextColor(Color.WHITE);
|
||||
tr.addView(labelBOLUS);
|
||||
|
||||
TextView labelTDD = new TextView(DanaRStatsActivity.this);
|
||||
labelTDD.setId(500+i);
|
||||
labelTDD.setText(DecimalFormatter.to2Decimal(tdd) + " U");
|
||||
labelTDD.setTextColor(Color.WHITE);
|
||||
tr.addView(labelTDD);
|
||||
|
||||
TextView labelRATIO = new TextView(DanaRStatsActivity.this);
|
||||
labelRATIO.setId(600+i);
|
||||
labelRATIO.setText(Math.round(100*tdd/magicNumber) +" %");
|
||||
labelRATIO.setTextColor(Color.WHITE);
|
||||
tr.addView(labelRATIO);
|
||||
|
||||
// add stats rows to tables
|
||||
tl.addView(tr, new TableLayout.LayoutParams(
|
||||
TableLayout.LayoutParams.MATCH_PARENT,
|
||||
TableLayout.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
sum = sum + tdd;
|
||||
i++;
|
||||
|
||||
// Create the cumtable row
|
||||
TableRow ctr = new TableRow(DanaRStatsActivity.this);
|
||||
if(i%2==0) ctr.setBackgroundColor(Color.DKGRAY);
|
||||
ctr.setId(700+i);
|
||||
ctr.setLayoutParams(new TableLayout.LayoutParams(
|
||||
TableLayout.LayoutParams.MATCH_PARENT,
|
||||
TableLayout.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
// Here create the TextView dynamically
|
||||
TextView labelDAYS = new TextView(DanaRStatsActivity.this);
|
||||
labelDAYS.setId(800+i);
|
||||
labelDAYS.setText("" + i);
|
||||
labelDAYS.setTextColor(Color.WHITE);
|
||||
ctr.addView(labelDAYS);
|
||||
|
||||
TextView labelCUMTDD = new TextView(DanaRStatsActivity.this);
|
||||
labelCUMTDD.setId(900+i);
|
||||
labelCUMTDD.setText(DecimalFormatter.to2Decimal(sum/i) + " U");
|
||||
labelCUMTDD.setTextColor(Color.WHITE);
|
||||
ctr.addView(labelCUMTDD);
|
||||
|
||||
TextView labelCUMRATIO = new TextView(DanaRStatsActivity.this);
|
||||
labelCUMRATIO.setId(1000+i);
|
||||
labelCUMRATIO.setText(Math.round(100*sum/i/magicNumber) + " %");
|
||||
labelCUMRATIO.setTextColor(Color.WHITE);
|
||||
ctr.addView(labelCUMRATIO);
|
||||
|
||||
// add cummulative rows to tables
|
||||
ctl.addView(ctr, new TableLayout.LayoutParams(
|
||||
TableLayout.LayoutParams.MATCH_PARENT,
|
||||
TableLayout.LayoutParams.WRAP_CONTENT));
|
||||
}
|
||||
|
||||
if (historyList.size()<3 || !(df.format(new Date(historyList.get(0).getRecordDate())).equals(df.format(new Date(System.currentTimeMillis() - 1000*60*60*24))))){
|
||||
statsMessage.setVisibility(View.VISIBLE);
|
||||
statsMessage.setText(getString(R.string.danar_stats_olddata_Message));
|
||||
|
||||
} else {
|
||||
tl.setBackgroundColor(Color.TRANSPARENT);
|
||||
}
|
||||
|
||||
Collections.reverse(historyList);
|
||||
|
||||
i = 0;
|
||||
|
||||
for (DanaRHistoryRecord record: historyList) {
|
||||
double tdd= record.getRecordDailyBolus() + record.getRecordDailyBasal();
|
||||
if(i == 0 ) {
|
||||
weighted03 = tdd;
|
||||
weighted05 = tdd;
|
||||
weighted07 = tdd;
|
||||
|
||||
} else {
|
||||
weighted07 = (weighted07*0.3 + tdd*0.7);
|
||||
weighted05 = (weighted05*0.5 + tdd*0.5);
|
||||
weighted03 = (weighted03*0.7 + tdd*0.3);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
// Create the exptable row
|
||||
TableRow etr = new TableRow(DanaRStatsActivity.this);
|
||||
if(i%2!=0) etr.setBackgroundColor(Color.DKGRAY);
|
||||
etr.setId(1100+i);
|
||||
etr.setLayoutParams(new TableLayout.LayoutParams(
|
||||
TableLayout.LayoutParams.MATCH_PARENT,
|
||||
TableLayout.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
// Here create the TextView dynamically
|
||||
TextView labelWEIGHT = new TextView(DanaRStatsActivity.this);
|
||||
labelWEIGHT.setId(1200+i);
|
||||
labelWEIGHT.setText("0.3\n" + "0.5\n" + "0.7");
|
||||
labelWEIGHT.setTextColor(Color.WHITE);
|
||||
etr.addView(labelWEIGHT);
|
||||
|
||||
TextView labelEXPTDD = new TextView(DanaRStatsActivity.this);
|
||||
labelEXPTDD.setId(1300+i);
|
||||
labelEXPTDD.setText(DecimalFormatter.to2Decimal(weighted03)
|
||||
+ " U\n" + DecimalFormatter.to2Decimal(weighted05)
|
||||
+ " U\n" + DecimalFormatter.to2Decimal(weighted07) + " U");
|
||||
labelEXPTDD.setTextColor(Color.WHITE);
|
||||
etr.addView(labelEXPTDD);
|
||||
|
||||
TextView labelEXPRATIO = new TextView(DanaRStatsActivity.this);
|
||||
labelEXPRATIO.setId(1400+i);
|
||||
labelEXPRATIO.setText(Math.round(100*weighted03/magicNumber) +" %\n"
|
||||
+ Math.round(100*weighted05/magicNumber) +" %\n"
|
||||
+ Math.round(100*weighted07/magicNumber) +" %");
|
||||
labelEXPRATIO.setTextColor(Color.WHITE);
|
||||
etr.addView(labelEXPRATIO);
|
||||
|
||||
// add exponentail rows to tables
|
||||
etl.addView(etr, new TableLayout.LayoutParams(
|
||||
TableLayout.LayoutParams.MATCH_PARENT,
|
||||
TableLayout.LayoutParams.WRAP_CONTENT));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void cleanTable(TableLayout table) {
|
||||
int childCount = table.getChildCount();
|
||||
// Remove all rows except the first one
|
||||
if (childCount > 1) {
|
||||
table.removeViews(1, childCount - 1);
|
||||
}
|
||||
}
|
||||
|
||||
@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");
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
|
@ -176,6 +176,10 @@ public class SerialIOThread extends Thread {
|
|||
}
|
||||
if (!message.received) {
|
||||
log.warn("Reply not received " + message.getMessageName());
|
||||
if (message.getCommand() == 0xF0F1) {
|
||||
DanaRPlugin.getDanaRPump().isNewPump = false;
|
||||
log.debug("Old firmware detected");
|
||||
}
|
||||
}
|
||||
scheduleDisconnection();
|
||||
}
|
||||
|
|
|
@ -26,12 +26,15 @@ import java.util.Set;
|
|||
import java.util.UUID;
|
||||
|
||||
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.Treatment;
|
||||
import info.nightscout.androidaps.events.EventAppExit;
|
||||
import info.nightscout.androidaps.events.EventInitializationChanged;
|
||||
import info.nightscout.androidaps.events.EventPreferenceChange;
|
||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin;
|
||||
import info.nightscout.androidaps.plugins.DanaR.DanaRPump;
|
||||
import info.nightscout.androidaps.plugins.DanaR.SerialIOThread;
|
||||
|
@ -77,6 +80,8 @@ 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.androidaps.plugins.Overview.Notification;
|
||||
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
|
||||
import info.nightscout.client.data.NSProfile;
|
||||
import info.nightscout.utils.SafeParse;
|
||||
import info.nightscout.utils.ToastUtils;
|
||||
|
@ -226,6 +231,9 @@ public class ExecutionService extends Service {
|
|||
if (!getPumpStatus()) {
|
||||
mSerialIOThread.disconnect("getPumpStatus failed");
|
||||
waitMsec(3000);
|
||||
if (!MainApp.getSpecificPlugin(DanaRPlugin.class).isEnabled(PluginBase.PUMP))
|
||||
return;
|
||||
getBTSocketForSelectedPump();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -272,22 +280,25 @@ public class ExecutionService extends Service {
|
|||
|
||||
private boolean getPumpStatus() {
|
||||
try {
|
||||
MainApp.bus().post(new EventDanaRConnectionStatus(EventDanaRConnectionStatus.PERFORMING, 0, MainApp.sResources.getString(R.string.gettingpumpstatus)));
|
||||
MsgStatus statusMsg = new MsgStatus();
|
||||
MsgStatusBasic statusBasicMsg = new MsgStatusBasic();
|
||||
MsgStatusTempBasal tempStatusMsg = new MsgStatusTempBasal();
|
||||
MsgStatusBolusExtended exStatusMsg = new MsgStatusBolusExtended();
|
||||
MsgCheckValue checkValue = new MsgCheckValue();
|
||||
|
||||
if (danaRPump.isNewPump) {
|
||||
mSerialIOThread.sendMessage(checkValue);
|
||||
if (!checkValue.received) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
mSerialIOThread.sendMessage(new MsgSettingShippingInfo()); // TODO: show it somewhere
|
||||
mSerialIOThread.sendMessage(tempStatusMsg); // do this before statusBasic because here is temp duration
|
||||
mSerialIOThread.sendMessage(exStatusMsg);
|
||||
mSerialIOThread.sendMessage(statusMsg);
|
||||
mSerialIOThread.sendMessage(statusBasicMsg);
|
||||
|
||||
if (danaRPump.isNewPump) {
|
||||
mSerialIOThread.sendMessage(new MsgCheckValue());
|
||||
}
|
||||
|
||||
if (!statusMsg.received) {
|
||||
mSerialIOThread.sendMessage(statusMsg);
|
||||
}
|
||||
|
@ -330,6 +341,13 @@ public class ExecutionService extends Service {
|
|||
danaRPump.lastConnection = now;
|
||||
MainApp.bus().post(new EventDanaRNewStatus());
|
||||
MainApp.bus().post(new EventInitializationChanged());
|
||||
MainApp.getConfigBuilder().uploadDeviceStatus(60);
|
||||
if (danaRPump.dailyTotalUnits > danaRPump.maxDailyTotalUnits * Constants.dailyLimitWarning ) {
|
||||
log.debug("Approaching daily limit: " + danaRPump.dailyTotalUnits + "/" + danaRPump.maxDailyTotalUnits);
|
||||
Notification reportFail = new Notification(Notification.APPROACHING_DAILY_LIMIT, MainApp.sResources.getString(R.string.approachingdailylimit), Notification.URGENT);
|
||||
MainApp.bus().post(new EventNewNotification(reportFail));
|
||||
MainApp.getConfigBuilder().uploadError(MainApp.sResources.getString(R.string.approachingdailylimit) + ": " + danaRPump.dailyTotalUnits + "/" + danaRPump.maxDailyTotalUnits + "U");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
@ -339,30 +357,37 @@ public class ExecutionService extends Service {
|
|||
public boolean tempBasal(int percent, int durationInHours) {
|
||||
connect("tempBasal");
|
||||
if (!isConnected()) return false;
|
||||
MainApp.bus().post(new EventDanaRConnectionStatus(EventDanaRConnectionStatus.PERFORMING, 0, MainApp.sResources.getString(R.string.settingtempbasal)));
|
||||
mSerialIOThread.sendMessage(new MsgSetTempBasalStart(percent, durationInHours));
|
||||
mSerialIOThread.sendMessage(new MsgStatusTempBasal());
|
||||
MainApp.bus().post(new EventDanaRConnectionStatus(EventDanaRConnectionStatus.PERFORMING, 0, MainApp.sResources.getString(R.string.disconnecting)));
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean tempBasalStop() {
|
||||
connect("tempBasalStop");
|
||||
if (!isConnected()) return false;
|
||||
MainApp.bus().post(new EventDanaRConnectionStatus(EventDanaRConnectionStatus.PERFORMING, 0, MainApp.sResources.getString(R.string.stoppingtempbasal)));
|
||||
mSerialIOThread.sendMessage(new MsgSetTempBasalStop());
|
||||
mSerialIOThread.sendMessage(new MsgStatusTempBasal());
|
||||
MainApp.bus().post(new EventDanaRConnectionStatus(EventDanaRConnectionStatus.PERFORMING, 0, MainApp.sResources.getString(R.string.disconnecting)));
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean extendedBolus(double insulin, int durationInHalfHours) {
|
||||
connect("extendedBolus");
|
||||
if (!isConnected()) return false;
|
||||
MainApp.bus().post(new EventDanaRConnectionStatus(EventDanaRConnectionStatus.PERFORMING, 0, MainApp.sResources.getString(R.string.settingextendedbolus)));
|
||||
mSerialIOThread.sendMessage(new MsgSetExtendedBolusStart(insulin, (byte) (durationInHalfHours & 0xFF)));
|
||||
mSerialIOThread.sendMessage(new MsgStatusBolusExtended());
|
||||
MainApp.bus().post(new EventDanaRConnectionStatus(EventDanaRConnectionStatus.PERFORMING, 0, MainApp.sResources.getString(R.string.disconnecting)));
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean extendedBolusStop() {
|
||||
connect("extendedBolusStop");
|
||||
if (!isConnected()) return false;
|
||||
MainApp.bus().post(new EventDanaRConnectionStatus(EventDanaRConnectionStatus.PERFORMING, 0, MainApp.sResources.getString(R.string.stoppingextendedbolus)));
|
||||
mSerialIOThread.sendMessage(new MsgSetExtendedBolusStop());
|
||||
mSerialIOThread.sendMessage(new MsgStatusBolusExtended());
|
||||
return true;
|
||||
|
@ -476,6 +501,7 @@ public class ExecutionService extends Service {
|
|||
public boolean updateBasalsInPump(final NSProfile profile) {
|
||||
connect("updateBasalsInPump");
|
||||
if (!isConnected()) return false;
|
||||
MainApp.bus().post(new EventDanaRConnectionStatus(EventDanaRConnectionStatus.PERFORMING, 0, MainApp.sResources.getString(R.string.updatingbasalrates)));
|
||||
double[] basal = buildDanaRProfileRecord(profile);
|
||||
MsgSetBasalProfile msgSet = new MsgSetBasalProfile((byte) 0, basal);
|
||||
mSerialIOThread.sendMessage(msgSet);
|
||||
|
@ -483,6 +509,7 @@ public class ExecutionService extends Service {
|
|||
mSerialIOThread.sendMessage(msgActivate);
|
||||
danaRPump.lastSettingsRead = new Date(0); // force read full settings
|
||||
getPumpStatus();
|
||||
MainApp.bus().post(new EventDanaRConnectionStatus(EventDanaRConnectionStatus.PERFORMING, 0, MainApp.sResources.getString(R.string.disconnecting)));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,9 @@ public class MsgCheckValue extends MessageBase {
|
|||
public void handleMessage(byte[] bytes) {
|
||||
DanaRPump pump = DanaRPlugin.getDanaRPump();
|
||||
|
||||
DanaRPlugin.getDanaRPump().isNewPump = true;
|
||||
log.debug("New firmware confirmed");
|
||||
|
||||
pump.model = intFromBuff(bytes, 0, 1);
|
||||
pump.protocol = intFromBuff(bytes, 1, 1);
|
||||
pump.productCode = intFromBuff(bytes, 2, 1);
|
||||
|
|
|
@ -3,6 +3,7 @@ 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;
|
||||
|
||||
|
@ -21,7 +22,7 @@ public class MsgSetExtendedBolusStart extends MessageBase {
|
|||
if (halfhours > 16) halfhours = 16;
|
||||
amount = MainApp.getConfigBuilder().applyBolusConstraints(amount);
|
||||
if (amount < 0d) amount = 0d;
|
||||
if (amount > 10d) amount = 10d;
|
||||
if (amount > BuildConfig.MAXBOLUS) amount = BuildConfig.MAXBOLUS;
|
||||
|
||||
AddParamInt((int) (amount * 100));
|
||||
AddParamByte(halfhours);
|
||||
|
|
|
@ -23,7 +23,7 @@ public class MsgSettingBasal extends MessageBase {
|
|||
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;
|
||||
if (basal < DanaRPlugin.pumpDescription.basalMinimumRate) basal = 0;
|
||||
pump.pumpProfiles[pump.activeProfile][index] = basal / 100d;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,10 +24,6 @@ public class MsgSettingShippingInfo extends MessageBase {
|
|||
pump.serialNumber = stringFromBuff(bytes, 0, 10);
|
||||
pump.shippingDate = dateFromBuff(bytes, 10);
|
||||
pump.shippingCountry = asciiStringFromBuff(bytes, 13, 3);
|
||||
if (pump.shippingDate.getTime() > new Date(116, 4, 1).getTime()) {
|
||||
pump.isNewPump = true;
|
||||
} else
|
||||
pump.isNewPump = false;
|
||||
if (Config.logDanaMessageDetail) {
|
||||
log.debug("Serial number: " + pump.serialNumber);
|
||||
log.debug("Shipping date: " + pump.shippingDate);
|
||||
|
|
|
@ -4,12 +4,20 @@ public class EventDanaRConnectionStatus {
|
|||
public static final int CONNECTING = 0;
|
||||
public static final int CONNECTED = 1;
|
||||
public static final int DISCONNECTED = 2;
|
||||
public static final int PERFORMING = 3;
|
||||
|
||||
public int sStatus = DISCONNECTED;
|
||||
public int sSecondsElapsed = 0;
|
||||
public String sAction = "";
|
||||
|
||||
public EventDanaRConnectionStatus(int status, int secondsElapsed) {
|
||||
sStatus = status;
|
||||
sSecondsElapsed = secondsElapsed;
|
||||
}
|
||||
|
||||
public EventDanaRConnectionStatus(int status, int secondsElapsed, String action) {
|
||||
sStatus = status;
|
||||
sSecondsElapsed = secondsElapsed;
|
||||
sAction = action;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ import info.nightscout.androidaps.plugins.DanaR.Dialogs.ProfileViewDialog;
|
|||
import info.nightscout.androidaps.plugins.DanaR.events.EventDanaRConnectionStatus;
|
||||
import info.nightscout.androidaps.plugins.DanaR.events.EventDanaRNewStatus;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.History.DanaRHistoryActivity;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.History.DanaRStatsActivity;
|
||||
import info.nightscout.utils.DateUtil;
|
||||
import info.nightscout.utils.DecimalFormatter;
|
||||
import info.nightscout.utils.SetWarnColor;
|
||||
|
@ -60,8 +61,11 @@ public class DanaRKoreanFragment extends Fragment implements FragmentBase {
|
|||
TextView batteryView;
|
||||
TextView reservoirView;
|
||||
TextView iobView;
|
||||
TextView firmwareView;
|
||||
Button viewProfileButton;
|
||||
Button historyButton;
|
||||
Button statsButton;
|
||||
|
||||
|
||||
public DanaRKoreanFragment() {
|
||||
if (sHandlerThread == null) {
|
||||
|
@ -100,8 +104,11 @@ public class DanaRKoreanFragment extends Fragment implements FragmentBase {
|
|||
batteryView = (TextView) view.findViewById(R.id.danar_battery);
|
||||
reservoirView = (TextView) view.findViewById(R.id.danar_reservoir);
|
||||
iobView = (TextView) view.findViewById(R.id.danar_iob);
|
||||
firmwareView = (TextView) view.findViewById(R.id.danar_firmware);
|
||||
viewProfileButton = (Button) view.findViewById(R.id.danar_viewprofile);
|
||||
historyButton = (Button) view.findViewById(R.id.danar_history);
|
||||
statsButton = (Button) view.findViewById(R.id.danar_stats);
|
||||
|
||||
|
||||
viewProfileButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
|
@ -119,6 +126,13 @@ public class DanaRKoreanFragment extends Fragment implements FragmentBase {
|
|||
}
|
||||
});
|
||||
|
||||
statsButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
startActivity(new Intent(getContext(), DanaRStatsActivity.class));
|
||||
}
|
||||
});
|
||||
|
||||
btConnectionView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
|
@ -192,24 +206,24 @@ public class DanaRKoreanFragment extends Fragment implements FragmentBase {
|
|||
@SuppressLint("SetTextI18n")
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
if (DanaRKoreanPlugin.getDanaRPump().lastConnection.getTime() != 0) {
|
||||
Long agoMsec = new Date().getTime() - DanaRKoreanPlugin.getDanaRPump().lastConnection.getTime();
|
||||
DanaRKoreanPump pump = DanaRKoreanPlugin.getDanaRPump();
|
||||
if (pump.lastConnection.getTime() != 0) {
|
||||
Long agoMsec = new Date().getTime() - pump.lastConnection.getTime();
|
||||
int agoMin = (int) (agoMsec / 60d / 1000d);
|
||||
lastConnectionView.setText(DateUtil.timeString(DanaRKoreanPlugin.getDanaRPump().lastConnection) + " (" + String.format(MainApp.sResources.getString(R.string.minago), agoMin) + ")");
|
||||
lastConnectionView.setText(DateUtil.timeString(pump.lastConnection) + " (" + String.format(MainApp.sResources.getString(R.string.minago), agoMin) + ")");
|
||||
SetWarnColor.setColor(lastConnectionView, agoMin, 16d, 31d);
|
||||
}
|
||||
// if (DanaRKoreanPlugin.getDanaRPump().lastBolusTime.getTime() != 0) {
|
||||
// Long agoMsec = new Date().getTime() - DanaRKoreanPlugin.getDanaRPump().lastBolusTime.getTime();
|
||||
// if (pump.lastBolusTime.getTime() != 0) {
|
||||
// Long agoMsec = new Date().getTime() - pump.lastBolusTime.getTime();
|
||||
// double agoHours = agoMsec / 60d / 60d / 1000d;
|
||||
// if (agoHours < 6) // max 6h back
|
||||
// lastBolusView.setText(formatTime.format(DanaRKoreanPlugin.getDanaRPump().lastBolusTime) + " (" + DecimalFormatter.to1Decimal(agoHours) + " " + getString(R.string.hoursago) + ") " + DecimalFormatter.to2Decimal(danaRKoreanPlugin.getDanaRPump().lastBolusAmount) + " U");
|
||||
// lastBolusView.setText(formatTime.format(pump.lastBolusTime) + " (" + DecimalFormatter.to1Decimal(agoHours) + " " + getString(R.string.hoursago) + ") " + DecimalFormatter.to2Decimal(pump.lastBolusAmount) + " U");
|
||||
// else lastBolusView.setText("");
|
||||
// }
|
||||
|
||||
dailyUnitsView.setText(DecimalFormatter.to0Decimal(DanaRKoreanPlugin.getDanaRPump().dailyTotalUnits) + " / " + DanaRKoreanPlugin.getDanaRPump().maxDailyTotalUnits + " U");
|
||||
SetWarnColor.setColor(dailyUnitsView, DanaRKoreanPlugin.getDanaRPump().dailyTotalUnits, DanaRKoreanPlugin.getDanaRPump().maxDailyTotalUnits * 0.75d, DanaRKoreanPlugin.getDanaRPump().maxDailyTotalUnits * 0.9d);
|
||||
basaBasalRateView.setText("( " + (DanaRKoreanPlugin.getDanaRPump().activeProfile + 1) + " ) " + DecimalFormatter.to2Decimal(danaRKoreanPlugin.getBaseBasalRate()) + " U/h");
|
||||
dailyUnitsView.setText(DecimalFormatter.to0Decimal(pump.dailyTotalUnits) + " / " + pump.maxDailyTotalUnits + " U");
|
||||
SetWarnColor.setColor(dailyUnitsView, pump.dailyTotalUnits, pump.maxDailyTotalUnits * 0.75d, pump.maxDailyTotalUnits * 0.9d);
|
||||
basaBasalRateView.setText("( " + (pump.activeProfile + 1) + " ) " + DecimalFormatter.to2Decimal(danaRKoreanPlugin.getBaseBasalRate()) + " U/h");
|
||||
if (danaRKoreanPlugin.isRealTempBasalInProgress()) {
|
||||
tempBasalView.setText(danaRKoreanPlugin.getRealTempBasal().toString());
|
||||
} else {
|
||||
|
@ -220,11 +234,16 @@ public class DanaRKoreanFragment extends Fragment implements FragmentBase {
|
|||
} else {
|
||||
extendedBolusView.setText("");
|
||||
}
|
||||
reservoirView.setText(DecimalFormatter.to0Decimal(DanaRKoreanPlugin.getDanaRPump().reservoirRemainingUnits) + " / 300 U");
|
||||
SetWarnColor.setColorInverse(reservoirView, DanaRKoreanPlugin.getDanaRPump().reservoirRemainingUnits, 50d, 20d);
|
||||
batteryView.setText("{fa-battery-" + (DanaRKoreanPlugin.getDanaRPump().batteryRemaining / 25) + "}");
|
||||
SetWarnColor.setColorInverse(batteryView, DanaRKoreanPlugin.getDanaRPump().batteryRemaining, 51d, 26d);
|
||||
iobView.setText(DanaRKoreanPlugin.getDanaRPump().iob + " U");
|
||||
reservoirView.setText(DecimalFormatter.to0Decimal(pump.reservoirRemainingUnits) + " / 300 U");
|
||||
SetWarnColor.setColorInverse(reservoirView, pump.reservoirRemainingUnits, 50d, 20d);
|
||||
batteryView.setText("{fa-battery-" + (pump.batteryRemaining / 25) + "}");
|
||||
SetWarnColor.setColorInverse(batteryView, pump.batteryRemaining, 51d, 26d);
|
||||
iobView.setText(pump.iob + " U");
|
||||
if (pump.isNewPump) {
|
||||
firmwareView.setText(String.format(MainApp.sResources.getString(R.string.danar_model), pump.model, pump.protocol, pump.productCode));
|
||||
} else {
|
||||
firmwareView.setText("OLD");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, Constraints
|
|||
private static DanaRKoreanPump sDanaRKoreanPump = new DanaRKoreanPump();
|
||||
private static boolean useExtendedBoluses = false;
|
||||
|
||||
private PumpDescription pumpDescription = new PumpDescription();
|
||||
public static PumpDescription pumpDescription = new PumpDescription();
|
||||
|
||||
public static DanaRKoreanPump getDanaRPump() {
|
||||
return sDanaRKoreanPump;
|
||||
|
@ -85,7 +85,7 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, Constraints
|
|||
pumpDescription.bolusStep = 0.1d;
|
||||
|
||||
pumpDescription.isExtendedBolusCapable = true;
|
||||
pumpDescription.extendedBolusStep = 0.1d;
|
||||
pumpDescription.extendedBolusStep = 0.05d;
|
||||
|
||||
pumpDescription.isTempBasalCapable = true;
|
||||
pumpDescription.lowTempBasalStyle = PumpDescription.PERCENT;
|
||||
|
@ -154,6 +154,17 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, Constraints
|
|||
return MainApp.instance().getString(R.string.danarkoreanpump);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNameShort() {
|
||||
String name = MainApp.sResources.getString(R.string.danarpump_shortname);
|
||||
if (!name.trim().isEmpty()){
|
||||
//only if translation exists
|
||||
return name;
|
||||
}
|
||||
// use long name as fallback
|
||||
return getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(int type) {
|
||||
if (type == PluginBase.PROFILE) return fragmentProfileEnabled && fragmentPumpEnabled;
|
||||
|
@ -200,6 +211,17 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, Constraints
|
|||
return getDanaRPump().lastConnection.getTime() > 0 && !getDanaRPump().isConfigUD && !getDanaRPump().isEasyModeEnabled && getDanaRPump().isExtendedBolusEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSuspended() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBusy() {
|
||||
if (sExecutionService == null) return false;
|
||||
return sExecutionService.isConnected() || sExecutionService.isConnecting();
|
||||
}
|
||||
|
||||
// Pump interface
|
||||
@Override
|
||||
public boolean isTempBasalInProgress() {
|
||||
|
@ -247,6 +269,8 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, Constraints
|
|||
if (!isInitialized())
|
||||
return true; // TODO: not sure what's better. so far TRUE to prevent too many SMS
|
||||
DanaRKoreanPump pump = getDanaRPump();
|
||||
if (pump.pumpProfiles == null)
|
||||
return true; // TODO: not sure what's better. so far TRUE to prevent too many SMS
|
||||
int basalValues = pump.basal48Enable ? 48 : 24;
|
||||
int basalIncrement = pump.basal48Enable ? 30 * 60 : 60 * 60;
|
||||
for (int h = 0; h < basalValues; h++) {
|
||||
|
@ -260,6 +284,18 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, Constraints
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date lastStatusTime() {
|
||||
return getDanaRPump().lastConnection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateStatus(String reason) {
|
||||
if (!isConnected() && !isConnecting()) {
|
||||
doConnect(reason);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getBaseBasalRate() {
|
||||
return getDanaRPump().currentBasal;
|
||||
|
@ -267,17 +303,19 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, Constraints
|
|||
|
||||
@Override
|
||||
public double getTempBasalAbsoluteRate() {
|
||||
if (isRealTempBasalInProgress()) {
|
||||
if (getRealTempBasal().isAbsolute) {
|
||||
return getRealTempBasal().absolute;
|
||||
TempBasal tb = getRealTempBasal();
|
||||
if (tb != null) {
|
||||
if (tb.isAbsolute) {
|
||||
return tb.absolute;
|
||||
} else {
|
||||
Double baseRate = getBaseBasalRate();
|
||||
Double tempRate = baseRate * (getRealTempBasal().percent / 100d);
|
||||
Double tempRate = baseRate * (tb.percent / 100d);
|
||||
return tempRate;
|
||||
}
|
||||
}
|
||||
if (isExtendedBoluslInProgress() && useExtendedBoluses) {
|
||||
return getBaseBasalRate() + getExtendedBolus().absolute;
|
||||
TempBasal eb = getExtendedBolus();
|
||||
if (eb != null && useExtendedBoluses) {
|
||||
return getBaseBasalRate() + eb.absolute;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -469,7 +507,7 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, Constraints
|
|||
}
|
||||
|
||||
// Compare with extended rate in progress
|
||||
if (Math.abs(getDanaRPump().extendedBolusAbsoluteRate - extendedRateToSet) < 0.02D) { // Allow some rounding diff
|
||||
if (isExtendedBoluslInProgress() && Math.abs(getDanaRPump().extendedBolusAbsoluteRate - extendedRateToSet) < getPumpDescription().extendedBolusStep) {
|
||||
// correct extended already set
|
||||
result.success = true;
|
||||
result.absolute = getDanaRPump().extendedBolusAbsoluteRate;
|
||||
|
@ -684,11 +722,12 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, Constraints
|
|||
extended.put("PumpIOB", getDanaRPump().iob);
|
||||
// extended.put("LastBolus", getDanaRPump().lastBolusTime.toLocaleString());
|
||||
// extended.put("LastBolusAmount", getDanaRPump().lastBolusAmount);
|
||||
if (isTempBasalInProgress()) {
|
||||
TempBasal tb = getTempBasal();
|
||||
if (tb != null) {
|
||||
extended.put("TempBasalAbsoluteRate", getTempBasalAbsoluteRate());
|
||||
extended.put("TempBasalStart", getTempBasal().timeStart.toLocaleString());
|
||||
extended.put("TempBasalRemaining", getTempBasal().getPlannedRemainingMinutes());
|
||||
extended.put("IsExtended", getTempBasal().isExtended);
|
||||
extended.put("TempBasalStart", tb.timeStart.toLocaleString());
|
||||
extended.put("TempBasalRemaining", tb.getPlannedRemainingMinutes());
|
||||
extended.put("IsExtended", tb.isExtended);
|
||||
}
|
||||
extended.put("BaseBasalRate", getBaseBasalRate());
|
||||
try {
|
||||
|
@ -800,7 +839,7 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, Constraints
|
|||
}
|
||||
|
||||
// Reply for sms communicator
|
||||
public String shortStatus() {
|
||||
public String shortStatus(boolean veryShort) {
|
||||
String ret = "";
|
||||
if (getDanaRPump().lastConnection.getTime() != 0) {
|
||||
Long agoMsec = new Date().getTime() - getDanaRPump().lastConnection.getTime();
|
||||
|
@ -816,6 +855,9 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, Constraints
|
|||
if (isExtendedBoluslInProgress()) {
|
||||
ret += "Extended: " + getExtendedBolus().toString() + "\n";
|
||||
}
|
||||
if (!veryShort){
|
||||
ret += "TDD: " + DecimalFormatter.to0Decimal(getDanaRPump().dailyTotalUnits) + " / " + getDanaRPump().maxDailyTotalUnits + " U\n";
|
||||
}
|
||||
ret += "IOB: " + getDanaRPump().iob + "U\n";
|
||||
ret += "Reserv: " + DecimalFormatter.to0Decimal(getDanaRPump().reservoirRemainingUnits) + "U\n";
|
||||
ret += "Batt: " + getDanaRPump().batteryRemaining + "\n";
|
||||
|
|
|
@ -36,7 +36,7 @@ public class DanaRKoreanPump {
|
|||
public String serialNumber = "";
|
||||
public Date shippingDate = new Date(0);
|
||||
public String shippingCountry = "";
|
||||
public boolean isNewPump = false;
|
||||
public boolean isNewPump = true;
|
||||
public int password = -1;
|
||||
public Date pumpTime = new Date(0);
|
||||
|
||||
|
@ -117,7 +117,6 @@ public class DanaRKoreanPump {
|
|||
|
||||
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", PROFILE_PREFIX + (activeProfile + 1));
|
||||
|
@ -132,8 +131,6 @@ public class DanaRKoreanPump {
|
|||
carbratios.put(new JSONObject().put("time", "22:00").put("timeAsSeconds", 22 * 3600).put("value", nightCIR));
|
||||
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", nightCF));
|
||||
sens.put(new JSONObject().put("time", "06:00").put("timeAsSeconds", 6 * 3600).put("value", morningCF));
|
||||
|
|
|
@ -0,0 +1,571 @@
|
|||
package info.nightscout.androidaps.plugins.DanaRKorean.History;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.IBinder;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.text.TextUtils;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TableLayout;
|
||||
import android.widget.TableRow;
|
||||
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.text.DecimalFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.db.DanaRHistoryRecord;
|
||||
import info.nightscout.androidaps.interfaces.ProfileInterface;
|
||||
import info.nightscout.androidaps.plugins.CircadianPercentageProfile.CircadianPercentageProfilePlugin;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||
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.androidaps.plugins.DanaRKorean.Services.ExecutionService;
|
||||
import info.nightscout.utils.DecimalFormatter;
|
||||
import info.nightscout.utils.SafeParse;
|
||||
import info.nightscout.utils.ToastUtils;
|
||||
|
||||
public class DanaRStatsActivity extends Activity {
|
||||
private static Logger log = LoggerFactory.getLogger(DanaRStatsActivity.class);
|
||||
|
||||
private boolean mBounded;
|
||||
private static ExecutionService mExecutionService;
|
||||
|
||||
private Handler mHandler;
|
||||
private static HandlerThread mHandlerThread;
|
||||
|
||||
TextView statusView, statsMessage,totalBaseBasal2;
|
||||
EditText totalBaseBasal;
|
||||
Button reloadButton;
|
||||
LinearLayoutManager llm;
|
||||
TableLayout tl,ctl,etl;
|
||||
String TBB;
|
||||
double magicNumber;
|
||||
DecimalFormat decimalFormat;
|
||||
|
||||
List<DanaRHistoryRecord> historyList = new ArrayList<>();
|
||||
|
||||
public DanaRStatsActivity() {
|
||||
super();
|
||||
mHandlerThread = new HandlerThread(DanaRStatsActivity.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;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchTouchEvent(MotionEvent event) {
|
||||
if (event.getAction() == MotionEvent.ACTION_DOWN) {
|
||||
View myView = getCurrentFocus();
|
||||
if ( myView instanceof EditText) {
|
||||
Rect rect = new Rect();
|
||||
myView.getGlobalVisibleRect(rect);
|
||||
if (!rect.contains((int)event.getRawX(), (int)event.getRawY())) {
|
||||
myView.clearFocus();
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.dispatchTouchEvent( event );
|
||||
}
|
||||
|
||||
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_statsactivity);
|
||||
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
|
||||
statusView = (TextView) findViewById(R.id.danar_stats_connection_status);
|
||||
reloadButton = (Button) findViewById(R.id.danar_statsreload);
|
||||
totalBaseBasal = (EditText) findViewById(R.id.danar_stats_editTotalBaseBasal);
|
||||
totalBaseBasal2 = (TextView) findViewById(R.id.danar_stats_editTotalBaseBasal2);
|
||||
statsMessage = (TextView) findViewById(R.id.danar_stats_Message);
|
||||
|
||||
statusView.setVisibility(View.GONE);
|
||||
statsMessage.setVisibility(View.GONE);
|
||||
|
||||
totalBaseBasal2.setEnabled(false);
|
||||
totalBaseBasal2.setClickable(false);
|
||||
totalBaseBasal2.setFocusable(false);
|
||||
totalBaseBasal2.setInputType(0);
|
||||
|
||||
decimalFormat = new DecimalFormat("0.000");
|
||||
llm = new LinearLayoutManager(this);
|
||||
|
||||
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
TBB = preferences.getString("TBB", "10.00");
|
||||
totalBaseBasal.setText(TBB);
|
||||
|
||||
ProfileInterface pi = ConfigBuilderPlugin.getActiveProfile();
|
||||
if (pi != null && pi instanceof CircadianPercentageProfilePlugin){
|
||||
double cppTBB = ((CircadianPercentageProfilePlugin)pi).baseBasalSum();
|
||||
totalBaseBasal.setText(decimalFormat.format(cppTBB));
|
||||
SharedPreferences.Editor edit = preferences.edit();
|
||||
edit.putString("TBB",totalBaseBasal.getText().toString());
|
||||
edit.commit();
|
||||
TBB = preferences.getString("TBB", "");
|
||||
}
|
||||
|
||||
// stats table
|
||||
tl = (TableLayout) findViewById(R.id.main_table);
|
||||
TableRow tr_head = new TableRow(this);
|
||||
tr_head.setBackgroundColor(Color.DKGRAY);
|
||||
tr_head.setLayoutParams(new TableLayout.LayoutParams(
|
||||
TableLayout.LayoutParams.MATCH_PARENT,
|
||||
TableLayout.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
TextView label_date = new TextView(this);
|
||||
label_date.setText(getString(R.string.danar_stats_date));
|
||||
label_date.setTextColor(Color.WHITE);
|
||||
tr_head.addView(label_date);
|
||||
|
||||
TextView label_basalrate = new TextView(this);
|
||||
label_basalrate.setText(getString(R.string.danar_stats_basalrate));
|
||||
label_basalrate.setTextColor(Color.WHITE);
|
||||
tr_head.addView(label_basalrate);
|
||||
|
||||
TextView label_bolus = new TextView(this);
|
||||
label_bolus.setText(getString(R.string.danar_stats_bolus));
|
||||
label_bolus.setTextColor(Color.WHITE);
|
||||
tr_head.addView(label_bolus);
|
||||
|
||||
TextView label_tdd = new TextView(this);
|
||||
label_tdd.setText(getString(R.string.danar_stats_tdd));
|
||||
label_tdd.setTextColor(Color.WHITE);
|
||||
tr_head.addView(label_tdd);
|
||||
|
||||
TextView label_ratio = new TextView(this);
|
||||
label_ratio.setText(getString(R.string.danar_stats_ratio));
|
||||
label_ratio.setTextColor(Color.WHITE);
|
||||
tr_head.addView(label_ratio);
|
||||
|
||||
// add stats headers to tables
|
||||
tl.addView(tr_head, new TableLayout.LayoutParams(
|
||||
TableLayout.LayoutParams.MATCH_PARENT,
|
||||
TableLayout.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
// cumulative table
|
||||
ctl = (TableLayout) findViewById(R.id.cumulative_table);
|
||||
TableRow ctr_head = new TableRow(this);
|
||||
ctr_head.setBackgroundColor(Color.DKGRAY);
|
||||
ctr_head.setLayoutParams(new TableLayout.LayoutParams(
|
||||
TableLayout.LayoutParams.MATCH_PARENT,
|
||||
TableLayout.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
TextView label_cum_amount_days = new TextView(this);
|
||||
label_cum_amount_days.setText(getString(R.string.danar_stats_amount_days));
|
||||
label_cum_amount_days.setTextColor(Color.WHITE);
|
||||
ctr_head.addView(label_cum_amount_days);
|
||||
|
||||
TextView label_cum_tdd = new TextView(this);
|
||||
label_cum_tdd.setText(getString(R.string.danar_stats_tdd));
|
||||
label_cum_tdd.setTextColor(Color.WHITE);
|
||||
ctr_head.addView(label_cum_tdd);
|
||||
|
||||
TextView label_cum_ratio = new TextView(this);
|
||||
label_cum_ratio.setText(getString(R.string.danar_stats_ratio));
|
||||
label_cum_ratio.setTextColor(Color.WHITE);
|
||||
ctr_head.addView(label_cum_ratio);
|
||||
|
||||
// add cummulative headers to tables
|
||||
ctl.addView(ctr_head, new TableLayout.LayoutParams(
|
||||
TableLayout.LayoutParams.MATCH_PARENT,
|
||||
TableLayout.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
// expontial table
|
||||
etl = (TableLayout) findViewById(R.id.expweight_table);
|
||||
TableRow etr_head = new TableRow(this);
|
||||
etr_head.setBackgroundColor(Color.DKGRAY);
|
||||
etr_head.setLayoutParams(new TableLayout.LayoutParams(
|
||||
TableLayout.LayoutParams.MATCH_PARENT,
|
||||
TableLayout.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
TextView label_exp_weight = new TextView(this);
|
||||
label_exp_weight.setText(getString(R.string.danar_stats_weight));
|
||||
label_exp_weight.setTextColor(Color.WHITE);
|
||||
etr_head.addView(label_exp_weight);
|
||||
|
||||
TextView label_exp_tdd = new TextView(this);
|
||||
label_exp_tdd.setText(getString(R.string.danar_stats_tdd));
|
||||
label_exp_tdd.setTextColor(Color.WHITE);
|
||||
etr_head.addView(label_exp_tdd);
|
||||
|
||||
TextView label_exp_ratio = new TextView(this);
|
||||
label_exp_ratio.setText(getString(R.string.danar_stats_ratio));
|
||||
label_exp_ratio.setTextColor(Color.WHITE);
|
||||
etr_head.addView(label_exp_ratio);
|
||||
|
||||
// add expontial headers to tables
|
||||
etl.addView(etr_head, new TableLayout.LayoutParams(
|
||||
TableLayout.LayoutParams.MATCH_PARENT,
|
||||
TableLayout.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
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() {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
reloadButton.setVisibility(View.GONE);
|
||||
statusView.setVisibility(View.VISIBLE);
|
||||
statsMessage.setVisibility(View.VISIBLE);
|
||||
statsMessage.setText(getString(R.string.danar_stats_warning_Message));
|
||||
}
|
||||
});
|
||||
mExecutionService.loadHistory(RecordTypes.RECORD_TYPE_DAILY);
|
||||
loadDataFromDB(RecordTypes.RECORD_TYPE_DAILY);
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
reloadButton.setVisibility(View.VISIBLE);
|
||||
statusView.setVisibility(View.GONE);
|
||||
statsMessage.setVisibility(View.GONE);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
totalBaseBasal.setOnEditorActionListener(new TextView.OnEditorActionListener() {
|
||||
@Override
|
||||
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
|
||||
if(actionId== EditorInfo.IME_ACTION_DONE){
|
||||
totalBaseBasal.clearFocus();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
totalBaseBasal.setOnFocusChangeListener(new View.OnFocusChangeListener() {
|
||||
@Override
|
||||
public void onFocusChange(View v, boolean hasFocus) {
|
||||
if(hasFocus){
|
||||
totalBaseBasal.getText().clear();
|
||||
} else {
|
||||
SharedPreferences.Editor edit = preferences.edit();
|
||||
edit.putString("TBB",totalBaseBasal.getText().toString());
|
||||
edit.commit();
|
||||
TBB = preferences.getString("TBB", "");
|
||||
loadDataFromDB(RecordTypes.RECORD_TYPE_DAILY);
|
||||
InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
|
||||
imm.hideSoftInputFromWindow(totalBaseBasal.getWindowToken(), 0);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
loadDataFromDB(RecordTypes.RECORD_TYPE_DAILY);
|
||||
}
|
||||
|
||||
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(10L);
|
||||
PreparedQuery<DanaRHistoryRecord> preparedQuery = queryBuilder.prepare();
|
||||
historyList = dao.query(preparedQuery);
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
historyList = new ArrayList<>();
|
||||
}
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
cleanTable(tl);
|
||||
cleanTable(ctl);
|
||||
cleanTable(etl);
|
||||
DateFormat df = new SimpleDateFormat("dd.MM.");
|
||||
|
||||
if(TextUtils.isEmpty(TBB)) {
|
||||
totalBaseBasal.setError("Please Enter Total Base Basal");
|
||||
return;
|
||||
}
|
||||
else {
|
||||
magicNumber = SafeParse.stringToDouble(TBB);
|
||||
}
|
||||
|
||||
magicNumber *=2;
|
||||
totalBaseBasal2.setText(decimalFormat.format(magicNumber));
|
||||
|
||||
int i = 0;
|
||||
double sum = 0d;
|
||||
double weighted03 = 0d;
|
||||
double weighted05 = 0d;
|
||||
double weighted07 = 0d;
|
||||
|
||||
for (DanaRHistoryRecord record: historyList) {
|
||||
double tdd= record.getRecordDailyBolus() + record.getRecordDailyBasal();
|
||||
|
||||
// Create the table row
|
||||
TableRow tr = new TableRow(DanaRStatsActivity.this);
|
||||
if(i%2!=0) tr.setBackgroundColor(Color.DKGRAY);
|
||||
tr.setId(100+i);
|
||||
tr.setLayoutParams(new TableLayout.LayoutParams(
|
||||
TableLayout.LayoutParams.MATCH_PARENT,
|
||||
TableLayout.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
// Here create the TextView dynamically
|
||||
TextView labelDATE = new TextView(DanaRStatsActivity.this);
|
||||
labelDATE.setId(200+i);
|
||||
labelDATE.setText(df.format(new Date(record.getRecordDate())));
|
||||
labelDATE.setTextColor(Color.WHITE);
|
||||
tr.addView(labelDATE);
|
||||
|
||||
TextView labelBASAL = new TextView(DanaRStatsActivity.this);
|
||||
labelBASAL.setId(300+i);
|
||||
labelBASAL.setText(DecimalFormatter.to2Decimal(record.getRecordDailyBasal()) + " U");
|
||||
labelBASAL.setTextColor(Color.WHITE);
|
||||
tr.addView(labelBASAL);
|
||||
|
||||
TextView labelBOLUS = new TextView(DanaRStatsActivity.this);
|
||||
labelBOLUS.setId(400+i);
|
||||
labelBOLUS.setText(DecimalFormatter.to2Decimal(record.getRecordDailyBolus()) + " U");
|
||||
labelBOLUS.setTextColor(Color.WHITE);
|
||||
tr.addView(labelBOLUS);
|
||||
|
||||
TextView labelTDD = new TextView(DanaRStatsActivity.this);
|
||||
labelTDD.setId(500+i);
|
||||
labelTDD.setText(DecimalFormatter.to2Decimal(tdd) + " U");
|
||||
labelTDD.setTextColor(Color.WHITE);
|
||||
tr.addView(labelTDD);
|
||||
|
||||
TextView labelRATIO = new TextView(DanaRStatsActivity.this);
|
||||
labelRATIO.setId(600+i);
|
||||
labelRATIO.setText(Math.round(100*tdd/magicNumber) +" %");
|
||||
labelRATIO.setTextColor(Color.WHITE);
|
||||
tr.addView(labelRATIO);
|
||||
|
||||
// add stats rows to tables
|
||||
tl.addView(tr, new TableLayout.LayoutParams(
|
||||
TableLayout.LayoutParams.MATCH_PARENT,
|
||||
TableLayout.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
sum = sum + tdd;
|
||||
i++;
|
||||
|
||||
// Create the cumtable row
|
||||
TableRow ctr = new TableRow(DanaRStatsActivity.this);
|
||||
if(i%2==0) ctr.setBackgroundColor(Color.DKGRAY);
|
||||
ctr.setId(700+i);
|
||||
ctr.setLayoutParams(new TableLayout.LayoutParams(
|
||||
TableLayout.LayoutParams.MATCH_PARENT,
|
||||
TableLayout.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
// Here create the TextView dynamically
|
||||
TextView labelDAYS = new TextView(DanaRStatsActivity.this);
|
||||
labelDAYS.setId(800+i);
|
||||
labelDAYS.setText("" + i);
|
||||
labelDAYS.setTextColor(Color.WHITE);
|
||||
ctr.addView(labelDAYS);
|
||||
|
||||
TextView labelCUMTDD = new TextView(DanaRStatsActivity.this);
|
||||
labelCUMTDD.setId(900+i);
|
||||
labelCUMTDD.setText(DecimalFormatter.to2Decimal(sum/i) + " U");
|
||||
labelCUMTDD.setTextColor(Color.WHITE);
|
||||
ctr.addView(labelCUMTDD);
|
||||
|
||||
TextView labelCUMRATIO = new TextView(DanaRStatsActivity.this);
|
||||
labelCUMRATIO.setId(1000+i);
|
||||
labelCUMRATIO.setText(Math.round(100*sum/i/magicNumber) + " %");
|
||||
labelCUMRATIO.setTextColor(Color.WHITE);
|
||||
ctr.addView(labelCUMRATIO);
|
||||
|
||||
// add cummulative rows to tables
|
||||
ctl.addView(ctr, new TableLayout.LayoutParams(
|
||||
TableLayout.LayoutParams.MATCH_PARENT,
|
||||
TableLayout.LayoutParams.WRAP_CONTENT));
|
||||
}
|
||||
|
||||
if (historyList.size()<3 || !(df.format(new Date(historyList.get(0).getRecordDate())).equals(df.format(new Date(System.currentTimeMillis() - 1000*60*60*24))))){
|
||||
statsMessage.setVisibility(View.VISIBLE);
|
||||
statsMessage.setText(getString(R.string.danar_stats_olddata_Message));
|
||||
|
||||
} else {
|
||||
tl.setBackgroundColor(Color.TRANSPARENT);
|
||||
}
|
||||
|
||||
Collections.reverse(historyList);
|
||||
|
||||
i = 0;
|
||||
|
||||
for (DanaRHistoryRecord record: historyList) {
|
||||
double tdd= record.getRecordDailyBolus() + record.getRecordDailyBasal();
|
||||
if(i == 0 ) {
|
||||
weighted03 = tdd;
|
||||
weighted05 = tdd;
|
||||
weighted07 = tdd;
|
||||
|
||||
} else {
|
||||
weighted07 = (weighted07*0.3 + tdd*0.7);
|
||||
weighted05 = (weighted05*0.5 + tdd*0.5);
|
||||
weighted03 = (weighted03*0.7 + tdd*0.3);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
// Create the exptable row
|
||||
TableRow etr = new TableRow(DanaRStatsActivity.this);
|
||||
if(i%2!=0) etr.setBackgroundColor(Color.DKGRAY);
|
||||
etr.setId(1100+i);
|
||||
etr.setLayoutParams(new TableLayout.LayoutParams(
|
||||
TableLayout.LayoutParams.MATCH_PARENT,
|
||||
TableLayout.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
// Here create the TextView dynamically
|
||||
TextView labelWEIGHT = new TextView(DanaRStatsActivity.this);
|
||||
labelWEIGHT.setId(1200+i);
|
||||
labelWEIGHT.setText("0.3\n" + "0.5\n" + "0.7");
|
||||
labelWEIGHT.setTextColor(Color.WHITE);
|
||||
etr.addView(labelWEIGHT);
|
||||
|
||||
TextView labelEXPTDD = new TextView(DanaRStatsActivity.this);
|
||||
labelEXPTDD.setId(1300+i);
|
||||
labelEXPTDD.setText(DecimalFormatter.to2Decimal(weighted03)
|
||||
+ " U\n" + DecimalFormatter.to2Decimal(weighted05)
|
||||
+ " U\n" + DecimalFormatter.to2Decimal(weighted07) + " U");
|
||||
labelEXPTDD.setTextColor(Color.WHITE);
|
||||
etr.addView(labelEXPTDD);
|
||||
|
||||
TextView labelEXPRATIO = new TextView(DanaRStatsActivity.this);
|
||||
labelEXPRATIO.setId(1400+i);
|
||||
labelEXPRATIO.setText(Math.round(100*weighted03/magicNumber) +" %\n"
|
||||
+ Math.round(100*weighted05/magicNumber) +" %\n"
|
||||
+ Math.round(100*weighted07/magicNumber) +" %");
|
||||
labelEXPRATIO.setTextColor(Color.WHITE);
|
||||
etr.addView(labelEXPRATIO);
|
||||
|
||||
// add exponentail rows to tables
|
||||
etl.addView(etr, new TableLayout.LayoutParams(
|
||||
TableLayout.LayoutParams.MATCH_PARENT,
|
||||
TableLayout.LayoutParams.WRAP_CONTENT));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void cleanTable(TableLayout table) {
|
||||
int childCount = table.getChildCount();
|
||||
// Remove all rows except the first one
|
||||
if (childCount > 1) {
|
||||
table.removeViews(1, childCount - 1);
|
||||
}
|
||||
}
|
||||
|
||||
@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");
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
|
@ -176,6 +176,10 @@ public class SerialIOThread extends Thread {
|
|||
}
|
||||
if (!message.received) {
|
||||
log.warn("Reply not received " + message.getMessageName());
|
||||
if (message.getCommand() == 0xF0F1) {
|
||||
DanaRKoreanPlugin.getDanaRPump().isNewPump = false;
|
||||
log.debug("Old firmware detected");
|
||||
}
|
||||
}
|
||||
scheduleDisconnection();
|
||||
}
|
||||
|
|
|
@ -26,12 +26,14 @@ import java.util.Set;
|
|||
import java.util.UUID;
|
||||
|
||||
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.Treatment;
|
||||
import info.nightscout.androidaps.events.EventAppExit;
|
||||
import info.nightscout.androidaps.events.EventInitializationChanged;
|
||||
import info.nightscout.androidaps.events.EventPreferenceChange;
|
||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MessageBase;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgBolusProgress;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgBolusStart;
|
||||
|
@ -73,6 +75,8 @@ import info.nightscout.androidaps.plugins.DanaRKorean.comm.MsgSettingShippingInf
|
|||
import info.nightscout.androidaps.plugins.DanaRKorean.comm.MsgStatusBasic;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.comm.MsgStatusBolusExtended;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.comm.MsgStatusTempBasal;
|
||||
import info.nightscout.androidaps.plugins.Overview.Notification;
|
||||
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
|
||||
import info.nightscout.client.data.NSProfile;
|
||||
import info.nightscout.utils.SafeParse;
|
||||
import info.nightscout.utils.ToastUtils;
|
||||
|
@ -222,6 +226,9 @@ public class ExecutionService extends Service {
|
|||
if (!getPumpStatus()) {
|
||||
mSerialIOThread.disconnect("getPumpStatus failed");
|
||||
waitMsec(3000);
|
||||
if (!MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).isEnabled(PluginBase.PUMP))
|
||||
return;
|
||||
getBTSocketForSelectedPump();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -268,11 +275,19 @@ public class ExecutionService extends Service {
|
|||
|
||||
private boolean getPumpStatus() {
|
||||
try {
|
||||
MainApp.bus().post(new EventDanaRConnectionStatus(EventDanaRConnectionStatus.PERFORMING, 0, MainApp.sResources.getString(R.string.gettingpumpstatus)));
|
||||
//MsgStatus statusMsg = new MsgStatus();
|
||||
MsgStatusBasic statusBasicMsg = new MsgStatusBasic();
|
||||
MsgStatusTempBasal tempStatusMsg = new MsgStatusTempBasal();
|
||||
MsgStatusBolusExtended exStatusMsg = new MsgStatusBolusExtended();
|
||||
MsgCheckValue checkValue = new MsgCheckValue();
|
||||
|
||||
if (danaRKoreanPump.isNewPump) {
|
||||
mSerialIOThread.sendMessage(checkValue);
|
||||
if (!checkValue.received) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
mSerialIOThread.sendMessage(new MsgSettingShippingInfo()); // TODO: show it somewhere
|
||||
mSerialIOThread.sendMessage(tempStatusMsg); // do this before statusBasic because here is temp duration
|
||||
|
@ -280,8 +295,6 @@ public class ExecutionService extends Service {
|
|||
//mSerialIOThread.sendMessage(statusMsg);
|
||||
mSerialIOThread.sendMessage(statusBasicMsg);
|
||||
|
||||
mSerialIOThread.sendMessage(new MsgCheckValue());
|
||||
|
||||
// if (!statusMsg.received) {
|
||||
// mSerialIOThread.sendMessage(statusMsg);
|
||||
// }
|
||||
|
@ -321,6 +334,13 @@ public class ExecutionService extends Service {
|
|||
danaRKoreanPump.lastConnection = now;
|
||||
MainApp.bus().post(new EventDanaRNewStatus());
|
||||
MainApp.bus().post(new EventInitializationChanged());
|
||||
MainApp.getConfigBuilder().uploadDeviceStatus(60);
|
||||
if (danaRKoreanPump.dailyTotalUnits > danaRKoreanPump.maxDailyTotalUnits * Constants.dailyLimitWarning ) {
|
||||
log.debug("Approaching daily limit: " + danaRKoreanPump.dailyTotalUnits + "/" + danaRKoreanPump.maxDailyTotalUnits);
|
||||
Notification reportFail = new Notification(Notification.APPROACHING_DAILY_LIMIT, MainApp.sResources.getString(R.string.approachingdailylimit), Notification.URGENT);
|
||||
MainApp.bus().post(new EventNewNotification(reportFail));
|
||||
MainApp.getConfigBuilder().uploadError(MainApp.sResources.getString(R.string.approachingdailylimit) + ": " + danaRKoreanPump.dailyTotalUnits + "/" + danaRKoreanPump.maxDailyTotalUnits + "U");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
@ -330,32 +350,40 @@ public class ExecutionService extends Service {
|
|||
public boolean tempBasal(int percent, int durationInHours) {
|
||||
connect("tempBasal");
|
||||
if (!isConnected()) return false;
|
||||
MainApp.bus().post(new EventDanaRConnectionStatus(EventDanaRConnectionStatus.PERFORMING, 0, MainApp.sResources.getString(R.string.settingtempbasal)));
|
||||
mSerialIOThread.sendMessage(new MsgSetTempBasalStart(percent, durationInHours));
|
||||
mSerialIOThread.sendMessage(new MsgStatusTempBasal());
|
||||
MainApp.bus().post(new EventDanaRConnectionStatus(EventDanaRConnectionStatus.PERFORMING, 0, MainApp.sResources.getString(R.string.disconnecting)));
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean tempBasalStop() {
|
||||
connect("tempBasalStop");
|
||||
if (!isConnected()) return false;
|
||||
MainApp.bus().post(new EventDanaRConnectionStatus(EventDanaRConnectionStatus.PERFORMING, 0, MainApp.sResources.getString(R.string.stoppingtempbasal)));
|
||||
mSerialIOThread.sendMessage(new MsgSetTempBasalStop());
|
||||
mSerialIOThread.sendMessage(new MsgStatusTempBasal());
|
||||
MainApp.bus().post(new EventDanaRConnectionStatus(EventDanaRConnectionStatus.PERFORMING, 0, MainApp.sResources.getString(R.string.disconnecting)));
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean extendedBolus(double insulin, int durationInHalfHours) {
|
||||
connect("extendedBolus");
|
||||
if (!isConnected()) return false;
|
||||
MainApp.bus().post(new EventDanaRConnectionStatus(EventDanaRConnectionStatus.PERFORMING, 0, MainApp.sResources.getString(R.string.settingextendedbolus)));
|
||||
mSerialIOThread.sendMessage(new MsgSetExtendedBolusStart(insulin, (byte) (durationInHalfHours & 0xFF)));
|
||||
mSerialIOThread.sendMessage(new MsgStatusBolusExtended());
|
||||
MainApp.bus().post(new EventDanaRConnectionStatus(EventDanaRConnectionStatus.PERFORMING, 0, MainApp.sResources.getString(R.string.disconnecting)));
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean extendedBolusStop() {
|
||||
connect("extendedBolusStop");
|
||||
if (!isConnected()) return false;
|
||||
MainApp.bus().post(new EventDanaRConnectionStatus(EventDanaRConnectionStatus.PERFORMING, 0, MainApp.sResources.getString(R.string.stoppingextendedbolus)));
|
||||
mSerialIOThread.sendMessage(new MsgSetExtendedBolusStop());
|
||||
mSerialIOThread.sendMessage(new MsgStatusBolusExtended());
|
||||
MainApp.bus().post(new EventDanaRConnectionStatus(EventDanaRConnectionStatus.PERFORMING, 0, MainApp.sResources.getString(R.string.disconnecting)));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -467,11 +495,13 @@ public class ExecutionService extends Service {
|
|||
public boolean updateBasalsInPump(final NSProfile profile) {
|
||||
connect("updateBasalsInPump");
|
||||
if (!isConnected()) return false;
|
||||
MainApp.bus().post(new EventDanaRConnectionStatus(EventDanaRConnectionStatus.PERFORMING, 0, MainApp.sResources.getString(R.string.updatingbasalrates)));
|
||||
double[] basal = buildDanaRProfileRecord(profile);
|
||||
MsgSetSingleBasalProfile msgSet = new MsgSetSingleBasalProfile(basal);
|
||||
mSerialIOThread.sendMessage(msgSet);
|
||||
danaRKoreanPump.lastSettingsRead = new Date(0); // force read full settings
|
||||
getPumpStatus();
|
||||
MainApp.bus().post(new EventDanaRConnectionStatus(EventDanaRConnectionStatus.PERFORMING, 0, MainApp.sResources.getString(R.string.disconnecting)));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,9 @@ public class MsgCheckValue extends MessageBase {
|
|||
public void handleMessage(byte[] bytes) {
|
||||
DanaRKoreanPump pump = DanaRKoreanPlugin.getDanaRPump();
|
||||
|
||||
DanaRKoreanPlugin.getDanaRPump().isNewPump = true;
|
||||
log.debug("New firmware confirmed");
|
||||
|
||||
pump.model = intFromBuff(bytes, 0, 1);
|
||||
pump.protocol = intFromBuff(bytes, 1, 1);
|
||||
pump.productCode = intFromBuff(bytes, 2, 1);
|
||||
|
|
|
@ -24,7 +24,7 @@ public class MsgSettingBasal extends MessageBase {
|
|||
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;
|
||||
if (basal < DanaRKoreanPlugin.pumpDescription.basalMinimumRate) basal = 0;
|
||||
pump.pumpProfiles[pump.activeProfile][index] = basal / 100d;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,10 +25,6 @@ public class MsgSettingShippingInfo extends MessageBase {
|
|||
pump.serialNumber = stringFromBuff(bytes, 0, 10);
|
||||
pump.shippingDate = dateFromBuff(bytes, 10);
|
||||
pump.shippingCountry = asciiStringFromBuff(bytes, 13, 3);
|
||||
if (pump.shippingDate.getTime() > new Date(116, 4, 1).getTime()) {
|
||||
pump.isNewPump = true;
|
||||
} else
|
||||
pump.isNewPump = false;
|
||||
if (Config.logDanaMessageDetail) {
|
||||
log.debug("Serial number: " + pump.serialNumber);
|
||||
log.debug("Shipping date: " + pump.shippingDate);
|
||||
|
|
|
@ -45,7 +45,6 @@ public class LocalProfileFragment extends Fragment implements FragmentBase {
|
|||
RadioButton mmolView;
|
||||
TimeListEdit icView;
|
||||
TimeListEdit isfView;
|
||||
EditText carView;
|
||||
TimeListEdit basalView;
|
||||
TimeListEdit targetView;
|
||||
Button profileswitchButton;
|
||||
|
@ -66,7 +65,6 @@ public class LocalProfileFragment extends Fragment implements FragmentBase {
|
|||
mmolView = (RadioButton) layout.findViewById(R.id.localprofile_mmol);
|
||||
icView = new TimeListEdit(getContext(), layout, R.id.localprofile_ic, MainApp.sResources.getString(R.string.nsprofileview_ic_label), getPlugin().ic, null, new DecimalFormat("0.0"), save);
|
||||
isfView = new TimeListEdit(getContext(), layout, R.id.localprofile_isf, MainApp.sResources.getString(R.string.nsprofileview_isf_label), getPlugin().isf, null, new DecimalFormat("0.0"), save);
|
||||
carView = (EditText) layout.findViewById(R.id.localprofile_car);
|
||||
basalView = new TimeListEdit(getContext(), layout, R.id.localprofile_basal, MainApp.sResources.getString(R.string.nsprofileview_basal_label), getPlugin().basal, null, new DecimalFormat("0.00"), save);
|
||||
targetView = new TimeListEdit(getContext(), layout, R.id.localprofile_target, MainApp.sResources.getString(R.string.nsprofileview_target_label), getPlugin().targetLow, getPlugin().targetHigh, new DecimalFormat("0.0"), save);
|
||||
profileswitchButton = (Button) layout.findViewById(R.id.localprofile_profileswitch);
|
||||
|
@ -81,7 +79,6 @@ public class LocalProfileFragment extends Fragment implements FragmentBase {
|
|||
mgdlView.setChecked(localProfilePlugin.mgdl);
|
||||
mmolView.setChecked(localProfilePlugin.mmol);
|
||||
diaView.setText(localProfilePlugin.dia.toString());
|
||||
carView.setText(localProfilePlugin.car.toString());
|
||||
|
||||
mgdlView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
|
@ -106,7 +103,7 @@ public class LocalProfileFragment extends Fragment implements FragmentBase {
|
|||
@Override
|
||||
public void onClick(View view) {
|
||||
NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog();
|
||||
final OptionsToShow profileswitch = new OptionsToShow(R.id.careportal_profileswitch, R.string.careportal_profileswitch, true, false, false, false, false, false, false, true, false);
|
||||
final OptionsToShow profileswitch = new OptionsToShow(R.id.careportal_profileswitch, R.string.careportal_profileswitch, true, false, false, false, false, false, false, true, false, false);
|
||||
profileswitch.executeProfileSwitch = true;
|
||||
newDialog.setOptions(profileswitch);
|
||||
newDialog.show(getFragmentManager(), "NewNSTreatmentDialog");
|
||||
|
@ -128,13 +125,11 @@ public class LocalProfileFragment extends Fragment implements FragmentBase {
|
|||
public void onTextChanged(CharSequence s, int start,
|
||||
int before, int count) {
|
||||
localProfilePlugin.dia = SafeParse.stringToDouble(diaView.getText().toString());
|
||||
localProfilePlugin.car = SafeParse.stringToDouble(carView.getText().toString());
|
||||
localProfilePlugin.storeSettings();
|
||||
}
|
||||
};
|
||||
|
||||
diaView.addTextChangedListener(textWatch);
|
||||
carView.addTextChangedListener(textWatch);
|
||||
|
||||
onStatusEvent(null);
|
||||
|
||||
|
@ -161,7 +156,7 @@ public class LocalProfileFragment extends Fragment implements FragmentBase {
|
|||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!MainApp.getConfigBuilder().isInitialized() || !MainApp.getConfigBuilder().getPumpDescription().isSetBasalProfileCapable) {
|
||||
if (!MainApp.getConfigBuilder().isInitialized() || MainApp.getConfigBuilder().isSuspended() || !MainApp.getConfigBuilder().getPumpDescription().isSetBasalProfileCapable) {
|
||||
profileswitchButton.setVisibility(View.GONE);
|
||||
} else {
|
||||
profileswitchButton.setVisibility(View.VISIBLE);
|
||||
|
|
|
@ -37,7 +37,6 @@ public class LocalProfilePlugin implements PluginBase, ProfileInterface {
|
|||
Double dia;
|
||||
JSONArray ic;
|
||||
JSONArray isf;
|
||||
Double car;
|
||||
JSONArray basal;
|
||||
JSONArray targetLow;
|
||||
JSONArray targetHigh;
|
||||
|
@ -61,6 +60,17 @@ public class LocalProfilePlugin implements PluginBase, ProfileInterface {
|
|||
return MainApp.instance().getString(R.string.localprofile);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNameShort() {
|
||||
String name = MainApp.sResources.getString(R.string.localprofile_shortname);
|
||||
if (!name.trim().isEmpty()){
|
||||
//only if translation exists
|
||||
return name;
|
||||
}
|
||||
// use long name as fallback
|
||||
return getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(int type) {
|
||||
return type == PROFILE && fragmentEnabled;
|
||||
|
@ -96,7 +106,6 @@ public class LocalProfilePlugin implements PluginBase, ProfileInterface {
|
|||
editor.putString("LocalProfile" + "dia", dia.toString());
|
||||
editor.putString("LocalProfile" + "ic", ic.toString());
|
||||
editor.putString("LocalProfile" + "isf", isf.toString());
|
||||
editor.putString("LocalProfile" + "car", car.toString());
|
||||
editor.putString("LocalProfile" + "basal", basal.toString());
|
||||
editor.putString("LocalProfile" + "targetlow", targetLow.toString());
|
||||
editor.putString("LocalProfile" + "targethigh", targetHigh.toString());
|
||||
|
@ -167,13 +176,6 @@ public class LocalProfilePlugin implements PluginBase, ProfileInterface {
|
|||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (settings.contains("LocalProfile" + "car"))
|
||||
try {
|
||||
car = SafeParse.stringToDouble(settings.getString("LocalProfile" + "car", "20"));
|
||||
} catch (Exception e) {
|
||||
log.debug(e.getMessage());
|
||||
}
|
||||
else car = 20d;
|
||||
if (settings.contains("LocalProfile" + "basal"))
|
||||
try {
|
||||
basal = new JSONArray(settings.getString("LocalProfile" + "basal", DEFAULTARRAY));
|
||||
|
@ -279,7 +281,6 @@ public class LocalProfilePlugin implements PluginBase, ProfileInterface {
|
|||
json.put("store", store);
|
||||
profile.put("dia", dia);
|
||||
profile.put("carbratio", ic);
|
||||
profile.put("carbs_hr", car);
|
||||
profile.put("sens", isf);
|
||||
profile.put("basal", basal);
|
||||
profile.put("target_low", targetLow);
|
||||
|
|
|
@ -16,7 +16,7 @@ import info.nightscout.utils.DecimalFormatter;
|
|||
/**
|
||||
* Created by mike on 09.06.2016.
|
||||
*/
|
||||
public class APSResult implements Parcelable {
|
||||
public class APSResult {
|
||||
public String reason;
|
||||
public double rate;
|
||||
public int duration;
|
||||
|
@ -51,36 +51,6 @@ public class APSResult implements Parcelable {
|
|||
return Html.fromHtml(MainApp.sResources.getString(R.string.nochangerequested));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeString(reason);
|
||||
dest.writeDouble(rate);
|
||||
dest.writeInt(duration);
|
||||
dest.writeInt(changeRequested ? 1 : 0);
|
||||
}
|
||||
|
||||
public final Parcelable.Creator<APSResult> CREATOR = new Parcelable.Creator<APSResult>() {
|
||||
public APSResult createFromParcel(Parcel in) {
|
||||
return new APSResult(in);
|
||||
}
|
||||
|
||||
public APSResult[] newArray(int size) {
|
||||
return new APSResult[size];
|
||||
}
|
||||
};
|
||||
|
||||
protected APSResult(Parcel in) {
|
||||
reason = in.readString();
|
||||
rate = in.readDouble();
|
||||
duration = in.readInt();
|
||||
changeRequested = in.readInt() == 1;
|
||||
}
|
||||
|
||||
public APSResult() {
|
||||
}
|
||||
|
||||
|
|
|
@ -76,7 +76,14 @@ public class LoopFragment extends Fragment implements View.OnClickListener, Frag
|
|||
public void onClick(View view) {
|
||||
switch (view.getId()) {
|
||||
case R.id.loop_run:
|
||||
getPlugin().invoke(true);
|
||||
lastRunView.setText(MainApp.sResources.getString(R.string.executing));
|
||||
Thread thread = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
getPlugin().invoke("Loop button", true);
|
||||
}
|
||||
});
|
||||
thread.start();
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -81,6 +81,17 @@ public class LoopPlugin implements PluginBase {
|
|||
return MainApp.instance().getString(R.string.loop);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNameShort() {
|
||||
String name = MainApp.sResources.getString(R.string.loop_shortname);
|
||||
if (!name.trim().isEmpty()){
|
||||
//only if translation exists
|
||||
return name;
|
||||
}
|
||||
// use long name as fallback
|
||||
return getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(int type) {
|
||||
return type == LOOP && fragmentEnabled && MainApp.getConfigBuilder().getPumpDescription().isTempBasalCapable;
|
||||
|
@ -108,15 +119,15 @@ public class LoopPlugin implements PluginBase {
|
|||
|
||||
@Subscribe
|
||||
public void onStatusEvent(final EventTreatmentChange ev) {
|
||||
invoke(true);
|
||||
invoke("EventTreatmentChange", true);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onStatusEvent(final EventNewBG ev) {
|
||||
invoke(true);
|
||||
invoke("EventNewBG", true);
|
||||
}
|
||||
|
||||
public void invoke(boolean allowNotification) {
|
||||
public void invoke(String initiator, boolean allowNotification) {
|
||||
try {
|
||||
if (Config.logFunctionCalls)
|
||||
log.debug("invoke");
|
||||
|
@ -136,7 +147,7 @@ public class LoopPlugin implements PluginBase {
|
|||
|
||||
APSInterface usedAPS = configBuilder.getActiveAPS();
|
||||
if (usedAPS != null && ((PluginBase) usedAPS).isEnabled(PluginBase.APS)) {
|
||||
usedAPS.invoke();
|
||||
usedAPS.invoke(initiator);
|
||||
result = usedAPS.getLastAPSResult();
|
||||
}
|
||||
|
||||
|
@ -217,7 +228,7 @@ public class LoopPlugin implements PluginBase {
|
|||
}
|
||||
|
||||
MainApp.bus().post(new EventLoopUpdateGui());
|
||||
MainApp.getConfigBuilder().uploadDeviceStatus();
|
||||
MainApp.getConfigBuilder().uploadDeviceStatus(120);
|
||||
} finally {
|
||||
if (Config.logFunctionCalls)
|
||||
log.debug("invoke end");
|
||||
|
|
|
@ -74,6 +74,12 @@ public class MDIPlugin implements PluginBase, PumpInterface {
|
|||
return MainApp.instance().getString(R.string.mdi);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNameShort() {
|
||||
// use long name as fallback (not visible in tabs)
|
||||
return getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(int type) {
|
||||
return type == PUMP && fragmentEnabled;
|
||||
|
@ -109,6 +115,16 @@ public class MDIPlugin implements PluginBase, PumpInterface {
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSuspended() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBusy() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTempBasalInProgress() {
|
||||
return false;
|
||||
|
@ -130,6 +146,16 @@ public class MDIPlugin implements PluginBase, PumpInterface {
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date lastStatusTime() {
|
||||
return new Date();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateStatus(String reason) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getBaseBasalRate() {
|
||||
return 0d;
|
||||
|
@ -256,4 +282,9 @@ public class MDIPlugin implements PluginBase, PumpInterface {
|
|||
return pumpDescription;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String shortStatus(boolean veryShort) {
|
||||
return deviceID();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -49,6 +49,17 @@ public class NSProfilePlugin implements PluginBase, ProfileInterface {
|
|||
return MainApp.instance().getString(R.string.profileviewer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNameShort() {
|
||||
String name = MainApp.sResources.getString(R.string.profileviewer_shortname);
|
||||
if (!name.trim().isEmpty()){
|
||||
//only if translation exists
|
||||
return name;
|
||||
}
|
||||
// use long name as fallback
|
||||
return getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(int type) {
|
||||
return type == PROFILE && fragmentEnabled;
|
||||
|
|
|
@ -49,6 +49,17 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface {
|
|||
return MainApp.instance().getString(R.string.objectives);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNameShort() {
|
||||
String name = MainApp.sResources.getString(R.string.objectives_shortname);
|
||||
if (!name.trim().isEmpty()){
|
||||
//only if translation exists
|
||||
return name;
|
||||
}
|
||||
// use long name as fallback
|
||||
return getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(int type) {
|
||||
return type == CONSTRAINTS && MainApp.getConfigBuilder().getPumpDescription().isTempBasalCapable;
|
||||
|
@ -177,7 +188,7 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface {
|
|||
MainApp.sResources.getString(R.string.objectives_6_objective),
|
||||
"",
|
||||
new Date(0),
|
||||
1,
|
||||
14,
|
||||
new Date(0)));
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,242 @@
|
|||
package info.nightscout.androidaps.plugins.OpenAPSAMA;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import info.nightscout.androidaps.Constants;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.data.IobTotal;
|
||||
import info.nightscout.androidaps.db.BgReading;
|
||||
import info.nightscout.client.data.NSProfile;
|
||||
import info.nightscout.utils.Round;
|
||||
import info.nightscout.utils.SafeParse;
|
||||
|
||||
|
||||
public class Autosens {
|
||||
private static Logger log = LoggerFactory.getLogger(Autosens.class);
|
||||
|
||||
public static AutosensResult detectSensitivityandCarbAbsorption(List<BgReading> glucose_data, Long mealTime) {
|
||||
SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
|
||||
NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile();
|
||||
|
||||
//console.error(mealTime);
|
||||
|
||||
double deviationSum = 0;
|
||||
double carbsAbsorbed = 0;
|
||||
|
||||
List<BgReading> bucketed_data = new ArrayList<>();
|
||||
bucketed_data.add(glucose_data.get(0));
|
||||
int j = 0;
|
||||
for (int i = 1; i < glucose_data.size(); ++i) {
|
||||
long bgTime = glucose_data.get(i).getTimeIndex();
|
||||
long lastbgTime = glucose_data.get(i - 1).getTimeIndex();
|
||||
if (glucose_data.get(i).value < 39 || glucose_data.get(i - 1).value < 39) {
|
||||
continue;
|
||||
}
|
||||
|
||||
long elapsed_minutes = (bgTime - lastbgTime) / (60 * 1000);
|
||||
if (Math.abs(elapsed_minutes) > 8) {
|
||||
// interpolate missing data points
|
||||
double lastbg = glucose_data.get(i - 1).value;
|
||||
elapsed_minutes = Math.abs(elapsed_minutes);
|
||||
//console.error(elapsed_minutes);
|
||||
long nextbgTime;
|
||||
while (elapsed_minutes > 5) {
|
||||
nextbgTime = lastbgTime + 5 * 60 * 1000;
|
||||
j++;
|
||||
BgReading newBgreading = new BgReading();
|
||||
newBgreading.timeIndex = nextbgTime;
|
||||
double gapDelta = glucose_data.get(i).value - lastbg;
|
||||
//console.error(gapDelta, lastbg, elapsed_minutes);
|
||||
double nextbg = lastbg + (5 / elapsed_minutes * gapDelta);
|
||||
newBgreading.value = Math.round(nextbg);
|
||||
//console.error("Interpolated", bucketed_data[j]);
|
||||
bucketed_data.add(newBgreading);
|
||||
|
||||
elapsed_minutes = elapsed_minutes - 5;
|
||||
lastbg = nextbg;
|
||||
lastbgTime = nextbgTime;
|
||||
}
|
||||
} else if (Math.abs(elapsed_minutes) > 2) {
|
||||
j++;
|
||||
BgReading newBgreading = new BgReading();
|
||||
newBgreading.value = glucose_data.get(i).value;
|
||||
newBgreading.timeIndex = bgTime;
|
||||
bucketed_data.add(newBgreading);
|
||||
} else {
|
||||
bucketed_data.get(j).value = (bucketed_data.get(j).value + glucose_data.get(i).value) / 2;
|
||||
}
|
||||
}
|
||||
//console.error(bucketed_data);
|
||||
double[] avgDeltas = new double[bucketed_data.size() - 2];
|
||||
double[] bgis = new double[bucketed_data.size() - 2];
|
||||
double[] deviations = new double[bucketed_data.size() - 2];
|
||||
|
||||
String pastSensitivity = "";
|
||||
for (int i = 0; i < bucketed_data.size() - 3; ++i) {
|
||||
long bgTime = bucketed_data.get(i).timeIndex;
|
||||
int secondsFromMidnight = NSProfile.secondsFromMidnight(new Date(bgTime));
|
||||
|
||||
double sens = NSProfile.toMgdl(profile.getIsf(secondsFromMidnight), profile.getUnits());
|
||||
|
||||
//console.error(bgTime , bucketed_data[i].glucose);
|
||||
double bg;
|
||||
double avgDelta;
|
||||
double delta;
|
||||
bg = bucketed_data.get(i).value;
|
||||
if (bg < 40 || bucketed_data.get(i + 3).value < 40) {
|
||||
log.error("! value < 40");
|
||||
continue;
|
||||
}
|
||||
avgDelta = (bg - bucketed_data.get(i + 3).value) / 3;
|
||||
delta = (bg - bucketed_data.get(i + 1).value);
|
||||
|
||||
// avgDelta = avgDelta.toFixed(2);
|
||||
IobTotal iob = IobTotal.calulateFromTreatmentsAndTemps(bgTime);
|
||||
|
||||
double bgi = Math.round((-iob.activity * sens * 5) * 100) / 100d;
|
||||
// bgi = bgi.toFixed(2);
|
||||
//console.error(delta);
|
||||
double deviation = delta - bgi;
|
||||
// deviation = deviation.toFixed(2);
|
||||
//if (deviation < 0 && deviation > -2) { console.error("BG: "+bg+", avgDelta: "+avgDelta+", BGI: "+bgi+", deviation: "+deviation); }
|
||||
|
||||
// Exclude large positive deviations (carb absorption) from autosens
|
||||
if (avgDelta - bgi < 6) {
|
||||
if (deviation > 0) {
|
||||
pastSensitivity += "+";
|
||||
} else if (deviation == 0) {
|
||||
pastSensitivity += "=";
|
||||
} else {
|
||||
pastSensitivity += "-";
|
||||
}
|
||||
avgDeltas[i] = avgDelta;
|
||||
bgis[i] = bgi;
|
||||
deviations[i] = deviation;
|
||||
deviationSum += deviation;
|
||||
} else {
|
||||
pastSensitivity += ">";
|
||||
//console.error(bgTime);
|
||||
}
|
||||
//log.debug("TIME: " + new Date(bgTime).toString() + " BG: " + bg + " SENS: " + sens + " DELTA: " + delta + " AVGDELTA: " + avgDelta + " IOB: " + iob.iob + " ACTIVITY: " + iob.activity + " BGI: " + bgi + " DEVIATION: " + deviation);
|
||||
|
||||
// if bgTime is more recent than mealTime
|
||||
if (mealTime != null && bgTime > mealTime) {
|
||||
// figure out how many carbs that represents
|
||||
// but always assume at least 3mg/dL/5m (default) absorption
|
||||
double ci = Math.max(deviation, SafeParse.stringToDouble(SP.getString("openapsama_min_5m_carbimpact", "3.0")));
|
||||
double absorbed = ci * profile.getIc(secondsFromMidnight) / sens;
|
||||
// and add that to the running total carbsAbsorbed
|
||||
carbsAbsorbed += absorbed;
|
||||
}
|
||||
}
|
||||
|
||||
double ratio = 1;
|
||||
String ratioLimit = "";
|
||||
String sensResult = "";
|
||||
|
||||
if (mealTime == null) {
|
||||
//console.error("");
|
||||
log.debug(pastSensitivity);
|
||||
//console.log(JSON.stringify(avgDeltas));
|
||||
//console.log(JSON.stringify(bgis));
|
||||
Arrays.sort(avgDeltas);
|
||||
Arrays.sort(bgis);
|
||||
Arrays.sort(deviations);
|
||||
|
||||
for (double i = 0.9; i > 0.1; i = i - 0.02) {
|
||||
//console.error("p="+i.toFixed(2)+": "+percentile(avgDeltas, i).toFixed(2)+", "+percentile(bgis, i).toFixed(2)+", "+percentile(deviations, i).toFixed(2));
|
||||
if (percentile(deviations, (i + 0.02)) >= 0 && percentile(deviations, i) < 0) {
|
||||
//console.error("p="+i.toFixed(2)+": "+percentile(avgDeltas, i).toFixed(2)+", "+percentile(bgis, i).toFixed(2)+", "+percentile(deviations, i).toFixed(2));
|
||||
log.debug(Math.round(100 * i) + "% of non-meal deviations negative (target 45%-50%)");
|
||||
}
|
||||
}
|
||||
double pSensitive = percentile(deviations, 0.50);
|
||||
double pResistant = percentile(deviations, 0.45);
|
||||
//p30 = percentile(deviations, 0.3);
|
||||
|
||||
// average = deviationSum / deviations.length;
|
||||
|
||||
//console.error("Mean deviation: "+average.toFixed(2));
|
||||
double basalOff = 0;
|
||||
|
||||
if (pSensitive < 0) { // sensitive
|
||||
basalOff = pSensitive * (60 / 5) / NSProfile.toMgdl(profile.getIsf(NSProfile.secondsFromMidnight()), profile.getUnits());
|
||||
sensResult = "Excess insulin sensitivity detected";
|
||||
} else if (pResistant > 0) { // resistant
|
||||
basalOff = pResistant * (60 / 5) / NSProfile.toMgdl(profile.getIsf(NSProfile.secondsFromMidnight()), profile.getUnits());
|
||||
sensResult = "Excess insulin resistance detected";
|
||||
} else {
|
||||
sensResult = "Sensitivity normal";
|
||||
}
|
||||
log.debug(sensResult);
|
||||
ratio = 1 + (basalOff / profile.getMaxDailyBasal());
|
||||
|
||||
// don't adjust more than 1.5x
|
||||
double rawRatio = ratio;
|
||||
ratio = Math.max(ratio, SafeParse.stringToDouble(SP.getString("openapsama_autosens_min", "0.7")));
|
||||
ratio = Math.min(ratio, SafeParse.stringToDouble(SP.getString("openapsama_autosens_max", "1.2")));
|
||||
|
||||
if (ratio != rawRatio) {
|
||||
ratioLimit = "Ratio limited from " + rawRatio + " to " + ratio;
|
||||
log.debug(ratioLimit);
|
||||
}
|
||||
|
||||
double newisf = Math.round(NSProfile.toMgdl(profile.getIsf(NSProfile.secondsFromMidnight()), profile.getUnits()) / ratio);
|
||||
if (ratio != 1) {
|
||||
log.debug("ISF adjusted from " + NSProfile.toMgdl(profile.getIsf(NSProfile.secondsFromMidnight()), profile.getUnits()) + " to " + newisf);
|
||||
}
|
||||
//console.error("Basal adjustment "+basalOff.toFixed(2)+"U/hr");
|
||||
//console.error("Ratio: "+ratio*100+"%: new ISF: "+newisf.toFixed(1)+"mg/dL/U");
|
||||
}
|
||||
|
||||
AutosensResult output = new AutosensResult();
|
||||
output.ratio = Round.roundTo(ratio, 0.01);
|
||||
output.carbsAbsorbed = Round.roundTo(carbsAbsorbed, 0.01);
|
||||
output.pastSensitivity = pastSensitivity;
|
||||
output.ratioLimit = ratioLimit;
|
||||
output.sensResult = sensResult;
|
||||
return output;
|
||||
}
|
||||
|
||||
// From https://gist.github.com/IceCreamYou/6ffa1b18c4c8f6aeaad2
|
||||
// Returns the value at a given percentile in a sorted numeric array.
|
||||
// "Linear interpolation between closest ranks" method
|
||||
public static double percentile(double[] arr, double p) {
|
||||
if (arr.length == 0) return 0;
|
||||
if (p <= 0) return arr[0];
|
||||
if (p >= 1) return arr[arr.length - 1];
|
||||
|
||||
double index = arr.length * p,
|
||||
lower = Math.floor(index),
|
||||
upper = lower + 1,
|
||||
weight = index % 1;
|
||||
|
||||
if (upper >= arr.length) return arr[(int) lower];
|
||||
return arr[(int) lower] * (1 - weight) + arr[(int) upper] * weight;
|
||||
}
|
||||
|
||||
// Returns the percentile of the given value in a sorted numeric array.
|
||||
public static double percentRank(double[] arr, double v) {
|
||||
for (int i = 0, l = arr.length; i < l; i++) {
|
||||
if (v <= arr[i]) {
|
||||
while (i < l && v == arr[i]) i++;
|
||||
if (i == 0) return 0;
|
||||
if (v != arr[i - 1]) {
|
||||
i += (v - arr[i - 1]) / (arr[i] - arr[i - 1]);
|
||||
}
|
||||
return i / l;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package info.nightscout.androidaps.plugins.OpenAPSAMA;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
/**
|
||||
* Created by mike on 06.01.2017.
|
||||
*/
|
||||
public class AutosensResult {
|
||||
|
||||
//default values to show when autosens algorithm is not called
|
||||
public double ratio = 1d;
|
||||
public double carbsAbsorbed = 0d;
|
||||
public String sensResult = "autosens deactivated";
|
||||
public String pastSensitivity = "";
|
||||
public String ratioLimit = "";
|
||||
|
||||
public JSONObject json() {
|
||||
JSONObject ret = new JSONObject();
|
||||
try {
|
||||
ret.put("ratio", ratio);
|
||||
ret.put("ratioLimit", ratioLimit);
|
||||
ret.put("pastSensitivity", pastSensitivity);
|
||||
ret.put("sensResult", sensResult);
|
||||
ret.put("ratio", ratio);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,294 @@
|
|||
package info.nightscout.androidaps.plugins.OpenAPSAMA;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
|
||||
import com.eclipsesource.v8.JavaVoidCallback;
|
||||
import com.eclipsesource.v8.V8;
|
||||
import com.eclipsesource.v8.V8Array;
|
||||
import com.eclipsesource.v8.V8Object;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.Constants;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.data.GlucoseStatus;
|
||||
import info.nightscout.androidaps.data.MealData;
|
||||
import info.nightscout.androidaps.db.TempBasal;
|
||||
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.Loop.ScriptReader;
|
||||
import info.nightscout.androidaps.data.IobTotal;
|
||||
import info.nightscout.client.data.NSProfile;
|
||||
import info.nightscout.utils.SafeParse;
|
||||
|
||||
public class DetermineBasalAdapterAMAJS {
|
||||
private static Logger log = LoggerFactory.getLogger(DetermineBasalAdapterAMAJS.class);
|
||||
|
||||
|
||||
private ScriptReader mScriptReader = null;
|
||||
V8 mV8rt;
|
||||
private V8Object mProfile;
|
||||
private V8Object mGlucoseStatus;
|
||||
private V8Array mIobData;
|
||||
private V8Object mMealData;
|
||||
private V8Object mCurrentTemp;
|
||||
private V8Object mAutosensData = null;
|
||||
|
||||
private final String PARAM_currentTemp = "currentTemp";
|
||||
private final String PARAM_iobData = "iobData";
|
||||
private final String PARAM_glucoseStatus = "glucose_status";
|
||||
private final String PARAM_profile = "profile";
|
||||
private final String PARAM_meal_data = "meal_data";
|
||||
private final String PARAM_autosens_data = "autosens_data";
|
||||
|
||||
private String storedCurrentTemp = null;
|
||||
private String storedIobData = null;
|
||||
private String storedGlucoseStatus = null;
|
||||
private String storedProfile = null;
|
||||
private String storedMeal_data = null;
|
||||
private String storedAutosens_data = null;
|
||||
|
||||
private String scriptDebug = "";
|
||||
|
||||
/**
|
||||
* Main code
|
||||
*/
|
||||
|
||||
public DetermineBasalAdapterAMAJS(ScriptReader scriptReader) throws IOException {
|
||||
mV8rt = V8.createV8Runtime();
|
||||
mScriptReader = scriptReader;
|
||||
|
||||
initLogCallback();
|
||||
initProcessExitCallback();
|
||||
initModuleParent();
|
||||
loadScript();
|
||||
}
|
||||
|
||||
public DetermineBasalResultAMA invoke() {
|
||||
|
||||
log.debug(">>> Invoking detemine_basal <<<");
|
||||
log.debug("Glucose status: " + (storedGlucoseStatus = mV8rt.executeStringScript("JSON.stringify(" + PARAM_glucoseStatus + ");")));
|
||||
log.debug("IOB data: " + (storedIobData = mV8rt.executeStringScript("JSON.stringify(" + PARAM_iobData + ");")));
|
||||
log.debug("Current temp: " + (storedCurrentTemp = mV8rt.executeStringScript("JSON.stringify(" + PARAM_currentTemp + ");")));
|
||||
log.debug("Profile: " + (storedProfile = mV8rt.executeStringScript("JSON.stringify(" + PARAM_profile + ");")));
|
||||
log.debug("Meal data: " + (storedMeal_data = mV8rt.executeStringScript("JSON.stringify(" + PARAM_meal_data + ");")));
|
||||
if (mAutosensData != null)
|
||||
log.debug("Autosens data: " + (storedAutosens_data = mV8rt.executeStringScript("JSON.stringify(" + PARAM_autosens_data + ");")));
|
||||
else
|
||||
log.debug("Autosens data: " + (storedAutosens_data = "undefined"));
|
||||
|
||||
mV8rt.executeVoidScript(
|
||||
"var rT = determine_basal(" +
|
||||
PARAM_glucoseStatus + ", " +
|
||||
PARAM_currentTemp + ", " +
|
||||
PARAM_iobData + ", " +
|
||||
PARAM_profile + ", " +
|
||||
PARAM_autosens_data + ", " +
|
||||
PARAM_meal_data + ", " +
|
||||
"tempBasalFunctions" +
|
||||
");");
|
||||
|
||||
|
||||
String ret = mV8rt.executeStringScript("JSON.stringify(rT);");
|
||||
log.debug("Result: " + ret);
|
||||
|
||||
V8Object v8ObjectReuslt = mV8rt.getObject("rT");
|
||||
|
||||
DetermineBasalResultAMA result = null;
|
||||
try {
|
||||
result = new DetermineBasalResultAMA(v8ObjectReuslt, new JSONObject(ret));
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
String getGlucoseStatusParam() {
|
||||
return storedGlucoseStatus;
|
||||
}
|
||||
|
||||
String getCurrentTempParam() {
|
||||
return storedCurrentTemp;
|
||||
}
|
||||
|
||||
String getIobDataParam() {
|
||||
return storedIobData;
|
||||
}
|
||||
|
||||
String getProfileParam() {
|
||||
return storedProfile;
|
||||
}
|
||||
|
||||
String getMealDataParam() {
|
||||
return storedMeal_data;
|
||||
}
|
||||
|
||||
String getAutosensDataParam() {
|
||||
return storedAutosens_data;
|
||||
}
|
||||
|
||||
String getScriptDebug() {
|
||||
return scriptDebug;
|
||||
}
|
||||
|
||||
private void loadScript() throws IOException {
|
||||
mV8rt.executeVoidScript("var round_basal = function round_basal(basal, profile) { return basal; };");
|
||||
mV8rt.executeVoidScript("require = function() {return round_basal;};");
|
||||
|
||||
mV8rt.executeVoidScript(readFile("OpenAPSAMA/basal-set-temp.js"), "OpenAPSAMA/basal-set-temp.js ", 0);
|
||||
mV8rt.executeVoidScript("var tempBasalFunctions = module.exports;");
|
||||
|
||||
mV8rt.executeVoidScript(
|
||||
readFile("OpenAPSAMA/determine-basal.js"),
|
||||
"OpenAPSAMA/determine-basal.js",
|
||||
0);
|
||||
mV8rt.executeVoidScript("var determine_basal = module.exports;");
|
||||
}
|
||||
|
||||
private void initModuleParent() {
|
||||
mV8rt.executeVoidScript("var module = {\"parent\":Boolean(1)};");
|
||||
}
|
||||
|
||||
private void initProcessExitCallback() {
|
||||
JavaVoidCallback callbackProccessExit = new JavaVoidCallback() {
|
||||
@Override
|
||||
public void invoke(V8Object arg0, V8Array parameters) {
|
||||
if (parameters.length() > 0) {
|
||||
Object arg1 = parameters.get(0);
|
||||
log.error("ProccessExit " + arg1);
|
||||
}
|
||||
}
|
||||
};
|
||||
mV8rt.registerJavaMethod(callbackProccessExit, "proccessExit");
|
||||
mV8rt.executeVoidScript("var process = {\"exit\": function () { proccessExit(); } };");
|
||||
}
|
||||
|
||||
private void initLogCallback() {
|
||||
JavaVoidCallback callbackLog = new JavaVoidCallback() {
|
||||
@Override
|
||||
public void invoke(V8Object arg0, V8Array parameters) {
|
||||
int i = 0;
|
||||
String s = "";
|
||||
while (i < parameters.length()) {
|
||||
Object arg = parameters.get(i);
|
||||
s += arg + " ";
|
||||
i++;
|
||||
}
|
||||
if (!s.equals("") && Config.logAPSResult) {
|
||||
log.debug("Script debug: " + s);
|
||||
scriptDebug += s + "\n";
|
||||
}
|
||||
}
|
||||
};
|
||||
mV8rt.registerJavaMethod(callbackLog, "log");
|
||||
mV8rt.executeVoidScript("var console = {\"log\":log, \"error\":log};");
|
||||
}
|
||||
|
||||
|
||||
public void setData(NSProfile profile,
|
||||
double maxIob,
|
||||
double maxBasal,
|
||||
double minBg,
|
||||
double maxBg,
|
||||
double targetBg,
|
||||
PumpInterface pump,
|
||||
IobTotal[] iobArray,
|
||||
GlucoseStatus glucoseStatus,
|
||||
MealData mealData,
|
||||
double autosensDataRatio,
|
||||
boolean tempTargetSet,
|
||||
double min_5m_carbimpact) {
|
||||
|
||||
String units = profile.getUnits();
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
|
||||
|
||||
mProfile = new V8Object(mV8rt);
|
||||
mProfile.add("max_iob", maxIob);
|
||||
mProfile.add("dia", profile.getDia());
|
||||
mProfile.add("type", "current");
|
||||
mProfile.add("max_daily_basal", profile.getMaxDailyBasal());
|
||||
mProfile.add("max_basal", maxBasal);
|
||||
mProfile.add("min_bg", minBg);
|
||||
mProfile.add("max_bg", maxBg);
|
||||
mProfile.add("target_bg", targetBg);
|
||||
mProfile.add("carb_ratio", profile.getIc(profile.secondsFromMidnight()));
|
||||
mProfile.add("sens", NSProfile.toMgdl(profile.getIsf(NSProfile.secondsFromMidnight()).doubleValue(), units));
|
||||
mProfile.add("max_daily_safety_multiplier", SafeParse.stringToInt(preferences.getString("openapsama_max_daily_safety_multiplier", "3")));
|
||||
mProfile.add("current_basal_safety_multiplier", SafeParse.stringToInt(preferences.getString("openapsama_current_basal_safety_multiplier", "4")));
|
||||
mProfile.add("skip_neutral_temps", true);
|
||||
mProfile.add("current_basal", pump.getBaseBasalRate());
|
||||
mProfile.add("temptargetSet", tempTargetSet);
|
||||
mProfile.add("autosens_adjust_targets", preferences.getBoolean("openapsama_autosens_adjusttargets", true));
|
||||
mProfile.add("min_5m_carbimpact", SafeParse.stringToDouble(preferences.getString("openapsama_min_5m_carbimpact", "3.0")));
|
||||
mV8rt.add(PARAM_profile, mProfile);
|
||||
|
||||
mCurrentTemp = new V8Object(mV8rt);
|
||||
mCurrentTemp.add("temp", "absolute");
|
||||
mCurrentTemp.add("duration", pump.getTempBasalRemainingMinutes());
|
||||
mCurrentTemp.add("rate", pump.getTempBasalAbsoluteRate());
|
||||
|
||||
// as we have non default temps longer than 30 mintues
|
||||
TempBasal tempBasal = pump.getTempBasal();
|
||||
if(tempBasal != null){
|
||||
mCurrentTemp.add("minutesrunning", tempBasal.getRealDuration());
|
||||
}
|
||||
|
||||
mV8rt.add(PARAM_currentTemp, mCurrentTemp);
|
||||
|
||||
mIobData = mV8rt.executeArrayScript(IobTotal.convertToJSONArray(iobArray).toString());
|
||||
mV8rt.add(PARAM_iobData, mIobData);
|
||||
|
||||
mGlucoseStatus = new V8Object(mV8rt);
|
||||
mGlucoseStatus.add("glucose", glucoseStatus.glucose);
|
||||
mGlucoseStatus.add("delta", glucoseStatus.delta);
|
||||
mGlucoseStatus.add("short_avgdelta", glucoseStatus.short_avgdelta);
|
||||
mGlucoseStatus.add("long_avgdelta", glucoseStatus.long_avgdelta);
|
||||
mV8rt.add(PARAM_glucoseStatus, mGlucoseStatus);
|
||||
|
||||
mMealData = new V8Object(mV8rt);
|
||||
mMealData.add("carbs", mealData.carbs);
|
||||
mMealData.add("boluses", mealData.boluses);
|
||||
mMealData.add("mealCOB", mealData.mealCOB);
|
||||
mV8rt.add(PARAM_meal_data, mMealData);
|
||||
|
||||
if (MainApp.getConfigBuilder().isAMAModeEnabled()) {
|
||||
mAutosensData = new V8Object(mV8rt);
|
||||
mAutosensData.add("ratio", autosensDataRatio);
|
||||
mV8rt.add(PARAM_autosens_data, mAutosensData);
|
||||
} else {
|
||||
mV8rt.addUndefined(PARAM_autosens_data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void release() {
|
||||
mProfile.release();
|
||||
mCurrentTemp.release();
|
||||
mIobData.release();
|
||||
mMealData.release();
|
||||
mGlucoseStatus.release();
|
||||
if (mAutosensData != null) {
|
||||
mAutosensData.release();
|
||||
}
|
||||
mV8rt.release();
|
||||
}
|
||||
|
||||
public String readFile(String filename) throws IOException {
|
||||
byte[] bytes = mScriptReader.readFile(filename);
|
||||
String string = new String(bytes, "UTF-8");
|
||||
if (string.startsWith("#!/usr/bin/env node")) {
|
||||
string = string.substring(20);
|
||||
}
|
||||
return string;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,159 @@
|
|||
package info.nightscout.androidaps.plugins.OpenAPSAMA;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import com.eclipsesource.v8.V8Object;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import info.nightscout.androidaps.db.BgReading;
|
||||
import info.nightscout.androidaps.plugins.Loop.APSResult;
|
||||
import info.nightscout.androidaps.data.IobTotal;
|
||||
|
||||
public class DetermineBasalResultAMA extends APSResult {
|
||||
public Date date;
|
||||
public JSONObject json = new JSONObject();
|
||||
public double eventualBG;
|
||||
public double snoozeBG;
|
||||
public IobTotal iob;
|
||||
|
||||
public DetermineBasalResultAMA(V8Object result, JSONObject j) {
|
||||
date = new Date();
|
||||
json = j;
|
||||
if (result.contains("error")) {
|
||||
reason = result.getString("error");
|
||||
changeRequested = false;
|
||||
rate = -1;
|
||||
duration = -1;
|
||||
} else {
|
||||
reason = result.getString("reason");
|
||||
if (result.contains("eventualBG")) eventualBG = result.getDouble("eventualBG");
|
||||
if (result.contains("snoozeBG")) snoozeBG = result.getDouble("snoozeBG");
|
||||
if (result.contains("rate")) {
|
||||
rate = result.getDouble("rate");
|
||||
if (rate < 0d) rate = 0d;
|
||||
changeRequested = true;
|
||||
} else {
|
||||
rate = -1;
|
||||
changeRequested = false;
|
||||
}
|
||||
if (result.contains("duration")) {
|
||||
duration = result.getInteger("duration");
|
||||
changeRequested = changeRequested;
|
||||
} else {
|
||||
duration = -1;
|
||||
changeRequested = false;
|
||||
}
|
||||
}
|
||||
result.release();
|
||||
}
|
||||
|
||||
public DetermineBasalResultAMA() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public DetermineBasalResultAMA clone() {
|
||||
DetermineBasalResultAMA newResult = new DetermineBasalResultAMA();
|
||||
newResult.reason = new String(reason);
|
||||
newResult.rate = rate;
|
||||
newResult.duration = duration;
|
||||
newResult.changeRequested = changeRequested;
|
||||
newResult.rate = rate;
|
||||
newResult.duration = duration;
|
||||
newResult.changeRequested = changeRequested;
|
||||
|
||||
try {
|
||||
newResult.json = new JSONObject(json.toString());
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
newResult.eventualBG = eventualBG;
|
||||
newResult.snoozeBG = snoozeBG;
|
||||
newResult.date = date;
|
||||
return newResult;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject json() {
|
||||
try {
|
||||
JSONObject ret = new JSONObject(this.json.toString());
|
||||
return ret;
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<BgReading> getPredictions() {
|
||||
List<BgReading> array = new ArrayList<>();
|
||||
try {
|
||||
long startTime = date.getTime();
|
||||
if (json.has("predBGs")) {
|
||||
JSONObject predBGs = json.getJSONObject("predBGs");
|
||||
if (predBGs.has("IOB")) {
|
||||
JSONArray iob = predBGs.getJSONArray("IOB");
|
||||
for (int i = 1; i < iob.length(); i ++) {
|
||||
BgReading bg = new BgReading();
|
||||
bg.value = iob.getInt(i);
|
||||
bg.timeIndex = startTime + i * 5 * 60 * 1000L;
|
||||
array.add(bg);
|
||||
}
|
||||
}
|
||||
if (predBGs.has("aCOB")) {
|
||||
JSONArray iob = predBGs.getJSONArray("aCOB");
|
||||
for (int i = 1; i < iob.length(); i ++) {
|
||||
BgReading bg = new BgReading();
|
||||
bg.value = iob.getInt(i);
|
||||
bg.timeIndex = startTime + i * 5 * 60 * 1000L;
|
||||
array.add(bg);
|
||||
}
|
||||
}
|
||||
if (predBGs.has("COB")) {
|
||||
JSONArray iob = predBGs.getJSONArray("COB");
|
||||
for (int i = 1; i < iob.length(); i ++) {
|
||||
BgReading bg = new BgReading();
|
||||
bg.value = iob.getInt(i);
|
||||
bg.timeIndex = startTime + i * 5 * 60 * 1000L;
|
||||
array.add(bg);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
public long getLatestPredictionsTime() {
|
||||
long latest = 0;
|
||||
try {
|
||||
long startTime = date.getTime();
|
||||
if (json.has("predBGs")) {
|
||||
JSONObject predBGs = json.getJSONObject("predBGs");
|
||||
if (predBGs.has("IOB")) {
|
||||
JSONArray iob = predBGs.getJSONArray("IOB");
|
||||
latest = Math.max(latest, startTime + (iob.length() - 1) * 5 * 60 * 1000L);
|
||||
}
|
||||
if (predBGs.has("aCOB")) {
|
||||
JSONArray iob = predBGs.getJSONArray("aCOB");
|
||||
latest = Math.max(latest, startTime + (iob.length() - 1) * 5 * 60 * 1000L);
|
||||
}
|
||||
if (predBGs.has("COB")) {
|
||||
JSONArray iob = predBGs.getJSONArray("COB");
|
||||
latest = Math.max(latest, startTime + (iob.length() - 1) * 5 * 60 * 1000L);
|
||||
}
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return latest;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,159 @@
|
|||
package info.nightscout.androidaps.plugins.OpenAPSAMA;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.squareup.otto.Subscribe;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.interfaces.FragmentBase;
|
||||
import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateGui;
|
||||
import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateResultGui;
|
||||
import info.nightscout.utils.JSONFormatter;
|
||||
|
||||
public class OpenAPSAMAFragment extends Fragment implements View.OnClickListener, FragmentBase {
|
||||
private static Logger log = LoggerFactory.getLogger(OpenAPSAMAFragment.class);
|
||||
|
||||
private static OpenAPSAMAPlugin openAPSAMAPlugin;
|
||||
|
||||
public static OpenAPSAMAPlugin getPlugin() {
|
||||
if(openAPSAMAPlugin ==null){
|
||||
openAPSAMAPlugin = new OpenAPSAMAPlugin();
|
||||
}
|
||||
return openAPSAMAPlugin;
|
||||
}
|
||||
|
||||
Button run;
|
||||
TextView lastRunView;
|
||||
TextView glucoseStatusView;
|
||||
TextView currentTempView;
|
||||
TextView iobDataView;
|
||||
TextView profileView;
|
||||
TextView mealDataView;
|
||||
TextView autosensDataView;
|
||||
TextView resultView;
|
||||
TextView scriptdebugView;
|
||||
TextView requestView;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.openapsama_fragment, container, false);
|
||||
|
||||
run = (Button) view.findViewById(R.id.openapsma_run);
|
||||
run.setOnClickListener(this);
|
||||
lastRunView = (TextView) view.findViewById(R.id.openapsma_lastrun);
|
||||
glucoseStatusView = (TextView) view.findViewById(R.id.openapsma_glucosestatus);
|
||||
currentTempView = (TextView) view.findViewById(R.id.openapsma_currenttemp);
|
||||
iobDataView = (TextView) view.findViewById(R.id.openapsma_iobdata);
|
||||
profileView = (TextView) view.findViewById(R.id.openapsma_profile);
|
||||
mealDataView = (TextView) view.findViewById(R.id.openapsma_mealdata);
|
||||
autosensDataView = (TextView) view.findViewById(R.id.openapsma_autosensdata);
|
||||
scriptdebugView = (TextView) view.findViewById(R.id.openapsma_scriptdebugdata);
|
||||
resultView = (TextView) view.findViewById(R.id.openapsma_result);
|
||||
requestView = (TextView) view.findViewById(R.id.openapsma_request);
|
||||
|
||||
updateGUI();
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
switch (view.getId()) {
|
||||
case R.id.openapsma_run:
|
||||
getPlugin().invoke("OpenAPSAMA button");
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@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 EventOpenAPSUpdateGui ev) {
|
||||
updateGUI();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onStatusEvent(final EventOpenAPSUpdateResultGui ev) {
|
||||
updateResultGUI(ev.text);
|
||||
}
|
||||
|
||||
void updateGUI() {
|
||||
Activity activity = getActivity();
|
||||
if (activity != null)
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
DetermineBasalResultAMA lastAPSResult = getPlugin().lastAPSResult;
|
||||
if (lastAPSResult != null) {
|
||||
resultView.setText(JSONFormatter.format(lastAPSResult.json));
|
||||
requestView.setText(lastAPSResult.toSpanned());
|
||||
}
|
||||
DetermineBasalAdapterAMAJS determineBasalAdapterAMAJS = getPlugin().lastDetermineBasalAdapterAMAJS;
|
||||
if (determineBasalAdapterAMAJS != null) {
|
||||
glucoseStatusView.setText(JSONFormatter.format(determineBasalAdapterAMAJS.getGlucoseStatusParam()));
|
||||
currentTempView.setText(JSONFormatter.format(determineBasalAdapterAMAJS.getCurrentTempParam()));
|
||||
try {
|
||||
JSONArray iobArray = new JSONArray(determineBasalAdapterAMAJS.getIobDataParam());
|
||||
iobDataView.setText(String.format(MainApp.sResources.getString(R.string.array_of_elements), iobArray.length()) + "\n" + JSONFormatter.format(iobArray.getString(0)));
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
iobDataView.setText("JSONException");
|
||||
}
|
||||
profileView.setText(JSONFormatter.format(determineBasalAdapterAMAJS.getProfileParam()));
|
||||
mealDataView.setText(JSONFormatter.format(determineBasalAdapterAMAJS.getMealDataParam()));
|
||||
scriptdebugView.setText(determineBasalAdapterAMAJS.getScriptDebug());
|
||||
}
|
||||
if (getPlugin().lastAPSRun != null) {
|
||||
lastRunView.setText(getPlugin().lastAPSRun.toLocaleString());
|
||||
}
|
||||
if (getPlugin().lastAutosensResult != null) {
|
||||
autosensDataView.setText(JSONFormatter.format(getPlugin().lastAutosensResult.json()));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void updateResultGUI(final String text) {
|
||||
Activity activity = getActivity();
|
||||
if (activity != null)
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
resultView.setText(text);
|
||||
glucoseStatusView.setText("");
|
||||
currentTempView.setText("");
|
||||
iobDataView.setText("");
|
||||
profileView.setText("");
|
||||
mealDataView.setText("");
|
||||
autosensDataView.setText("");
|
||||
scriptdebugView.setText("");
|
||||
requestView.setText("");
|
||||
lastRunView.setText("");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,293 @@
|
|||
package info.nightscout.androidaps.plugins.OpenAPSAMA;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.Constants;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.data.GlucoseStatus;
|
||||
import info.nightscout.androidaps.data.MealData;
|
||||
import info.nightscout.androidaps.db.BgReading;
|
||||
import info.nightscout.androidaps.db.TempTarget;
|
||||
import info.nightscout.androidaps.interfaces.APSInterface;
|
||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||
import info.nightscout.androidaps.interfaces.TempBasalsInterface;
|
||||
import info.nightscout.androidaps.plugins.Loop.APSResult;
|
||||
import info.nightscout.androidaps.plugins.Loop.ScriptReader;
|
||||
import info.nightscout.androidaps.data.IobTotal;
|
||||
import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateGui;
|
||||
import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateResultGui;
|
||||
import info.nightscout.androidaps.plugins.TempTargetRange.TempTargetRangePlugin;
|
||||
import info.nightscout.client.data.NSProfile;
|
||||
import info.nightscout.utils.DateUtil;
|
||||
import info.nightscout.utils.Profiler;
|
||||
import info.nightscout.utils.Round;
|
||||
import info.nightscout.utils.SafeParse;
|
||||
import info.nightscout.utils.ToastUtils;
|
||||
|
||||
/**
|
||||
* Created by mike on 05.08.2016.
|
||||
*/
|
||||
public class OpenAPSAMAPlugin implements PluginBase, APSInterface {
|
||||
private static Logger log = LoggerFactory.getLogger(OpenAPSAMAPlugin.class);
|
||||
|
||||
// last values
|
||||
DetermineBasalAdapterAMAJS lastDetermineBasalAdapterAMAJS = null;
|
||||
Date lastAPSRun = null;
|
||||
DetermineBasalResultAMA lastAPSResult = null;
|
||||
AutosensResult lastAutosensResult = null;
|
||||
|
||||
boolean fragmentEnabled = false;
|
||||
boolean fragmentVisible = true;
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return MainApp.instance().getString(R.string.openapsama);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNameShort() {
|
||||
String name = MainApp.sResources.getString(R.string.oaps_shortname);
|
||||
if (!name.trim().isEmpty()){
|
||||
//only if translation exists
|
||||
return name;
|
||||
}
|
||||
// use long name as fallback
|
||||
return getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(int type) {
|
||||
return type == APS && fragmentEnabled && MainApp.getConfigBuilder().getPumpDescription().isTempBasalCapable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVisibleInTabs(int type) {
|
||||
return type == APS && fragmentVisible && MainApp.getConfigBuilder().getPumpDescription().isTempBasalCapable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeHidden(int type) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFragmentVisible(int type, boolean fragmentVisible) {
|
||||
if (type == APS) this.fragmentVisible = fragmentVisible;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
|
||||
if (type == APS) this.fragmentEnabled = fragmentEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getType() {
|
||||
return PluginBase.APS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFragmentClass() {
|
||||
return OpenAPSAMAFragment.class.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public APSResult getLastAPSResult() {
|
||||
return lastAPSResult;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date getLastAPSRun() {
|
||||
return lastAPSRun;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(String initiator) {
|
||||
log.debug("invoke from " + initiator);
|
||||
lastAPSResult = null;
|
||||
DetermineBasalAdapterAMAJS determineBasalAdapterAMAJS = null;
|
||||
try {
|
||||
determineBasalAdapterAMAJS = new DetermineBasalAdapterAMAJS(new ScriptReader(MainApp.instance().getBaseContext()));
|
||||
} catch (IOException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
return;
|
||||
}
|
||||
|
||||
GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData();
|
||||
NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile();
|
||||
PumpInterface pump = MainApp.getConfigBuilder();
|
||||
|
||||
if (!isEnabled(PluginBase.APS)) {
|
||||
MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.instance().getString(R.string.openapsma_disabled)));
|
||||
if (Config.logAPSResult)
|
||||
log.debug(MainApp.instance().getString(R.string.openapsma_disabled));
|
||||
return;
|
||||
}
|
||||
|
||||
if (glucoseStatus == null) {
|
||||
MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.instance().getString(R.string.openapsma_noglucosedata)));
|
||||
if (Config.logAPSResult)
|
||||
log.debug(MainApp.instance().getString(R.string.openapsma_noglucosedata));
|
||||
return;
|
||||
}
|
||||
|
||||
if (profile == null) {
|
||||
MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.instance().getString(R.string.openapsma_noprofile)));
|
||||
if (Config.logAPSResult)
|
||||
log.debug(MainApp.instance().getString(R.string.openapsma_noprofile));
|
||||
return;
|
||||
}
|
||||
|
||||
if (pump == null) {
|
||||
MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.instance().getString(R.string.openapsma_nopump)));
|
||||
if (Config.logAPSResult)
|
||||
log.debug(MainApp.instance().getString(R.string.openapsma_nopump));
|
||||
return;
|
||||
}
|
||||
|
||||
SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
|
||||
String units = profile.getUnits();
|
||||
|
||||
String maxBgDefault = Constants.MAX_BG_DEFAULT_MGDL;
|
||||
String minBgDefault = Constants.MIN_BG_DEFAULT_MGDL;
|
||||
String targetBgDefault = Constants.TARGET_BG_DEFAULT_MGDL;
|
||||
if (!units.equals(Constants.MGDL)) {
|
||||
maxBgDefault = Constants.MAX_BG_DEFAULT_MMOL;
|
||||
minBgDefault = Constants.MIN_BG_DEFAULT_MMOL;
|
||||
targetBgDefault = Constants.TARGET_BG_DEFAULT_MMOL;
|
||||
}
|
||||
|
||||
Date now = new Date();
|
||||
|
||||
double maxIob = SafeParse.stringToDouble(SP.getString("openapsma_max_iob", "1.5"));
|
||||
double maxBasal = SafeParse.stringToDouble(SP.getString("openapsma_max_basal", "1"));
|
||||
double minBg = NSProfile.toMgdl(SafeParse.stringToDouble(SP.getString("openapsma_min_bg", minBgDefault)), units);
|
||||
double maxBg = NSProfile.toMgdl(SafeParse.stringToDouble(SP.getString("openapsma_max_bg", maxBgDefault)), units);
|
||||
double targetBg = NSProfile.toMgdl(SafeParse.stringToDouble(SP.getString("openapsma_target_bg", targetBgDefault)), units);
|
||||
|
||||
minBg = Round.roundTo(minBg, 0.1d);
|
||||
maxBg = Round.roundTo(maxBg, 0.1d);
|
||||
|
||||
Date start = new Date();
|
||||
Date startPart = new Date();
|
||||
IobTotal[] iobArray = IobTotal.calculateIobArrayInDia();
|
||||
Profiler.log(log, "calculateIobArrayInDia()", startPart);
|
||||
|
||||
startPart = new Date();
|
||||
MealData mealData = MainApp.getConfigBuilder().getActiveTreatments().getMealData();
|
||||
Profiler.log(log, "getMealData()", startPart);
|
||||
|
||||
maxIob = MainApp.getConfigBuilder().applyMaxIOBConstraints(maxIob);
|
||||
|
||||
minBg = verifyHardLimits(minBg, "minBg", Constants.VERY_HARD_LIMIT_MIN_BG[0], Constants.VERY_HARD_LIMIT_MIN_BG[1]);
|
||||
maxBg = verifyHardLimits(maxBg, "maxBg", Constants.VERY_HARD_LIMIT_MAX_BG[0], Constants.VERY_HARD_LIMIT_MAX_BG[1]);
|
||||
targetBg = verifyHardLimits(targetBg, "targetBg", Constants.VERY_HARD_LIMIT_TARGET_BG[0], Constants.VERY_HARD_LIMIT_TARGET_BG[1]);
|
||||
|
||||
boolean isTempTarget = false;
|
||||
TempTargetRangePlugin tempTargetRangePlugin = (TempTargetRangePlugin) MainApp.getSpecificPlugin(TempTargetRangePlugin.class);
|
||||
if (tempTargetRangePlugin != null && tempTargetRangePlugin.isEnabled(PluginBase.GENERAL)) {
|
||||
TempTarget tempTarget = tempTargetRangePlugin.getTempTargetInProgress(new Date().getTime());
|
||||
if (tempTarget != null) {
|
||||
isTempTarget = true;
|
||||
minBg = verifyHardLimits(tempTarget.low, "minBg", Constants.VERY_HARD_LIMIT_TEMP_MIN_BG[0], Constants.VERY_HARD_LIMIT_TEMP_MIN_BG[1]);
|
||||
maxBg = verifyHardLimits(tempTarget.high, "maxBg", Constants.VERY_HARD_LIMIT_TEMP_MAX_BG[0], Constants.VERY_HARD_LIMIT_TEMP_MAX_BG[1]);
|
||||
targetBg = verifyHardLimits((tempTarget.low + tempTarget.high) / 2, "targetBg", Constants.VERY_HARD_LIMIT_TEMP_TARGET_BG[0], Constants.VERY_HARD_LIMIT_TEMP_TARGET_BG[1]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
maxIob = verifyHardLimits(maxIob, "maxIob", 0, 7);
|
||||
maxBasal = verifyHardLimits(maxBasal, "max_basal", 0.1, 10);
|
||||
|
||||
if (!checkOnlyHardLimits(profile.getDia(), "dia", 2, 7)) return;
|
||||
if (!checkOnlyHardLimits(profile.getIc(profile.secondsFromMidnight()), "carbratio", 2, 100)) return;
|
||||
if (!checkOnlyHardLimits(NSProfile.toMgdl(profile.getIsf(NSProfile.secondsFromMidnight()).doubleValue(), units), "sens", 2, 900)) return;
|
||||
if (!checkOnlyHardLimits(profile.getMaxDailyBasal(), "max_daily_basal", 0.1, 10)) return;
|
||||
if (!checkOnlyHardLimits(pump.getBaseBasalRate(), "current_basal", 0.01, 5)) return;
|
||||
|
||||
startPart = new Date();
|
||||
long oldestDataAvailable = MainApp.getConfigBuilder().getActiveTempBasals().oldestDataAvaialable();
|
||||
List<BgReading> bgReadings = MainApp.getDbHelper().getBgreadingsDataFromTime(Math.max(oldestDataAvailable, (long) (new Date().getTime() - 60 * 60 * 1000L * (24 + profile.getDia()))), false);
|
||||
log.debug("Limiting data to oldest available temps: " + new Date(oldestDataAvailable).toString() + " (" + bgReadings.size() + " records)");
|
||||
Profiler.log(log, "getBgreadingsDataFromTime()", startPart);
|
||||
|
||||
startPart = new Date();
|
||||
if(MainApp.getConfigBuilder().isAMAModeEnabled()){
|
||||
lastAutosensResult = Autosens.detectSensitivityandCarbAbsorption(bgReadings, null);
|
||||
} else {
|
||||
lastAutosensResult = new AutosensResult();
|
||||
}
|
||||
Profiler.log(log, "detectSensitivityandCarbAbsorption()", startPart);
|
||||
Profiler.log(log, "AMA data gathering", start);
|
||||
|
||||
start = new Date();
|
||||
determineBasalAdapterAMAJS.setData(profile, maxIob, maxBasal, minBg, maxBg, targetBg, pump, iobArray, glucoseStatus, mealData,
|
||||
lastAutosensResult.ratio, //autosensDataRatio
|
||||
isTempTarget,
|
||||
SafeParse.stringToDouble(SP.getString("openapsama_min_5m_carbimpact", "3.0"))//min_5m_carbimpact
|
||||
);
|
||||
|
||||
|
||||
DetermineBasalResultAMA determineBasalResultAMA = determineBasalAdapterAMAJS.invoke();
|
||||
Profiler.log(log, "AMA calculation", start);
|
||||
// Fix bug determine basal
|
||||
if (determineBasalResultAMA.rate == 0d && determineBasalResultAMA.duration == 0 && !MainApp.getConfigBuilder().isTempBasalInProgress())
|
||||
determineBasalResultAMA.changeRequested = false;
|
||||
// limit requests on openloop mode
|
||||
if (!MainApp.getConfigBuilder().isClosedModeEnabled()) {
|
||||
if (MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultAMA.rate - MainApp.getConfigBuilder().getTempBasalAbsoluteRate()) < 0.1)
|
||||
determineBasalResultAMA.changeRequested = false;
|
||||
if (!MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultAMA.rate - MainApp.getConfigBuilder().getBaseBasalRate()) < 0.1)
|
||||
determineBasalResultAMA.changeRequested = false;
|
||||
}
|
||||
|
||||
determineBasalResultAMA.iob = iobArray[0];
|
||||
|
||||
determineBasalAdapterAMAJS.release();
|
||||
|
||||
try {
|
||||
determineBasalResultAMA.json.put("timestamp", DateUtil.toISOString(now));
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
lastDetermineBasalAdapterAMAJS = determineBasalAdapterAMAJS;
|
||||
lastAPSResult = determineBasalResultAMA;
|
||||
lastAPSRun = now;
|
||||
MainApp.bus().post(new EventOpenAPSUpdateGui());
|
||||
|
||||
//deviceStatus.suggested = determineBasalResultAMA.json;
|
||||
}
|
||||
|
||||
// safety checks
|
||||
public static boolean checkOnlyHardLimits(Double value, String valueName, double lowLimit, double highLimit) {
|
||||
return value.equals(verifyHardLimits(value, valueName, lowLimit, highLimit));
|
||||
}
|
||||
|
||||
public static Double verifyHardLimits(Double value, String valueName, double lowLimit, double highLimit) {
|
||||
Double newvalue = value;
|
||||
if (newvalue < lowLimit || newvalue > highLimit) {
|
||||
newvalue = Math.max(newvalue, lowLimit);
|
||||
newvalue = Math.min(newvalue, highLimit);
|
||||
String msg = String.format(MainApp.sResources.getString(R.string.openapsma_valueoutofrange), valueName);
|
||||
msg += ".\n";
|
||||
msg += String.format(MainApp.sResources.getString(R.string.openapsma_valuelimitedto), value, newvalue);
|
||||
log.error(msg);
|
||||
MainApp.getConfigBuilder().uploadError(msg);
|
||||
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), msg, R.raw.error);
|
||||
}
|
||||
return newvalue;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,8 +1,5 @@
|
|||
package info.nightscout.androidaps.plugins.OpenAPSMA;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import com.eclipsesource.v8.JavaVoidCallback;
|
||||
import com.eclipsesource.v8.V8;
|
||||
import com.eclipsesource.v8.V8Array;
|
||||
|
@ -16,15 +13,15 @@ import org.slf4j.LoggerFactory;
|
|||
import java.io.IOException;
|
||||
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.data.GlucoseStatus;
|
||||
import info.nightscout.androidaps.data.IobTotal;
|
||||
import info.nightscout.androidaps.data.MealData;
|
||||
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||
import info.nightscout.androidaps.db.DatabaseHelper;
|
||||
import info.nightscout.androidaps.plugins.Loop.ScriptReader;
|
||||
import info.nightscout.androidaps.plugins.Treatments.TreatmentsFragment;
|
||||
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
|
||||
import info.nightscout.client.data.NSProfile;
|
||||
|
||||
public class DetermineBasalAdapterJS implements Parcelable {
|
||||
private static Logger log = LoggerFactory.getLogger(DetermineBasalAdapterJS.class);
|
||||
public class DetermineBasalAdapterMAJS {
|
||||
private static Logger log = LoggerFactory.getLogger(DetermineBasalAdapterMAJS.class);
|
||||
|
||||
|
||||
private ScriptReader mScriptReader = null;
|
||||
|
@ -47,49 +44,11 @@ public class DetermineBasalAdapterJS implements Parcelable {
|
|||
private String storedProfile = null;
|
||||
private String storedMeal_data = null;
|
||||
|
||||
/**
|
||||
* Parcelable implementation
|
||||
* result string for display only
|
||||
**/
|
||||
protected DetermineBasalAdapterJS(Parcel in) {
|
||||
storedCurrentTemp = in.readString();
|
||||
storedIobData = in.readString();
|
||||
storedGlucoseStatus = in.readString();
|
||||
storedProfile = in.readString();
|
||||
storedMeal_data = in.readString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeString(storedCurrentTemp);
|
||||
dest.writeString(storedIobData);
|
||||
dest.writeString(storedGlucoseStatus);
|
||||
dest.writeString(storedProfile);
|
||||
dest.writeString(storedMeal_data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static final Creator<DetermineBasalAdapterJS> CREATOR = new Creator<DetermineBasalAdapterJS>() {
|
||||
@Override
|
||||
public DetermineBasalAdapterJS createFromParcel(Parcel in) {
|
||||
return new DetermineBasalAdapterJS(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DetermineBasalAdapterJS[] newArray(int size) {
|
||||
return new DetermineBasalAdapterJS[size];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
/**
|
||||
* Main code
|
||||
*/
|
||||
|
||||
public DetermineBasalAdapterJS(ScriptReader scriptReader) throws IOException {
|
||||
public DetermineBasalAdapterMAJS(ScriptReader scriptReader) throws IOException {
|
||||
mV8rt = V8.createV8Runtime();
|
||||
mScriptReader = scriptReader;
|
||||
|
||||
|
@ -104,7 +63,6 @@ public class DetermineBasalAdapterJS implements Parcelable {
|
|||
// Profile
|
||||
mProfile = new V8Object(mV8rt);
|
||||
mProfile.add("max_iob", 0);
|
||||
mProfile.add("carbs_hr", 0);
|
||||
mProfile.add("dia", 0);
|
||||
mProfile.add("type", "current");
|
||||
mProfile.add("max_daily_basal", 0);
|
||||
|
@ -143,7 +101,7 @@ public class DetermineBasalAdapterJS implements Parcelable {
|
|||
mV8rt.add(PARAM_meal_data, mMealData);
|
||||
}
|
||||
|
||||
public DetermineBasalResult invoke() {
|
||||
public DetermineBasalResultMA invoke() {
|
||||
mV8rt.executeVoidScript(
|
||||
"console.error(\"determine_basal(\"+\n" +
|
||||
"JSON.stringify(" + PARAM_glucoseStatus + ")+ \", \" +\n" +
|
||||
|
@ -170,14 +128,13 @@ public class DetermineBasalAdapterJS implements Parcelable {
|
|||
|
||||
V8Object v8ObjectReuslt = mV8rt.getObject("rT");
|
||||
|
||||
DetermineBasalResult result = null;
|
||||
DetermineBasalResultMA result = null;
|
||||
try {
|
||||
result = new DetermineBasalResult(v8ObjectReuslt, new JSONObject(ret));
|
||||
result = new DetermineBasalResultMA(v8ObjectReuslt, new JSONObject(ret));
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// Store input params for Parcelable
|
||||
storedGlucoseStatus = mV8rt.executeStringScript("JSON.stringify(" + PARAM_glucoseStatus + ");");
|
||||
storedIobData = mV8rt.executeStringScript("JSON.stringify(" + PARAM_iobData + ");");
|
||||
storedCurrentTemp = mV8rt.executeStringScript("JSON.stringify(" + PARAM_currentTemp + ");");
|
||||
|
@ -266,13 +223,12 @@ public class DetermineBasalAdapterJS implements Parcelable {
|
|||
double targetBg,
|
||||
PumpInterface pump,
|
||||
IobTotal iobData,
|
||||
DatabaseHelper.GlucoseStatus glucoseStatus,
|
||||
TreatmentsPlugin.MealData mealData) {
|
||||
GlucoseStatus glucoseStatus,
|
||||
MealData mealData) {
|
||||
|
||||
String units = profile.getUnits();
|
||||
|
||||
mProfile.add("max_iob", maxIob);
|
||||
mProfile.add("carbs_hr", profile.getCarbAbsorbtionRate());
|
||||
mProfile.add("dia", profile.getDia());
|
||||
mProfile.add("type", "current");
|
||||
mProfile.add("max_daily_basal", profile.getMaxDailyBasal());
|
|
@ -8,9 +8,10 @@ import com.eclipsesource.v8.V8Object;
|
|||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import info.nightscout.androidaps.data.IobTotal;
|
||||
import info.nightscout.androidaps.plugins.Loop.APSResult;
|
||||
|
||||
public class DetermineBasalResult extends APSResult {
|
||||
public class DetermineBasalResultMA extends APSResult {
|
||||
|
||||
public JSONObject json = new JSONObject();
|
||||
public double eventualBG;
|
||||
|
@ -18,7 +19,7 @@ public class DetermineBasalResult extends APSResult {
|
|||
public String mealAssist;
|
||||
public IobTotal iob;
|
||||
|
||||
public DetermineBasalResult(V8Object result, JSONObject j) {
|
||||
public DetermineBasalResultMA(V8Object result, JSONObject j) {
|
||||
json = j;
|
||||
if (result.contains("error")) {
|
||||
reason = result.getString("error");
|
||||
|
@ -52,43 +53,12 @@ public class DetermineBasalResult extends APSResult {
|
|||
result.release();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
super.writeToParcel(dest, flags);
|
||||
dest.writeString(json.toString());
|
||||
dest.writeDouble(eventualBG);
|
||||
dest.writeDouble(snoozeBG);
|
||||
dest.writeString(mealAssist);
|
||||
}
|
||||
|
||||
public final Parcelable.Creator<DetermineBasalResult> CREATOR = new Parcelable.Creator<DetermineBasalResult>() {
|
||||
public DetermineBasalResult createFromParcel(Parcel in) {
|
||||
return new DetermineBasalResult(in);
|
||||
}
|
||||
|
||||
public DetermineBasalResult[] newArray(int size) {
|
||||
return new DetermineBasalResult[size];
|
||||
}
|
||||
};
|
||||
|
||||
private DetermineBasalResult(Parcel in) {
|
||||
super(in);
|
||||
try {
|
||||
json = new JSONObject(in.readString());
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
eventualBG = in.readDouble();
|
||||
snoozeBG = in.readDouble();
|
||||
mealAssist = in.readString();
|
||||
}
|
||||
|
||||
public DetermineBasalResult() {
|
||||
public DetermineBasalResultMA() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public DetermineBasalResult clone() {
|
||||
DetermineBasalResult newResult = new DetermineBasalResult();
|
||||
public DetermineBasalResultMA clone() {
|
||||
DetermineBasalResultMA newResult = new DetermineBasalResultMA();
|
||||
newResult.reason = new String(reason);
|
||||
newResult.rate = rate;
|
||||
newResult.duration = duration;
|
|
@ -1,76 +0,0 @@
|
|||
package info.nightscout.androidaps.plugins.OpenAPSMA;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import info.nightscout.utils.DateUtil;
|
||||
import info.nightscout.utils.Round;
|
||||
|
||||
public class IobTotal {
|
||||
public Double iob;
|
||||
public Double activity;
|
||||
public Double bolussnooze;
|
||||
public Double basaliob;
|
||||
public Double netbasalinsulin;
|
||||
public Double hightempinsulin;
|
||||
|
||||
public Double netInsulin = 0d; // for calculations from temp basals only
|
||||
public Double netRatio = 0d; // for calculations from temp basals only
|
||||
|
||||
public IobTotal() {
|
||||
this.iob = 0d;
|
||||
this.activity = 0d;
|
||||
this.bolussnooze = 0d;
|
||||
this.basaliob = 0d;
|
||||
this.netbasalinsulin = 0d;
|
||||
this.hightempinsulin = 0d;
|
||||
}
|
||||
|
||||
public IobTotal plus(IobTotal other) {
|
||||
iob += other.iob;
|
||||
activity += other.activity;
|
||||
bolussnooze += other.bolussnooze;
|
||||
basaliob += other.basaliob;
|
||||
netbasalinsulin += other.netbasalinsulin;
|
||||
hightempinsulin += other.hightempinsulin;
|
||||
netInsulin += other.netInsulin;
|
||||
netRatio += other.netRatio;
|
||||
return this;
|
||||
}
|
||||
|
||||
public static IobTotal combine(IobTotal bolusIOB, IobTotal basalIob) {
|
||||
IobTotal result = new IobTotal();
|
||||
result.iob = bolusIOB.iob + basalIob.basaliob;
|
||||
result.activity = bolusIOB.activity + basalIob.activity;
|
||||
result.bolussnooze = bolusIOB.bolussnooze;
|
||||
result.basaliob = basalIob.basaliob;
|
||||
result.netbasalinsulin = basalIob.netbasalinsulin;
|
||||
result.hightempinsulin = basalIob.hightempinsulin;
|
||||
return result;
|
||||
}
|
||||
|
||||
public IobTotal round() {
|
||||
this.iob = Round.roundTo(this.iob, 0.001);
|
||||
this.activity = Round.roundTo(this.activity, 0.0001);
|
||||
this.bolussnooze = Round.roundTo(this.bolussnooze, 0.0001);
|
||||
this.basaliob = Round.roundTo(this.basaliob, 0.001);
|
||||
this.netbasalinsulin = Round.roundTo(this.netbasalinsulin, 0.001);
|
||||
this.hightempinsulin = Round.roundTo(this.hightempinsulin, 0.001);
|
||||
return this;
|
||||
}
|
||||
|
||||
public JSONObject json() {
|
||||
JSONObject json = new JSONObject();
|
||||
try {
|
||||
json.put("iob", iob);
|
||||
json.put("basaliob", basaliob);
|
||||
json.put("activity", activity);
|
||||
json.put("time", DateUtil.toISOString(new Date()));
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return json;
|
||||
}
|
||||
}
|
|
@ -17,9 +17,8 @@ import org.slf4j.LoggerFactory;
|
|||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.interfaces.FragmentBase;
|
||||
import info.nightscout.androidaps.plugins.Loop.APSResult;
|
||||
import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSMAUpdateGui;
|
||||
import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSMAUpdateResultGui;
|
||||
import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateGui;
|
||||
import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateResultGui;
|
||||
import info.nightscout.utils.JSONFormatter;
|
||||
|
||||
public class OpenAPSMAFragment extends Fragment implements View.OnClickListener, FragmentBase {
|
||||
|
@ -68,7 +67,7 @@ public class OpenAPSMAFragment extends Fragment implements View.OnClickListener,
|
|||
public void onClick(View view) {
|
||||
switch (view.getId()) {
|
||||
case R.id.openapsma_run:
|
||||
getPlugin().invoke();
|
||||
getPlugin().invoke("OpenAPSMA button");
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -87,12 +86,12 @@ public class OpenAPSMAFragment extends Fragment implements View.OnClickListener,
|
|||
}
|
||||
|
||||
@Subscribe
|
||||
public void onStatusEvent(final EventOpenAPSMAUpdateGui ev) {
|
||||
public void onStatusEvent(final EventOpenAPSUpdateGui ev) {
|
||||
updateGUI();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onStatusEvent(final EventOpenAPSMAUpdateResultGui ev) {
|
||||
public void onStatusEvent(final EventOpenAPSUpdateResultGui ev) {
|
||||
updateResultGUI(ev.text);
|
||||
}
|
||||
|
||||
|
@ -102,18 +101,18 @@ public class OpenAPSMAFragment extends Fragment implements View.OnClickListener,
|
|||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
DetermineBasalResult lastAPSResult = getPlugin().lastAPSResult;
|
||||
DetermineBasalResultMA lastAPSResult = getPlugin().lastAPSResult;
|
||||
if (lastAPSResult != null) {
|
||||
resultView.setText(JSONFormatter.format(lastAPSResult.json));
|
||||
requestView.setText(lastAPSResult.toSpanned());
|
||||
}
|
||||
DetermineBasalAdapterJS determineBasalAdapterJS = getPlugin().lastDetermineBasalAdapterJS;
|
||||
if (determineBasalAdapterJS != null) {
|
||||
glucoseStatusView.setText(JSONFormatter.format(determineBasalAdapterJS.getGlucoseStatusParam()));
|
||||
currentTempView.setText(JSONFormatter.format(determineBasalAdapterJS.getCurrentTempParam()));
|
||||
iobDataView.setText(JSONFormatter.format(determineBasalAdapterJS.getIobDataParam()));
|
||||
profileView.setText(JSONFormatter.format(determineBasalAdapterJS.getProfileParam()));
|
||||
mealDataView.setText(JSONFormatter.format(determineBasalAdapterJS.getMealDataParam()));
|
||||
DetermineBasalAdapterMAJS determineBasalAdapterMAJS = getPlugin().lastDetermineBasalAdapterMAJS;
|
||||
if (determineBasalAdapterMAJS != null) {
|
||||
glucoseStatusView.setText(JSONFormatter.format(determineBasalAdapterMAJS.getGlucoseStatusParam()));
|
||||
currentTempView.setText(JSONFormatter.format(determineBasalAdapterMAJS.getCurrentTempParam()));
|
||||
iobDataView.setText(JSONFormatter.format(determineBasalAdapterMAJS.getIobDataParam()));
|
||||
profileView.setText(JSONFormatter.format(determineBasalAdapterMAJS.getProfileParam()));
|
||||
mealDataView.setText(JSONFormatter.format(determineBasalAdapterMAJS.getMealDataParam()));
|
||||
}
|
||||
if (getPlugin().lastAPSRun != null) {
|
||||
lastRunView.setText(getPlugin().lastAPSRun.toLocaleString());
|
||||
|
|
|
@ -1,13 +1,9 @@
|
|||
package info.nightscout.androidaps.plugins.OpenAPSMA;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -18,8 +14,10 @@ import info.nightscout.androidaps.Config;
|
|||
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.DatabaseHelper;
|
||||
import info.nightscout.androidaps.data.GlucoseStatus;
|
||||
import info.nightscout.androidaps.data.IobTotal;
|
||||
import info.nightscout.androidaps.data.MealData;
|
||||
import info.nightscout.androidaps.db.TempTarget;
|
||||
import info.nightscout.androidaps.interfaces.APSInterface;
|
||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||
|
@ -27,16 +25,19 @@ import info.nightscout.androidaps.interfaces.TempBasalsInterface;
|
|||
import info.nightscout.androidaps.interfaces.TreatmentsInterface;
|
||||
import info.nightscout.androidaps.plugins.Loop.APSResult;
|
||||
import info.nightscout.androidaps.plugins.Loop.ScriptReader;
|
||||
import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSMAUpdateGui;
|
||||
import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSMAUpdateResultGui;
|
||||
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
|
||||
import info.nightscout.client.data.DbLogger;
|
||||
import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateGui;
|
||||
import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateResultGui;
|
||||
import info.nightscout.androidaps.plugins.TempTargetRange.TempTargetRangePlugin;
|
||||
import info.nightscout.client.data.NSProfile;
|
||||
import info.nightscout.utils.DateUtil;
|
||||
import info.nightscout.utils.Profiler;
|
||||
import info.nightscout.utils.Round;
|
||||
import info.nightscout.utils.SafeParse;
|
||||
import info.nightscout.utils.ToastUtils;
|
||||
|
||||
import static info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin.checkOnlyHardLimits;
|
||||
import static info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin.verifyHardLimits;
|
||||
|
||||
/**
|
||||
* Created by mike on 05.08.2016.
|
||||
*/
|
||||
|
@ -44,9 +45,9 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface {
|
|||
private static Logger log = LoggerFactory.getLogger(OpenAPSMAPlugin.class);
|
||||
|
||||
// last values
|
||||
DetermineBasalAdapterJS lastDetermineBasalAdapterJS = null;
|
||||
DetermineBasalAdapterMAJS lastDetermineBasalAdapterMAJS = null;
|
||||
Date lastAPSRun = null;
|
||||
DetermineBasalResult lastAPSResult = null;
|
||||
DetermineBasalResultMA lastAPSResult = null;
|
||||
|
||||
boolean fragmentEnabled = false;
|
||||
boolean fragmentVisible = true;
|
||||
|
@ -56,6 +57,17 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface {
|
|||
return MainApp.instance().getString(R.string.openapsma);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNameShort() {
|
||||
String name = MainApp.sResources.getString(R.string.oaps_shortname);
|
||||
if (!name.trim().isEmpty()){
|
||||
//only if translation exists
|
||||
return name;
|
||||
}
|
||||
// use long name as fallback
|
||||
return getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(int type) {
|
||||
return type == APS && fragmentEnabled && MainApp.getConfigBuilder().getPumpDescription().isTempBasalCapable;
|
||||
|
@ -102,43 +114,44 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void invoke() {
|
||||
public void invoke(String initiator) {
|
||||
log.debug("invoke from " + initiator);
|
||||
lastAPSResult = null;
|
||||
DetermineBasalAdapterJS determineBasalAdapterJS = null;
|
||||
DetermineBasalAdapterMAJS determineBasalAdapterMAJS = null;
|
||||
try {
|
||||
determineBasalAdapterJS = new DetermineBasalAdapterJS(new ScriptReader(MainApp.instance().getBaseContext()));
|
||||
determineBasalAdapterMAJS = new DetermineBasalAdapterMAJS(new ScriptReader(MainApp.instance().getBaseContext()));
|
||||
} catch (IOException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
return;
|
||||
}
|
||||
|
||||
DatabaseHelper.GlucoseStatus glucoseStatus = MainApp.getDbHelper().getGlucoseStatusData();
|
||||
GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData();
|
||||
NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile();
|
||||
PumpInterface pump = MainApp.getConfigBuilder();
|
||||
|
||||
if (!isEnabled(PluginBase.APS)) {
|
||||
MainApp.bus().post(new EventOpenAPSMAUpdateResultGui(MainApp.instance().getString(R.string.openapsma_disabled)));
|
||||
MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.instance().getString(R.string.openapsma_disabled)));
|
||||
if (Config.logAPSResult)
|
||||
log.debug(MainApp.instance().getString(R.string.openapsma_disabled));
|
||||
return;
|
||||
}
|
||||
|
||||
if (glucoseStatus == null) {
|
||||
MainApp.bus().post(new EventOpenAPSMAUpdateResultGui(MainApp.instance().getString(R.string.openapsma_noglucosedata)));
|
||||
MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.instance().getString(R.string.openapsma_noglucosedata)));
|
||||
if (Config.logAPSResult)
|
||||
log.debug(MainApp.instance().getString(R.string.openapsma_noglucosedata));
|
||||
return;
|
||||
}
|
||||
|
||||
if (profile == null) {
|
||||
MainApp.bus().post(new EventOpenAPSMAUpdateResultGui(MainApp.instance().getString(R.string.openapsma_noprofile)));
|
||||
MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.instance().getString(R.string.openapsma_noprofile)));
|
||||
if (Config.logAPSResult)
|
||||
log.debug(MainApp.instance().getString(R.string.openapsma_noprofile));
|
||||
return;
|
||||
}
|
||||
|
||||
if (pump == null) {
|
||||
MainApp.bus().post(new EventOpenAPSMAUpdateResultGui(MainApp.instance().getString(R.string.openapsma_nopump)));
|
||||
MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.instance().getString(R.string.openapsma_nopump)));
|
||||
if (Config.logAPSResult)
|
||||
log.debug(MainApp.instance().getString(R.string.openapsma_nopump));
|
||||
return;
|
||||
|
@ -147,13 +160,13 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface {
|
|||
SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
|
||||
String units = profile.getUnits();
|
||||
|
||||
String maxBgDefault = "180";
|
||||
String minBgDefault = "100";
|
||||
String targetBgDefault = "150";
|
||||
String maxBgDefault = Constants.MAX_BG_DEFAULT_MGDL;
|
||||
String minBgDefault = Constants.MIN_BG_DEFAULT_MGDL;
|
||||
String targetBgDefault = Constants.TARGET_BG_DEFAULT_MGDL;
|
||||
if (!units.equals(Constants.MGDL)) {
|
||||
maxBgDefault = "10";
|
||||
minBgDefault = "5";
|
||||
targetBgDefault = "7";
|
||||
maxBgDefault = Constants.MAX_BG_DEFAULT_MMOL;
|
||||
minBgDefault = Constants.MIN_BG_DEFAULT_MMOL;
|
||||
targetBgDefault = Constants.TARGET_BG_DEFAULT_MMOL;
|
||||
}
|
||||
|
||||
Date now = new Date();
|
||||
|
@ -167,6 +180,7 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface {
|
|||
minBg = Round.roundTo(minBg, 0.1d);
|
||||
maxBg = Round.roundTo(maxBg, 0.1d);
|
||||
|
||||
Date start = new Date();
|
||||
TreatmentsInterface treatments = MainApp.getConfigBuilder().getActiveTreatments();
|
||||
TempBasalsInterface tempBasals = MainApp.getConfigBuilder().getActiveTempBasals();
|
||||
treatments.updateTotalIOB();
|
||||
|
@ -176,71 +190,68 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface {
|
|||
|
||||
IobTotal iobTotal = IobTotal.combine(bolusIob, basalIob).round();
|
||||
|
||||
TreatmentsPlugin.MealData mealData = treatments.getMealData();
|
||||
MealData mealData = treatments.getMealData();
|
||||
|
||||
maxIob = MainApp.getConfigBuilder().applyMaxIOBConstraints(maxIob);
|
||||
Profiler.log(log, "MA data gathering", start);
|
||||
|
||||
minBg = verifyHardLimits(minBg, "minBg", Constants.VERY_HARD_LIMIT_MIN_BG[0], Constants.VERY_HARD_LIMIT_MIN_BG[1]);
|
||||
maxBg = verifyHardLimits(maxBg, "maxBg", Constants.VERY_HARD_LIMIT_MAX_BG[0], Constants.VERY_HARD_LIMIT_MAX_BG[1]);
|
||||
targetBg = verifyHardLimits(targetBg, "targetBg", Constants.VERY_HARD_LIMIT_TARGET_BG[0], Constants.VERY_HARD_LIMIT_TARGET_BG[1]);
|
||||
|
||||
TempTargetRangePlugin tempTargetRangePlugin = (TempTargetRangePlugin) MainApp.getSpecificPlugin(TempTargetRangePlugin.class);
|
||||
if (tempTargetRangePlugin != null && tempTargetRangePlugin.isEnabled(PluginBase.GENERAL)) {
|
||||
TempTarget tempTarget = tempTargetRangePlugin.getTempTargetInProgress(new Date().getTime());
|
||||
if (tempTarget != null) {
|
||||
minBg = verifyHardLimits(tempTarget.low, "minBg", Constants.VERY_HARD_LIMIT_TEMP_MIN_BG[0], Constants.VERY_HARD_LIMIT_TEMP_MIN_BG[1]);
|
||||
maxBg = verifyHardLimits(tempTarget.high, "maxBg", Constants.VERY_HARD_LIMIT_TEMP_MAX_BG[0], Constants.VERY_HARD_LIMIT_TEMP_MAX_BG[1]);
|
||||
targetBg = verifyHardLimits((tempTarget.low + tempTarget.high) / 2, "targetBg", Constants.VERY_HARD_LIMIT_TEMP_TARGET_BG[0], Constants.VERY_HARD_LIMIT_TEMP_TARGET_BG[1]);
|
||||
}
|
||||
}
|
||||
|
||||
minBg = verifyHardLimits(minBg, "minBg", 72, 180);
|
||||
maxBg = verifyHardLimits(maxBg, "maxBg", 100, 270);
|
||||
targetBg = verifyHardLimits(targetBg, "targetBg", 80, 200);
|
||||
maxIob = verifyHardLimits(maxIob, "maxIob", 0, 7);
|
||||
maxBasal = verifyHardLimits(maxBasal, "max_basal", 0.1, 10);
|
||||
|
||||
if (!checkOnlyHardLimits(profile.getCarbAbsorbtionRate(), "carbs_hr", 4, 100)) return;
|
||||
if (!checkOnlyHardLimits(profile.getDia(), "dia", 2, 7)) return;
|
||||
if (!checkOnlyHardLimits(profile.getIc(profile.secondsFromMidnight()), "carbratio", 2, 100)) return;
|
||||
if (!checkOnlyHardLimits(NSProfile.toMgdl(profile.getIsf(NSProfile.secondsFromMidnight()).doubleValue(), units), "sens", 2, 900)) return;
|
||||
if (!checkOnlyHardLimits(profile.getMaxDailyBasal(), "max_daily_basal", 0.1, 10)) return;
|
||||
if (!checkOnlyHardLimits(pump.getBaseBasalRate(), "current_basal", 0.01, 5)) return;
|
||||
|
||||
determineBasalAdapterJS.setData(profile, maxIob, maxBasal, minBg, maxBg, targetBg, pump, iobTotal, glucoseStatus, mealData);
|
||||
start = new Date();
|
||||
determineBasalAdapterMAJS.setData(profile, maxIob, maxBasal, minBg, maxBg, targetBg, pump, iobTotal, glucoseStatus, mealData);
|
||||
Profiler.log(log, "MA calculation", start);
|
||||
|
||||
|
||||
DetermineBasalResult determineBasalResult = determineBasalAdapterJS.invoke();
|
||||
DetermineBasalResultMA determineBasalResultMA = determineBasalAdapterMAJS.invoke();
|
||||
// Fix bug determine basal
|
||||
if (determineBasalResult.rate == 0d && determineBasalResult.duration == 0 && !MainApp.getConfigBuilder().isTempBasalInProgress())
|
||||
determineBasalResult.changeRequested = false;
|
||||
if (determineBasalResultMA.rate == 0d && determineBasalResultMA.duration == 0 && !MainApp.getConfigBuilder().isTempBasalInProgress())
|
||||
determineBasalResultMA.changeRequested = false;
|
||||
// limit requests on openloop mode
|
||||
if (!MainApp.getConfigBuilder().isClosedModeEnabled()) {
|
||||
if (MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResult.rate - MainApp.getConfigBuilder().getTempBasalAbsoluteRate()) < 0.1)
|
||||
determineBasalResult.changeRequested = false;
|
||||
if (!MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResult.rate - MainApp.getConfigBuilder().getBaseBasalRate()) < 0.1)
|
||||
determineBasalResult.changeRequested = false;
|
||||
if (MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultMA.rate - MainApp.getConfigBuilder().getTempBasalAbsoluteRate()) < 0.1)
|
||||
determineBasalResultMA.changeRequested = false;
|
||||
if (!MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultMA.rate - MainApp.getConfigBuilder().getBaseBasalRate()) < 0.1)
|
||||
determineBasalResultMA.changeRequested = false;
|
||||
}
|
||||
|
||||
determineBasalResult.iob = iobTotal;
|
||||
determineBasalResultMA.iob = iobTotal;
|
||||
|
||||
determineBasalAdapterJS.release();
|
||||
determineBasalAdapterMAJS.release();
|
||||
|
||||
try {
|
||||
determineBasalResult.json.put("timestamp", DateUtil.toISOString(now));
|
||||
determineBasalResultMA.json.put("timestamp", DateUtil.toISOString(now));
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
lastDetermineBasalAdapterJS = determineBasalAdapterJS;
|
||||
lastAPSResult = determineBasalResult;
|
||||
lastDetermineBasalAdapterMAJS = determineBasalAdapterMAJS;
|
||||
lastAPSResult = determineBasalResultMA;
|
||||
lastAPSRun = now;
|
||||
MainApp.bus().post(new EventOpenAPSMAUpdateGui());
|
||||
MainApp.bus().post(new EventOpenAPSUpdateGui());
|
||||
|
||||
//deviceStatus.suggested = determineBasalResult.json;
|
||||
//deviceStatus.suggested = determineBasalResultMA.json;
|
||||
}
|
||||
|
||||
// safety checks
|
||||
public static boolean checkOnlyHardLimits(Double value, String valueName, double lowLimit, double highLimit) {
|
||||
return value.equals(verifyHardLimits(value, valueName, lowLimit, highLimit));
|
||||
}
|
||||
|
||||
public static Double verifyHardLimits(Double value, String valueName, double lowLimit, double highLimit) {
|
||||
if (value < lowLimit || value > highLimit) {
|
||||
String msg = String.format(MainApp.sResources.getString(R.string.openapsma_valueoutofrange), valueName);
|
||||
log.error(msg);
|
||||
MainApp.getConfigBuilder().uploadError(msg);
|
||||
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), msg, R.raw.error);
|
||||
value = Math.max(value, lowLimit);
|
||||
value = Math.min(value, highLimit);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,5 +3,5 @@ package info.nightscout.androidaps.plugins.OpenAPSMA.events;
|
|||
/**
|
||||
* Created by mike on 05.08.2016.
|
||||
*/
|
||||
public class EventOpenAPSMAUpdateGui {
|
||||
public class EventOpenAPSUpdateGui {
|
||||
}
|
|
@ -3,10 +3,10 @@ package info.nightscout.androidaps.plugins.OpenAPSMA.events;
|
|||
/**
|
||||
* Created by mike on 05.08.2016.
|
||||
*/
|
||||
public class EventOpenAPSMAUpdateResultGui {
|
||||
public class EventOpenAPSUpdateResultGui {
|
||||
public String text = null;
|
||||
|
||||
public EventOpenAPSMAUpdateResultGui(String text) {
|
||||
public EventOpenAPSUpdateResultGui(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
}
|
|
@ -29,6 +29,7 @@ public class BolusProgressDialog extends DialogFragment implements View.OnClickL
|
|||
TextView statusView;
|
||||
TextView stopPressedView;
|
||||
ProgressBar progressBar;
|
||||
BolusProgressHelperActivity helperActivity;
|
||||
|
||||
static double amount;
|
||||
public static boolean bolusEnded = false;
|
||||
|
@ -45,6 +46,10 @@ public class BolusProgressDialog extends DialogFragment implements View.OnClickL
|
|||
bolusEnded = false;
|
||||
}
|
||||
|
||||
public void setHelperActivity(BolusProgressHelperActivity activity){
|
||||
this.helperActivity = activity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
|
@ -71,6 +76,14 @@ public class BolusProgressDialog extends DialogFragment implements View.OnClickL
|
|||
if (bolusEnded) dismiss();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dismiss(){
|
||||
super.dismiss();
|
||||
if (helperActivity!= null){
|
||||
helperActivity.finish();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
|
@ -124,7 +137,7 @@ public class BolusProgressDialog extends DialogFragment implements View.OnClickL
|
|||
@Override
|
||||
public void run() {
|
||||
if (c.sStatus == c.CONNECTING) {
|
||||
statusView.setText(String.format(getString(R.string.danar_history_connectingfor), c.sSecondsElapsed));
|
||||
statusView.setText(String.format(MainApp.sResources.getString(R.string.danar_history_connectingfor), c.sSecondsElapsed));
|
||||
} else if (c.sStatus == c.CONNECTED) {
|
||||
statusView.setText(MainApp.sResources.getString(R.string.connected));
|
||||
} else {
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
package info.nightscout.androidaps.plugins.Overview.Dialogs;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
|
||||
/**
|
||||
* Created by adrian on 09/02/17.
|
||||
*/
|
||||
|
||||
public class BolusProgressHelperActivity extends AppCompatActivity {
|
||||
public BolusProgressHelperActivity() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
this.getIntent().getDoubleExtra("insulin", 0d);
|
||||
BolusProgressDialog bolusProgressDialog = new BolusProgressDialog();
|
||||
bolusProgressDialog.setHelperActivity(this);
|
||||
bolusProgressDialog.setInsulin(this.getIntent().getDoubleExtra("insulin", 0d));
|
||||
bolusProgressDialog.show(this.getSupportFragmentManager(), "BolusProgress");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
package info.nightscout.androidaps.plugins.Overview.Dialogs;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
|
||||
import info.nightscout.androidaps.Constants;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.data.GlucoseStatus;
|
||||
import info.nightscout.client.data.NSProfile;
|
||||
import info.nightscout.utils.PlusMinusEditText;
|
||||
import info.nightscout.utils.XdripCalibrations;
|
||||
|
||||
public class CalibrationDialog extends DialogFragment implements View.OnClickListener {
|
||||
private static Logger log = LoggerFactory.getLogger(CalibrationDialog.class);
|
||||
|
||||
Button okButton;
|
||||
PlusMinusEditText bgText;
|
||||
TextView unitsView;
|
||||
|
||||
Context parentContext;
|
||||
|
||||
public CalibrationDialog() {
|
||||
// Required empty public constructor
|
||||
}
|
||||
|
||||
public void setContext(Context context) {
|
||||
parentContext = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.overview_calibration_dialog, container, false);
|
||||
|
||||
getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
|
||||
getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
|
||||
|
||||
okButton = (Button) view.findViewById(R.id.overview_calibration_okbutton);
|
||||
okButton.setOnClickListener(this);
|
||||
|
||||
NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile();
|
||||
Double bg = NSProfile.fromMgdlToUnits(GlucoseStatus.getGlucoseStatusData() != null ? GlucoseStatus.getGlucoseStatusData().glucose : 0d, profile.getUnits());
|
||||
if (profile.getUnits().equals(Constants.MMOL))
|
||||
bgText = new PlusMinusEditText(view, R.id.overview_calibration_bg, R.id.overview_calibration_bg_plus, R.id.overview_calibration_bg_minus, bg, 0d, 30d, 0.1d, new DecimalFormat("0.0"), false);
|
||||
else
|
||||
bgText = new PlusMinusEditText(view, R.id.overview_calibration_bg, R.id.overview_calibration_bg_plus, R.id.overview_calibration_bg_minus, bg, 0d, 500d, 1d, new DecimalFormat("0"), false);
|
||||
|
||||
unitsView = (TextView) view.findViewById(R.id.overview_calibration_units);
|
||||
unitsView.setText(profile.getUnits());
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
switch (view.getId()) {
|
||||
case R.id.overview_calibration_okbutton:
|
||||
final Double bg = bgText.getValue();
|
||||
XdripCalibrations.confirmAndSendCalibration(bg, parentContext);
|
||||
dismiss();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -36,20 +36,18 @@ import java.util.Date;
|
|||
import info.nightscout.androidaps.Constants;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.data.GlucoseStatus;
|
||||
import info.nightscout.androidaps.data.PumpEnactResult;
|
||||
import info.nightscout.androidaps.db.BgReading;
|
||||
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||
import info.nightscout.androidaps.interfaces.TempBasalsInterface;
|
||||
import info.nightscout.androidaps.interfaces.TreatmentsInterface;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.OpenAPSMA.IobTotal;
|
||||
import info.nightscout.androidaps.data.IobTotal;
|
||||
import info.nightscout.client.data.NSProfile;
|
||||
import info.nightscout.utils.BolusWizard;
|
||||
import info.nightscout.utils.DateUtil;
|
||||
import info.nightscout.utils.DecimalFormatter;
|
||||
import info.nightscout.utils.PlusMinusEditText;
|
||||
import info.nightscout.utils.Round;
|
||||
import info.nightscout.utils.SafeParse;
|
||||
import info.nightscout.utils.ToastUtils;
|
||||
|
||||
|
@ -281,7 +279,7 @@ public class WizardDialog extends DialogFragment implements OnClickListener {
|
|||
else editBg.setStep(0.1d);
|
||||
|
||||
// Set BG if not old
|
||||
BgReading lastBg = MainApp.getDbHelper().actualBg();
|
||||
BgReading lastBg = GlucoseStatus.actualBg();
|
||||
|
||||
if (lastBg != null) {
|
||||
Double lastBgValue = lastBg.valueToUnits(units);
|
||||
|
|
|
@ -20,6 +20,9 @@ public class Notification {
|
|||
public static final int PROFILE_NOT_SET_NOT_INITIALIZED = 5;
|
||||
public static final int FAILED_UDPATE_PROFILE = 6;
|
||||
public static final int BASAL_VALUE_BELOW_MINIMUM = 7;
|
||||
public static final int OLD_NSCLIENT = 8;
|
||||
public static final int INVALID_PHONE_NUMBER = 9;
|
||||
public static final int APPROACHING_DAILY_LIMIT = 10;
|
||||
|
||||
public int id;
|
||||
public Date date;
|
||||
|
|
|
@ -13,6 +13,7 @@ import android.os.HandlerThread;
|
|||
import android.preference.PreferenceManager;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.support.v7.widget.CardView;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
|
@ -22,6 +23,8 @@ import android.view.LayoutInflater;
|
|||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
|
@ -49,10 +52,12 @@ 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.GlucoseStatus;
|
||||
import info.nightscout.androidaps.data.IobTotal;
|
||||
import info.nightscout.androidaps.data.PumpEnactResult;
|
||||
import info.nightscout.androidaps.db.BgReading;
|
||||
import info.nightscout.androidaps.db.DatabaseHelper;
|
||||
import info.nightscout.androidaps.db.TempBasal;
|
||||
import info.nightscout.androidaps.db.TempTarget;
|
||||
import info.nightscout.androidaps.db.Treatment;
|
||||
import info.nightscout.androidaps.events.EventInitializationChanged;
|
||||
import info.nightscout.androidaps.events.EventNewBG;
|
||||
|
@ -66,16 +71,22 @@ import info.nightscout.androidaps.interfaces.PumpInterface;
|
|||
import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog;
|
||||
import info.nightscout.androidaps.plugins.Careportal.OptionsToShow;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.DanaR.events.EventDanaRConnectionStatus;
|
||||
import info.nightscout.androidaps.plugins.Loop.LoopPlugin;
|
||||
import info.nightscout.androidaps.plugins.Loop.events.EventNewOpenLoopNotification;
|
||||
import info.nightscout.androidaps.plugins.Objectives.ObjectivesPlugin;
|
||||
import info.nightscout.androidaps.plugins.OpenAPSMA.IobTotal;
|
||||
import info.nightscout.androidaps.plugins.OpenAPSAMA.DetermineBasalResultAMA;
|
||||
import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin;
|
||||
import info.nightscout.androidaps.plugins.Overview.Dialogs.CalibrationDialog;
|
||||
import info.nightscout.androidaps.plugins.Overview.Dialogs.NewTreatmentDialog;
|
||||
import info.nightscout.androidaps.plugins.Overview.Dialogs.WizardDialog;
|
||||
import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLabelGraphSeries;
|
||||
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
|
||||
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
|
||||
import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLabelGraphSeries;
|
||||
import info.nightscout.androidaps.plugins.Overview.graphExtensions.TimeAsXAxisLabelFormatter;
|
||||
import info.nightscout.androidaps.plugins.SourceXdrip.SourceXdripPlugin;
|
||||
import info.nightscout.androidaps.plugins.TempTargetRange.TempTargetRangePlugin;
|
||||
import info.nightscout.androidaps.plugins.TempTargetRange.events.EventTempTargetRangeChange;
|
||||
import info.nightscout.client.data.NSProfile;
|
||||
import info.nightscout.utils.BolusWizard;
|
||||
import info.nightscout.utils.DateUtil;
|
||||
|
@ -105,17 +116,20 @@ public class OverviewFragment extends Fragment {
|
|||
TextView activeProfileView;
|
||||
TextView iobView;
|
||||
TextView apsModeView;
|
||||
TextView tempTargetView;
|
||||
TextView pumpStatusView;
|
||||
GraphView bgGraph;
|
||||
CheckBox showPredictionView;
|
||||
|
||||
RecyclerView notificationsView;
|
||||
LinearLayoutManager llm;
|
||||
|
||||
LinearLayout cancelTempLayout;
|
||||
LinearLayout acceptTempLayout;
|
||||
LinearLayout quickWizardLayout;
|
||||
Button cancelTempButton;
|
||||
Button treatmentButton;
|
||||
Button wizardButton;
|
||||
Button calibrationButton;
|
||||
Button acceptTempButton;
|
||||
Button quickWizardButton;
|
||||
|
||||
|
@ -149,9 +163,11 @@ public class OverviewFragment extends Fragment {
|
|||
baseBasalView = (TextView) view.findViewById(R.id.overview_basebasal);
|
||||
basalLayout = (LinearLayout) view.findViewById(R.id.overview_basallayout);
|
||||
activeProfileView = (TextView) view.findViewById(R.id.overview_activeprofile);
|
||||
pumpStatusView = (TextView) view.findViewById(R.id.overview_initializing);
|
||||
|
||||
iobView = (TextView) view.findViewById(R.id.overview_iob);
|
||||
apsModeView = (TextView) view.findViewById(R.id.overview_apsmode);
|
||||
tempTargetView = (TextView) view.findViewById(R.id.overview_temptarget);
|
||||
bgGraph = (GraphView) view.findViewById(R.id.overview_bggraph);
|
||||
cancelTempButton = (Button) view.findViewById(R.id.overview_canceltemp);
|
||||
treatmentButton = (Button) view.findViewById(R.id.overview_treatment);
|
||||
|
@ -161,13 +177,26 @@ public class OverviewFragment extends Fragment {
|
|||
acceptTempButton = (Button) view.findViewById(R.id.overview_accepttempbutton);
|
||||
acceptTempLayout = (LinearLayout) view.findViewById(R.id.overview_accepttemplayout);
|
||||
quickWizardButton = (Button) view.findViewById(R.id.overview_quickwizard);
|
||||
quickWizardLayout = (LinearLayout) view.findViewById(R.id.overview_quickwizardlayout);
|
||||
calibrationButton = (Button) view.findViewById(R.id.overview_calibration);
|
||||
showPredictionView = (CheckBox) view.findViewById(R.id.overview_showprediction);
|
||||
|
||||
notificationsView = (RecyclerView) view.findViewById(R.id.overview_notifications);
|
||||
notificationsView.setHasFixedSize(true);
|
||||
llm = new LinearLayoutManager(view.getContext());
|
||||
notificationsView.setLayoutManager(llm);
|
||||
|
||||
showPredictionView.setChecked(prefs.getBoolean("showprediction", false));
|
||||
|
||||
showPredictionView.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||
SharedPreferences.Editor editor = prefs.edit();
|
||||
editor.putBoolean("showprediction", showPredictionView.isChecked());
|
||||
editor.apply();
|
||||
updateGUI();
|
||||
}
|
||||
});
|
||||
|
||||
treatmentButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
|
@ -210,11 +239,20 @@ public class OverviewFragment extends Fragment {
|
|||
}
|
||||
});
|
||||
|
||||
calibrationButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
FragmentManager manager = getFragmentManager();
|
||||
CalibrationDialog calibrationDialog = new CalibrationDialog();
|
||||
calibrationDialog.setContext(getContext());
|
||||
calibrationDialog.show(manager, "CalibrationDialog");
|
||||
}
|
||||
});
|
||||
|
||||
acceptTempButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
MainApp.getConfigBuilder().getActiveLoop().invoke(false);
|
||||
ConfigBuilderPlugin.getActiveLoop().invoke("Accept temp button", false);
|
||||
final LoopPlugin.LastRun finalLastRun = LoopPlugin.lastRun;
|
||||
if (finalLastRun != null && finalLastRun.lastAPSRun != null && finalLastRun.constraintsProcessed.changeRequested) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
|
||||
|
@ -231,7 +269,7 @@ public class OverviewFragment extends Fragment {
|
|||
finalLastRun.setByPump = applyResult;
|
||||
finalLastRun.lastEnact = new Date();
|
||||
finalLastRun.lastOpenModeAccept = new Date();
|
||||
MainApp.getConfigBuilder().uploadDeviceStatus();
|
||||
MainApp.getConfigBuilder().uploadDeviceStatus(15);
|
||||
ObjectivesPlugin objectivesPlugin = (ObjectivesPlugin) MainApp.getSpecificPlugin(ObjectivesPlugin.class);
|
||||
if (objectivesPlugin != null) {
|
||||
objectivesPlugin.manualEnacts++;
|
||||
|
@ -250,26 +288,39 @@ public class OverviewFragment extends Fragment {
|
|||
}
|
||||
});
|
||||
|
||||
pumpStatusView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
if (MainApp.getConfigBuilder().isSuspended() || !MainApp.getConfigBuilder().isInitialized())
|
||||
sHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
MainApp.getConfigBuilder().updateStatus("RefreshClicked");
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
updateGUI();
|
||||
return view;
|
||||
}
|
||||
|
||||
void processQuickWizard() {
|
||||
final BgReading lastBG = MainApp.getDbHelper().lastBg();
|
||||
final BgReading actualBg = GlucoseStatus.actualBg();
|
||||
if (MainApp.getConfigBuilder() == null || ConfigBuilderPlugin.getActiveProfile() == null) // app not initialized yet
|
||||
return;
|
||||
final NSProfile profile = ConfigBuilderPlugin.getActiveProfile().getProfile();
|
||||
|
||||
QuickWizard.QuickWizardEntry quickWizardEntry = getPlugin().quickWizard.getActive();
|
||||
if (quickWizardEntry != null && lastBG != null) {
|
||||
quickWizardLayout.setVisibility(View.VISIBLE);
|
||||
if (quickWizardEntry != null && actualBg != null) {
|
||||
quickWizardButton.setVisibility(View.VISIBLE);
|
||||
String text = MainApp.sResources.getString(R.string.bolus) + ": " + quickWizardEntry.buttonText();
|
||||
BolusWizard wizard = new BolusWizard();
|
||||
wizard.doCalc(profile.getDefaultProfile(), quickWizardEntry.carbs(), lastBG.valueToUnits(profile.getUnits()), 0d, true, true);
|
||||
wizard.doCalc(profile.getDefaultProfile(), quickWizardEntry.carbs(), actualBg.valueToUnits(profile.getUnits()), 0d, true, true);
|
||||
|
||||
final JSONObject boluscalcJSON = new JSONObject();
|
||||
try {
|
||||
boluscalcJSON.put("eventTime", DateUtil.toISOString(new Date()));
|
||||
boluscalcJSON.put("eventTime", DateUtil.toISOString(new Date()));
|
||||
boluscalcJSON.put("targetBGLow", wizard.targetBGLow);
|
||||
boluscalcJSON.put("targetBGHigh", wizard.targetBGHigh);
|
||||
boluscalcJSON.put("isf", wizard.sens);
|
||||
|
@ -277,7 +328,7 @@ public class OverviewFragment extends Fragment {
|
|||
boluscalcJSON.put("iob", -(wizard.insulingFromBolusIOB + wizard.insulingFromBasalsIOB));
|
||||
boluscalcJSON.put("bolusiobused", true);
|
||||
boluscalcJSON.put("basaliobused", true);
|
||||
boluscalcJSON.put("bg", lastBG.valueToUnits(profile.getUnits()));
|
||||
boluscalcJSON.put("bg", actualBg.valueToUnits(profile.getUnits()));
|
||||
boluscalcJSON.put("insulinbg", wizard.insulinFromBG);
|
||||
boluscalcJSON.put("insulinbgused", true);
|
||||
boluscalcJSON.put("bgdiff", wizard.bgDiff);
|
||||
|
@ -324,7 +375,7 @@ public class OverviewFragment extends Fragment {
|
|||
getContext(),
|
||||
finalInsulinAfterConstraints,
|
||||
finalCarbsAfterConstraints,
|
||||
lastBG.valueToUnits(profile.getUnits()),
|
||||
actualBg.valueToUnits(profile.getUnits()),
|
||||
"Manual",
|
||||
0,
|
||||
boluscalcJSON
|
||||
|
@ -406,13 +457,41 @@ public class OverviewFragment extends Fragment {
|
|||
}
|
||||
|
||||
@Subscribe
|
||||
public void onStatusEvent(final EventNewBasalProfile ev) { updateGUIIfVisible(); }
|
||||
public void onStatusEvent(final EventNewBasalProfile ev) {
|
||||
updateGUIIfVisible();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onStatusEvent(final EventNewNotification n) { updateNotifications(); }
|
||||
public void onStatusEvent(final EventTempTargetRangeChange ev) {
|
||||
updateGUIIfVisible();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onStatusEvent(final EventDismissNotification n) { updateNotifications(); }
|
||||
public void onStatusEvent(final EventNewNotification n) {
|
||||
updateNotifications();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onStatusEvent(final EventDismissNotification n) {
|
||||
updateNotifications();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onStatusEvent(final EventDanaRConnectionStatus s) {
|
||||
Activity activity = getActivity();
|
||||
if (activity != null)
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (s.sStatus == EventDanaRConnectionStatus.CONNECTING)
|
||||
updatePumpStatus(String.format(getString(R.string.danar_history_connectingfor), s.sSecondsElapsed));
|
||||
else if (s.sStatus == EventDanaRConnectionStatus.PERFORMING)
|
||||
updatePumpStatus(s.sAction);
|
||||
else if (s.sStatus == EventDanaRConnectionStatus.DISCONNECTED)
|
||||
updatePumpStatus(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void hideTempRecommendation() {
|
||||
Activity activity = getActivity();
|
||||
|
@ -436,13 +515,48 @@ public class OverviewFragment extends Fragment {
|
|||
});
|
||||
}
|
||||
|
||||
private void updatePumpStatus(String status) {
|
||||
PumpInterface pump = MainApp.getConfigBuilder();
|
||||
if (status != null) {
|
||||
pumpStatusView.setText(status);
|
||||
pumpStatusView.setVisibility(View.VISIBLE);
|
||||
} else if (pump.isBusy()) {
|
||||
pumpStatusView.setText(R.string.pumpbusy);
|
||||
pumpStatusView.setVisibility(View.VISIBLE);
|
||||
} else if (pump.isSuspended()) {
|
||||
// disable all treatment buttons because we are not able to check constraints without profile
|
||||
wizardButton.setVisibility(View.INVISIBLE);
|
||||
treatmentButton.setVisibility(View.INVISIBLE);
|
||||
quickWizardButton.setVisibility(View.INVISIBLE);
|
||||
pumpStatusView.setText(R.string.pumpsuspendedclicktorefresh);
|
||||
pumpStatusView.setVisibility(View.VISIBLE);
|
||||
} else if (!pump.isInitialized()) {
|
||||
// disable all treatment buttons because we are not able to check constraints without profile
|
||||
wizardButton.setVisibility(View.INVISIBLE);
|
||||
treatmentButton.setVisibility(View.INVISIBLE);
|
||||
quickWizardButton.setVisibility(View.INVISIBLE);
|
||||
pumpStatusView.setText(R.string.waitingforpumpclicktorefresh);
|
||||
pumpStatusView.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
wizardButton.setVisibility(View.VISIBLE);
|
||||
treatmentButton.setVisibility(View.VISIBLE);
|
||||
pumpStatusView.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
public void updateGUI() {
|
||||
updateNotifications();
|
||||
BgReading actualBG = MainApp.getDbHelper().actualBg();
|
||||
BgReading lastBG = MainApp.getDbHelper().lastBg();
|
||||
if (MainApp.getConfigBuilder() == null || MainApp.getConfigBuilder().getActiveProfile() == null) // app not initialized yet
|
||||
BgReading actualBG = GlucoseStatus.actualBg();
|
||||
BgReading lastBG = GlucoseStatus.lastBg();
|
||||
|
||||
if (MainApp.getConfigBuilder() == null || MainApp.getConfigBuilder().getActiveProfile() == null || MainApp.getConfigBuilder().getActiveProfile().getProfile() == null) {// app not initialized yet
|
||||
pumpStatusView.setText(R.string.noprofileset);
|
||||
pumpStatusView.setVisibility(View.VISIBLE);
|
||||
return;
|
||||
} else {
|
||||
pumpStatusView.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
// Skip if not initialized yet
|
||||
if (bgGraph == null)
|
||||
|
@ -458,7 +572,7 @@ public class OverviewFragment extends Fragment {
|
|||
apsModeView.setBackgroundResource(R.drawable.loopmodeborder);
|
||||
apsModeView.setTextColor(Color.BLACK);
|
||||
final LoopPlugin activeloop = MainApp.getConfigBuilder().getActiveLoop();
|
||||
if(activeloop != null && activeloop.isEnabled(activeloop.getType())) {
|
||||
if (activeloop != null && activeloop.isEnabled(activeloop.getType())) {
|
||||
if (MainApp.getConfigBuilder().isClosedModeEnabled()) {
|
||||
apsModeView.setText(MainApp.sResources.getString(R.string.closedloop));
|
||||
} else {
|
||||
|
@ -476,10 +590,10 @@ public class OverviewFragment extends Fragment {
|
|||
@Override
|
||||
public boolean onLongClick(View view) {
|
||||
view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
|
||||
if (activeloop == null){
|
||||
if (activeloop == null) {
|
||||
log.error("no active loop?");
|
||||
return true;
|
||||
} else if (activeloop.isEnabled(PluginBase.LOOP)){
|
||||
} else if (activeloop.isEnabled(PluginBase.LOOP)) {
|
||||
activeloop.setFragmentEnabled(PluginBase.LOOP, false);
|
||||
activeloop.setFragmentVisible(PluginBase.LOOP, false);
|
||||
} else {
|
||||
|
@ -497,8 +611,34 @@ public class OverviewFragment extends Fragment {
|
|||
apsModeView.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
// **** Temp button ****
|
||||
// temp target
|
||||
NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile();
|
||||
TempTargetRangePlugin tempTargetRangePlugin = (TempTargetRangePlugin) MainApp.getSpecificPlugin(TempTargetRangePlugin.class);
|
||||
if (Config.APS && tempTargetRangePlugin != null && tempTargetRangePlugin.isEnabled(PluginBase.GENERAL)) {
|
||||
TempTarget tempTarget = tempTargetRangePlugin.getTempTargetInProgress(new Date().getTime());
|
||||
if (tempTarget != null) {
|
||||
tempTargetView.setTextColor(Color.BLACK);
|
||||
tempTargetView.setBackgroundResource(R.drawable.temptargetborder);
|
||||
tempTargetView.setVisibility(View.VISIBLE);
|
||||
tempTargetView.setText(NSProfile.toUnitsString(tempTarget.low, NSProfile.fromMgdlToUnits(tempTarget.low, profile.getUnits()), profile.getUnits()) + " - " + NSProfile.toUnitsString(tempTarget.high, NSProfile.fromMgdlToUnits(tempTarget.high, profile.getUnits()), profile.getUnits()));
|
||||
} else {
|
||||
|
||||
String maxBgDefault = Constants.MAX_BG_DEFAULT_MGDL;
|
||||
String minBgDefault = Constants.MIN_BG_DEFAULT_MGDL;
|
||||
if (!profile.getUnits().equals(Constants.MGDL)) {
|
||||
maxBgDefault = Constants.MAX_BG_DEFAULT_MMOL;
|
||||
minBgDefault = Constants.MIN_BG_DEFAULT_MMOL;
|
||||
}
|
||||
tempTargetView.setTextColor(Color.WHITE);
|
||||
tempTargetView.setBackgroundResource(R.drawable.temptargetborderdisabled);
|
||||
tempTargetView.setText(prefs.getString("openapsma_min_bg", minBgDefault) + " - " + prefs.getString("openapsma_max_bg", maxBgDefault));
|
||||
tempTargetView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
} else {
|
||||
tempTargetView.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
// **** Temp button ****
|
||||
PumpInterface pump = MainApp.getConfigBuilder();
|
||||
|
||||
boolean showAcceptButton = !MainApp.getConfigBuilder().isClosedModeEnabled(); // Open mode needed
|
||||
|
@ -506,15 +646,22 @@ public class OverviewFragment extends Fragment {
|
|||
showAcceptButton = showAcceptButton && (finalLastRun.lastOpenModeAccept == null || finalLastRun.lastOpenModeAccept.getTime() < finalLastRun.lastAPSRun.getTime()); // never accepted or before last result
|
||||
showAcceptButton = showAcceptButton && finalLastRun.constraintsProcessed.changeRequested; // change is requested
|
||||
|
||||
if (showAcceptButton && pump.isInitialized()) {
|
||||
if (showAcceptButton && pump.isInitialized() && !pump.isSuspended() && ConfigBuilderPlugin.getActiveLoop() != null) {
|
||||
acceptTempLayout.setVisibility(View.VISIBLE);
|
||||
acceptTempButton.setText(getContext().getString(R.string.setbasalquestion) + "\n" + finalLastRun.constraintsProcessed);
|
||||
} else {
|
||||
acceptTempLayout.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
// **** Calibration button ****
|
||||
if (MainApp.getSpecificPlugin(SourceXdripPlugin.class).isEnabled(PluginBase.BGSOURCE) && profile != null && GlucoseStatus.actualBg() != null) {
|
||||
calibrationButton.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
calibrationButton.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
TempBasal activeTemp = pump.getTempBasal();
|
||||
if (pump.isTempBasalInProgress()) {
|
||||
TempBasal activeTemp = pump.getTempBasal();
|
||||
cancelTempLayout.setVisibility(View.VISIBLE);
|
||||
cancelTempButton.setText(MainApp.instance().getString(R.string.cancel) + ": " + activeTemp.toString());
|
||||
runningTempView.setVisibility(View.VISIBLE);
|
||||
|
@ -539,7 +686,7 @@ public class OverviewFragment extends Fragment {
|
|||
public boolean onLongClick(View view) {
|
||||
view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
|
||||
NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog();
|
||||
final OptionsToShow profileswitch = new OptionsToShow(R.id.careportal_profileswitch, R.string.careportal_profileswitch, true, false, false, false, false, false, false, true, false);
|
||||
final OptionsToShow profileswitch = new OptionsToShow(R.id.careportal_profileswitch, R.string.careportal_profileswitch, true, false, false, false, false, false, false, true, false, false);
|
||||
profileswitch.executeProfileSwitch = true;
|
||||
newDialog.setOptions(profileswitch);
|
||||
newDialog.show(getFragmentManager(), "NewNSTreatmentDialog");
|
||||
|
@ -548,40 +695,46 @@ public class OverviewFragment extends Fragment {
|
|||
});
|
||||
activeProfileView.setLongClickable(true);
|
||||
|
||||
if (profile == null || !pump.isInitialized()) {
|
||||
// disable all treatment buttons because we are not able to check constraints without profile
|
||||
wizardButton.setVisibility(View.INVISIBLE);
|
||||
treatmentButton.setVisibility(View.INVISIBLE);
|
||||
return;
|
||||
} else {
|
||||
wizardButton.setVisibility(View.VISIBLE);
|
||||
treatmentButton.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
String units = profile.getUnits();
|
||||
tempTargetView.setOnLongClickListener(new View.OnLongClickListener() {
|
||||
@Override
|
||||
public boolean onLongClick(View view) {
|
||||
view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
|
||||
NewNSTreatmentDialog newTTDialog = new NewNSTreatmentDialog();
|
||||
final OptionsToShow temptarget = new OptionsToShow(R.id.careportal_temporarytarget, R.string.careportal_temporarytarget, false, false, false, false, true, false, false, false, false, true);
|
||||
temptarget.executeTempTarget = true;
|
||||
newTTDialog.setOptions(temptarget);
|
||||
newTTDialog.show(getFragmentManager(), "NewNSTreatmentDialog");
|
||||
return true;
|
||||
}
|
||||
});
|
||||
tempTargetView.setLongClickable(true);
|
||||
|
||||
// QuickWizard button
|
||||
QuickWizard.QuickWizardEntry quickWizardEntry = getPlugin().quickWizard.getActive();
|
||||
if (quickWizardEntry != null && lastBG != null && pump.isInitialized()) {
|
||||
quickWizardLayout.setVisibility(View.VISIBLE);
|
||||
if (quickWizardEntry != null && lastBG != null && pump.isInitialized() && !pump.isSuspended()) {
|
||||
quickWizardButton.setVisibility(View.VISIBLE);
|
||||
String text = MainApp.sResources.getString(R.string.bolus) + ": " + quickWizardEntry.buttonText() + " " + DecimalFormatter.to0Decimal(quickWizardEntry.carbs()) + "g";
|
||||
BolusWizard wizard = new BolusWizard();
|
||||
wizard.doCalc(profile.getDefaultProfile(), quickWizardEntry.carbs(), lastBG.valueToUnits(profile.getUnits()), 0d, true, true);
|
||||
text += " " + DecimalFormatter.to2Decimal(wizard.calculatedTotalInsulin) + "U";
|
||||
quickWizardButton.setText(text);
|
||||
if (wizard.calculatedTotalInsulin <= 0)
|
||||
quickWizardLayout.setVisibility(View.GONE);
|
||||
quickWizardButton.setVisibility(View.GONE);
|
||||
} else
|
||||
quickWizardLayout.setVisibility(View.GONE);
|
||||
quickWizardButton.setVisibility(View.GONE);
|
||||
|
||||
String units = profile.getUnits();
|
||||
|
||||
// **** BG value ****
|
||||
if (lastBG != null && bgView != null) {
|
||||
if (lastBG != null) {
|
||||
bgView.setText(lastBG.valueToUnitsToString(profile.getUnits()));
|
||||
arrowView.setText(lastBG.directionToSymbol());
|
||||
DatabaseHelper.GlucoseStatus glucoseStatus = MainApp.getDbHelper().getGlucoseStatusData();
|
||||
if (glucoseStatus != null){
|
||||
GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData();
|
||||
if (glucoseStatus != null) {
|
||||
deltaView.setText("Δ " + NSProfile.toUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units) + " " + units);
|
||||
avgdeltaView.setText("øΔ " + NSProfile.toUnitsString(glucoseStatus.avgdelta, glucoseStatus.avgdelta * Constants.MGDL_TO_MMOLL, units) + " " + units);
|
||||
avgdeltaView.setText("øΔ15m: " + NSProfile.toUnitsString(glucoseStatus.short_avgdelta, glucoseStatus.short_avgdelta * Constants.MGDL_TO_MMOLL, units) +
|
||||
" øΔ40m: " + NSProfile.toUnitsString(glucoseStatus.long_avgdelta, glucoseStatus.long_avgdelta * Constants.MGDL_TO_MMOLL, units));
|
||||
}
|
||||
|
||||
BgReading.units = profile.getUnits();
|
||||
|
@ -602,16 +755,21 @@ public class OverviewFragment extends Fragment {
|
|||
// iob
|
||||
MainApp.getConfigBuilder().getActiveTreatments().updateTotalIOB();
|
||||
IobTotal bolusIob = MainApp.getConfigBuilder().getActiveTreatments().getLastCalculation().round();
|
||||
if (bolusIob == null) bolusIob = new IobTotal();
|
||||
MainApp.getConfigBuilder().getActiveTempBasals().updateTotalIOB();
|
||||
IobTotal basalIob = MainApp.getConfigBuilder().getActiveTempBasals().getLastCalculation().round();
|
||||
if (basalIob == null) basalIob = new IobTotal();
|
||||
|
||||
String iobtext = getString(R.string.treatments_iob_label_string) + " " + DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U ("
|
||||
+ getString(R.string.bolus) + ": " + DecimalFormatter.to2Decimal(bolusIob.iob) + "U "
|
||||
+ getString(R.string.basal) + ": " + DecimalFormatter.to2Decimal(basalIob.basaliob) + "U)";
|
||||
iobView.setText(iobtext);
|
||||
|
||||
boolean showPrediction = showPredictionView.isChecked() && finalLastRun != null && finalLastRun.constraintsProcessed.getClass().equals(DetermineBasalResultAMA.class);
|
||||
if (MainApp.getSpecificPlugin(OpenAPSAMAPlugin.class) != null && MainApp.getSpecificPlugin(OpenAPSAMAPlugin.class).isEnabled(PluginBase.APS)) {
|
||||
showPredictionView.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
showPredictionView.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
// ****** GRAPH *******
|
||||
|
||||
// allign to hours
|
||||
|
@ -622,27 +780,44 @@ public class OverviewFragment extends Fragment {
|
|||
calendar.set(Calendar.MINUTE, 0);
|
||||
calendar.add(Calendar.HOUR, 1);
|
||||
|
||||
int hoursToFetch = 6;
|
||||
long toTime = calendar.getTimeInMillis() + 100000; // little bit more to avoid wrong rounding
|
||||
long fromTime = toTime - hoursToFetch * 60 * 60 * 1000L;
|
||||
int hoursToFetch;
|
||||
long toTime;
|
||||
long fromTime;
|
||||
long endTime;
|
||||
if (showPrediction) {
|
||||
int predHours = (int) (Math.ceil(((DetermineBasalResultAMA) finalLastRun.constraintsProcessed).getLatestPredictionsTime() - new Date().getTime()) / (60 * 60 * 1000));
|
||||
predHours = Math.min(2, predHours);
|
||||
predHours = Math.max(0, predHours);
|
||||
hoursToFetch = (int) (6 - predHours);
|
||||
toTime = calendar.getTimeInMillis() + 100000; // little bit more to avoid wrong rounding
|
||||
fromTime = toTime - hoursToFetch * 60 * 60 * 1000L;
|
||||
endTime = toTime + predHours * 60 * 60 * 1000L;
|
||||
} else {
|
||||
hoursToFetch = 6;
|
||||
toTime = calendar.getTimeInMillis() + 100000; // little bit more to avoid wrong rounding
|
||||
fromTime = toTime - hoursToFetch * 60 * 60 * 1000L;
|
||||
endTime = toTime;
|
||||
}
|
||||
|
||||
Double lowLine = SafeParse.stringToDouble(prefs.getString("low_mark", "0"));
|
||||
Double highLine = SafeParse.stringToDouble(prefs.getString("high_mark", "0"));
|
||||
|
||||
if (lowLine < 1){
|
||||
if (lowLine < 1) {
|
||||
lowLine = NSProfile.fromMgdlToUnits(OverviewPlugin.bgTargetLow, units);
|
||||
}
|
||||
|
||||
if(highLine < 1){
|
||||
if (highLine < 1) {
|
||||
highLine = NSProfile.fromMgdlToUnits(OverviewPlugin.bgTargetHigh, units);
|
||||
}
|
||||
|
||||
LineGraphSeries<DataPoint> basalsLineSeries = null;
|
||||
BarGraphSeries<DataPoint> basalsSeries = null;
|
||||
LineGraphSeries<DataPoint> seriesLow = null;
|
||||
LineGraphSeries<DataPoint> seriesHigh = null;
|
||||
LineGraphSeries<DataPoint> seriesNow = null;
|
||||
PointsGraphSeries<BgReading> seriesInRage = null;
|
||||
PointsGraphSeries<BgReading> seriesOutOfRange = null;
|
||||
PointsGraphSeries<BgReading> predSeries = null;
|
||||
PointsWithLabelGraphSeries<Treatment> seriesTreatments = null;
|
||||
|
||||
// remove old data from graph
|
||||
|
@ -651,11 +826,11 @@ public class OverviewFragment extends Fragment {
|
|||
// **** HIGH and LOW targets graph ****
|
||||
DataPoint[] lowDataPoints = new DataPoint[]{
|
||||
new DataPoint(fromTime, lowLine),
|
||||
new DataPoint(toTime, lowLine)
|
||||
new DataPoint(endTime, lowLine)
|
||||
};
|
||||
DataPoint[] highDataPoints = new DataPoint[]{
|
||||
new DataPoint(fromTime, highLine),
|
||||
new DataPoint(toTime, highLine)
|
||||
new DataPoint(endTime, highLine)
|
||||
};
|
||||
bgGraph.addSeries(seriesLow = new LineGraphSeries<DataPoint>(lowDataPoints));
|
||||
seriesLow.setColor(Color.RED);
|
||||
|
@ -672,19 +847,26 @@ public class OverviewFragment extends Fragment {
|
|||
public boolean isTempBasal = false;
|
||||
}
|
||||
|
||||
Double maxAllowedBasal = MainApp.getConfigBuilder().applyBasalConstraints(Constants.basalAbsoluteOnlyForCheckLimit);
|
||||
Double maxBasalValueFound = 0d;
|
||||
|
||||
long now = new Date().getTime();
|
||||
if (pump.getPumpDescription().isTempBasalCapable) {
|
||||
List<BarDataPoint> basalArray = new ArrayList<BarDataPoint>();
|
||||
List<DataPoint> basalLineArray = new ArrayList<DataPoint>();
|
||||
double lastBaseBasal = 0;
|
||||
for (long time = fromTime; time < now; time += 5 * 60 * 1000L) {
|
||||
TempBasal tb = MainApp.getConfigBuilder().getTempBasal(new Date(time));
|
||||
double basebasal = profile.getBasal(NSProfile.secondsFromMidnight(new Date(time)));
|
||||
Double basal = 0d;
|
||||
if (tb != null)
|
||||
basalArray.add(new BarDataPoint(time, basal = tb.tempBasalConvertedToAbsolute(new Date(time)), true));
|
||||
else
|
||||
basalArray.add(new BarDataPoint(time, basal = profile.getBasal(NSProfile.secondsFromMidnight(new Date(time))), false));
|
||||
else {
|
||||
basalArray.add(new BarDataPoint(time, basal = basebasal, false));
|
||||
}
|
||||
if (basebasal != lastBaseBasal)
|
||||
basalLineArray.add(new DataPoint(time, lastBaseBasal));
|
||||
basalLineArray.add(new DataPoint(time, basebasal));
|
||||
lastBaseBasal = basebasal;
|
||||
maxBasalValueFound = Math.max(maxBasalValueFound, basal);
|
||||
}
|
||||
BarDataPoint[] basal = new BarDataPoint[basalArray.size()];
|
||||
|
@ -698,17 +880,23 @@ public class OverviewFragment extends Fragment {
|
|||
else return Color.CYAN;
|
||||
}
|
||||
});
|
||||
DataPoint[] basalLine = new DataPoint[basalLineArray.size()];
|
||||
basalLine = basalLineArray.toArray(basalLine);
|
||||
bgGraph.addSeries(basalsLineSeries = new LineGraphSeries<DataPoint>(basalLine));
|
||||
basalsLineSeries.setColor(Color.CYAN);
|
||||
basalsLineSeries.setDrawDataPoints(false);
|
||||
basalsLineSeries.setThickness(2);
|
||||
}
|
||||
|
||||
// set manual x bounds to have nice steps
|
||||
bgGraph.getViewport().setMaxX(toTime);
|
||||
bgGraph.getViewport().setMaxX(endTime);
|
||||
bgGraph.getViewport().setMinX(fromTime);
|
||||
bgGraph.getViewport().setXAxisBoundsManual(true);
|
||||
bgGraph.getGridLabelRenderer().setLabelFormatter(new TimeAsXAxisLabelFormatter(getActivity(), "HH"));
|
||||
bgGraph.getGridLabelRenderer().setNumHorizontalLabels(7); // only 7 because of the space
|
||||
|
||||
// **** BG graph ****
|
||||
List<BgReading> bgReadingsArray = MainApp.getDbHelper().getDataFromTime(fromTime);
|
||||
List<BgReading> bgReadingsArray = MainApp.getDbHelper().getBgreadingsDataFromTime(fromTime, true);
|
||||
List<BgReading> inRangeArray = new ArrayList<BgReading>();
|
||||
List<BgReading> outOfRangeArray = new ArrayList<BgReading>();
|
||||
|
||||
|
@ -727,7 +915,7 @@ public class OverviewFragment extends Fragment {
|
|||
}
|
||||
maxBgValue = NSProfile.fromMgdlToUnits(maxBgValue, units);
|
||||
maxBgValue = units.equals(Constants.MGDL) ? Round.roundTo(maxBgValue, 40d) + 80 : Round.roundTo(maxBgValue, 2d) + 4;
|
||||
if(highLine > maxBgValue) maxBgValue = highLine;
|
||||
if (highLine > maxBgValue) maxBgValue = highLine;
|
||||
Integer numOfHorizLines = units.equals(Constants.MGDL) ? (int) (maxBgValue / 40 + 1) : (int) (maxBgValue / 2 + 1);
|
||||
|
||||
BgReading[] inRange = new BgReading[inRangeArray.size()];
|
||||
|
@ -750,6 +938,19 @@ public class OverviewFragment extends Fragment {
|
|||
seriesOutOfRange.setColor(Color.RED);
|
||||
}
|
||||
|
||||
if (showPrediction) {
|
||||
DetermineBasalResultAMA amaResult = (DetermineBasalResultAMA) finalLastRun.constraintsProcessed;
|
||||
List<BgReading> predArray = amaResult.getPredictions();
|
||||
BgReading[] pred = new BgReading[predArray.size()];
|
||||
pred = predArray.toArray(pred);
|
||||
if (pred.length > 0) {
|
||||
bgGraph.addSeries(predSeries = new PointsGraphSeries<BgReading>(pred));
|
||||
predSeries.setShape(PointsGraphSeries.Shape.POINT);
|
||||
predSeries.setSize(4);
|
||||
predSeries.setColor(Color.MAGENTA);
|
||||
}
|
||||
}
|
||||
|
||||
// **** NOW line ****
|
||||
DataPoint[] nowPoints = new DataPoint[]{
|
||||
new DataPoint(now, 0),
|
||||
|
@ -762,8 +963,8 @@ public class OverviewFragment extends Fragment {
|
|||
// custom paint to make a dotted line
|
||||
Paint paint = new Paint();
|
||||
paint.setStyle(Paint.Style.STROKE);
|
||||
paint.setStrokeWidth(1);
|
||||
paint.setPathEffect(new DashPathEffect(new float[]{4, 20}, 0));
|
||||
paint.setStrokeWidth(2);
|
||||
paint.setPathEffect(new DashPathEffect(new float[]{10, 20}, 0));
|
||||
paint.setColor(Color.WHITE);
|
||||
seriesNow.setCustomPaint(paint);
|
||||
|
||||
|
@ -796,12 +997,13 @@ public class OverviewFragment extends Fragment {
|
|||
// set second scale
|
||||
if (pump.getPumpDescription().isTempBasalCapable) {
|
||||
bgGraph.getSecondScale().addSeries(basalsSeries);
|
||||
bgGraph.getSecondScale().addSeries(basalsLineSeries);
|
||||
bgGraph.getSecondScale().setMinY(0);
|
||||
bgGraph.getSecondScale().setMaxY(maxBgValue / lowLine * maxBasalValueFound * 1.2d);
|
||||
bgGraph.getGridLabelRenderer().setVerticalLabelsSecondScaleColor(MainApp.instance().getResources().getColor(R.color.background_material_dark)); // same color as backround = hide
|
||||
bgGraph.getGridLabelRenderer().setVerticalLabelsSecondScaleColor(ContextCompat.getColor(MainApp.instance(), R.color.background_material_dark)); // same color as backround = hide
|
||||
}
|
||||
|
||||
|
||||
updatePumpStatus(null);
|
||||
}
|
||||
|
||||
//Notifications
|
||||
|
@ -827,13 +1029,13 @@ public class OverviewFragment extends Fragment {
|
|||
holder.text.setText(notification.text);
|
||||
holder.time.setText(DateUtil.timeString(notification.date));
|
||||
if (notification.level == Notification.URGENT)
|
||||
holder.cv.setBackgroundColor(MainApp.instance().getResources().getColor(R.color.notificationUrgent));
|
||||
holder.cv.setBackgroundColor(ContextCompat.getColor(MainApp.instance(), R.color.notificationUrgent));
|
||||
else if (notification.level == Notification.NORMAL)
|
||||
holder.cv.setBackgroundColor(MainApp.instance().getResources().getColor(R.color.notificationNormal));
|
||||
holder.cv.setBackgroundColor(ContextCompat.getColor(MainApp.instance(), R.color.notificationNormal));
|
||||
else if (notification.level == Notification.LOW)
|
||||
holder.cv.setBackgroundColor(MainApp.instance().getResources().getColor(R.color.notificationLow));
|
||||
holder.cv.setBackgroundColor(ContextCompat.getColor(MainApp.instance(), R.color.notificationLow));
|
||||
else if (notification.level == Notification.INFO)
|
||||
holder.cv.setBackgroundColor(MainApp.instance().getResources().getColor(R.color.notificationInfo));
|
||||
holder.cv.setBackgroundColor(ContextCompat.getColor(MainApp.instance(), R.color.notificationInfo));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -893,5 +1095,4 @@ public class OverviewFragment extends Fragment {
|
|||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -47,6 +47,17 @@ public class OverviewPlugin implements PluginBase {
|
|||
return MainApp.instance().getString(R.string.overview);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNameShort() {
|
||||
String name = MainApp.sResources.getString(R.string.overview_shortname);
|
||||
if (!name.trim().isEmpty()){
|
||||
//only if translation exists
|
||||
return name;
|
||||
}
|
||||
// use long name as fallback
|
||||
return getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(int type) {
|
||||
return type == GENERAL;
|
||||
|
|
|
@ -38,6 +38,12 @@ public class SafetyPlugin implements PluginBase, ConstraintsInterface {
|
|||
return MainApp.instance().getString(R.string.safety);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNameShort() {
|
||||
// use long name as fallback (no tabs)
|
||||
return getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(int type) {
|
||||
return type == CONSTRAINTS;
|
||||
|
@ -97,8 +103,8 @@ public class SafetyPlugin implements PluginBase, ConstraintsInterface {
|
|||
if (profile == null) return absoluteRate;
|
||||
if (absoluteRate < 0) absoluteRate = 0d;
|
||||
|
||||
Integer maxBasalMult = 4;
|
||||
Integer maxBasalFromDaily = 3;
|
||||
Integer maxBasalMult = SafeParse.stringToInt(SP.getString("openapsama_current_basal_safety_multiplier", "4"));
|
||||
Integer maxBasalFromDaily = SafeParse.stringToInt(SP.getString("openapsama_max_daily_safety_multiplier", "3"));
|
||||
// Check percentRate but absolute rate too, because we know real current basal in pump
|
||||
Double origRate = absoluteRate;
|
||||
if (absoluteRate > maxBasal) {
|
||||
|
@ -136,8 +142,8 @@ public class SafetyPlugin implements PluginBase, ConstraintsInterface {
|
|||
|
||||
if (absoluteRate < 0) absoluteRate = 0d;
|
||||
|
||||
Integer maxBasalMult = 4;
|
||||
Integer maxBasalFromDaily = 3;
|
||||
Integer maxBasalMult = SafeParse.stringToInt(SP.getString("openapsama_current_basal_safety_multiplier", "4"));
|
||||
Integer maxBasalFromDaily = SafeParse.stringToInt(SP.getString("openapsama_max_daily_safety_multiplier", "3"));
|
||||
// Check percentRate but absolute rate too, because we know real current basal in pump
|
||||
Double origRate = absoluteRate;
|
||||
if (absoluteRate > maxBasal) {
|
||||
|
@ -185,7 +191,7 @@ public class SafetyPlugin implements PluginBase, ConstraintsInterface {
|
|||
public Integer applyCarbsConstraints(Integer carbs) {
|
||||
SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
|
||||
try {
|
||||
Integer maxCarbs = Integer.parseInt(SP.getString("treatmentssafety_maxcarbs", "48"));
|
||||
Integer maxCarbs = SafeParse.stringToInt(SP.getString("treatmentssafety_maxcarbs", "48"));
|
||||
|
||||
if (carbs < 0) carbs = 0;
|
||||
if (carbs > maxCarbs) carbs = maxCarbs;
|
||||
|
|
|
@ -48,7 +48,6 @@ public class SimpleProfileFragment extends Fragment implements FragmentBase {
|
|||
RadioButton mmolView;
|
||||
EditText icView;
|
||||
EditText isfView;
|
||||
EditText carView;
|
||||
EditText basalView;
|
||||
EditText targetlowView;
|
||||
EditText targethighView;
|
||||
|
@ -63,7 +62,6 @@ public class SimpleProfileFragment extends Fragment implements FragmentBase {
|
|||
mmolView = (RadioButton) layout.findViewById(R.id.simpleprofile_mmol);
|
||||
icView = (EditText) layout.findViewById(R.id.simpleprofile_ic);
|
||||
isfView = (EditText) layout.findViewById(R.id.simpleprofile_isf);
|
||||
carView = (EditText) layout.findViewById(R.id.simpleprofile_car);
|
||||
basalView = (EditText) layout.findViewById(R.id.simpleprofile_basalrate);
|
||||
targetlowView = (EditText) layout.findViewById(R.id.simpleprofile_targetlow);
|
||||
targethighView = (EditText) layout.findViewById(R.id.simpleprofile_targethigh);
|
||||
|
@ -82,7 +80,6 @@ public class SimpleProfileFragment extends Fragment implements FragmentBase {
|
|||
diaView.setText(simpleProfilePlugin.dia.toString());
|
||||
icView.setText(simpleProfilePlugin.ic.toString());
|
||||
isfView.setText(simpleProfilePlugin.isf.toString());
|
||||
carView.setText(simpleProfilePlugin.car.toString());
|
||||
basalView.setText(simpleProfilePlugin.basal.toString());
|
||||
targetlowView.setText(simpleProfilePlugin.targetLow.toString());
|
||||
targethighView.setText(simpleProfilePlugin.targetHigh.toString());
|
||||
|
@ -110,7 +107,7 @@ public class SimpleProfileFragment extends Fragment implements FragmentBase {
|
|||
@Override
|
||||
public void onClick(View view) {
|
||||
NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog();
|
||||
final OptionsToShow profileswitch = new OptionsToShow(R.id.careportal_profileswitch, R.string.careportal_profileswitch, true, false, false, false, false, false, false, true, false);
|
||||
final OptionsToShow profileswitch = new OptionsToShow(R.id.careportal_profileswitch, R.string.careportal_profileswitch, true, false, false, false, false, false, false, true, false, false);
|
||||
profileswitch.executeProfileSwitch = true;
|
||||
newDialog.setOptions(profileswitch);
|
||||
newDialog.show(getFragmentManager(), "NewNSTreatmentDialog");
|
||||
|
@ -134,7 +131,6 @@ public class SimpleProfileFragment extends Fragment implements FragmentBase {
|
|||
simpleProfilePlugin.dia = SafeParse.stringToDouble(diaView.getText().toString());
|
||||
simpleProfilePlugin.ic = SafeParse.stringToDouble(icView.getText().toString());
|
||||
simpleProfilePlugin.isf = SafeParse.stringToDouble(isfView.getText().toString());
|
||||
simpleProfilePlugin.car = SafeParse.stringToDouble(carView.getText().toString());
|
||||
simpleProfilePlugin.basal = SafeParse.stringToDouble(basalView.getText().toString());
|
||||
simpleProfilePlugin.targetLow = SafeParse.stringToDouble(targetlowView.getText().toString());
|
||||
simpleProfilePlugin.targetHigh = SafeParse.stringToDouble(targethighView.getText().toString());
|
||||
|
@ -145,7 +141,6 @@ public class SimpleProfileFragment extends Fragment implements FragmentBase {
|
|||
diaView.addTextChangedListener(textWatch);
|
||||
icView.addTextChangedListener(textWatch);
|
||||
isfView.addTextChangedListener(textWatch);
|
||||
carView.addTextChangedListener(textWatch);
|
||||
basalView.addTextChangedListener(textWatch);
|
||||
targetlowView.addTextChangedListener(textWatch);
|
||||
targethighView.addTextChangedListener(textWatch);
|
||||
|
@ -175,7 +170,7 @@ public class SimpleProfileFragment extends Fragment implements FragmentBase {
|
|||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!MainApp.getConfigBuilder().isInitialized() || !MainApp.getConfigBuilder().getPumpDescription().isSetBasalProfileCapable) {
|
||||
if (!MainApp.getConfigBuilder().isInitialized() || MainApp.getConfigBuilder().isSuspended() || !MainApp.getConfigBuilder().getPumpDescription().isSetBasalProfileCapable) {
|
||||
profileswitchButton.setVisibility(View.GONE);
|
||||
} else {
|
||||
profileswitchButton.setVisibility(View.VISIBLE);
|
||||
|
|
|
@ -34,7 +34,6 @@ public class SimpleProfilePlugin implements PluginBase, ProfileInterface {
|
|||
Double dia;
|
||||
Double ic;
|
||||
Double isf;
|
||||
Double car;
|
||||
Double basal;
|
||||
Double targetLow;
|
||||
Double targetHigh;
|
||||
|
@ -58,6 +57,17 @@ public class SimpleProfilePlugin implements PluginBase, ProfileInterface {
|
|||
return MainApp.instance().getString(R.string.simpleprofile);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNameShort() {
|
||||
String name = MainApp.sResources.getString(R.string.simpleprofile_shortname);
|
||||
if (!name.trim().isEmpty()){
|
||||
//only if translation exists
|
||||
return name;
|
||||
}
|
||||
// use long name as fallback
|
||||
return getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(int type) {
|
||||
return type == PROFILE && fragmentEnabled;
|
||||
|
@ -93,7 +103,6 @@ public class SimpleProfilePlugin implements PluginBase, ProfileInterface {
|
|||
editor.putString("SimpleProfile" + "dia", dia.toString());
|
||||
editor.putString("SimpleProfile" + "ic", ic.toString());
|
||||
editor.putString("SimpleProfile" + "isf", isf.toString());
|
||||
editor.putString("SimpleProfile" + "car", car.toString());
|
||||
editor.putString("SimpleProfile" + "basal", basal.toString());
|
||||
editor.putString("SimpleProfile" + "targetlow", targetLow.toString());
|
||||
editor.putString("SimpleProfile" + "targethigh", targetHigh.toString());
|
||||
|
@ -142,13 +151,6 @@ public class SimpleProfilePlugin implements PluginBase, ProfileInterface {
|
|||
log.debug(e.getMessage());
|
||||
}
|
||||
else isf = 200d;
|
||||
if (settings.contains("SimpleProfile" + "car"))
|
||||
try {
|
||||
car = SafeParse.stringToDouble(settings.getString("SimpleProfile" + "car", "20"));
|
||||
} catch (Exception e) {
|
||||
log.debug(e.getMessage());
|
||||
}
|
||||
else car = 20d;
|
||||
if (settings.contains("SimpleProfile" + "basal"))
|
||||
try {
|
||||
basal = SafeParse.stringToDouble(settings.getString("SimpleProfile" + "basal", "1"));
|
||||
|
@ -221,7 +223,6 @@ public class SimpleProfilePlugin implements PluginBase, ProfileInterface {
|
|||
json.put("store", store);
|
||||
profile.put("dia", dia);
|
||||
profile.put("carbratio", new JSONArray().put(new JSONObject().put("timeAsSeconds", 0).put("value", ic)));
|
||||
profile.put("carbs_hr", car);
|
||||
profile.put("sens", new JSONArray().put(new JSONObject().put("timeAsSeconds", 0).put("value", isf)));
|
||||
profile.put("basal", new JSONArray().put(new JSONObject().put("timeAsSeconds", 0).put("value", basal)));
|
||||
profile.put("target_low", new JSONArray().put(new JSONObject().put("timeAsSeconds", 0).put("value", targetLow)));
|
||||
|
|
|
@ -21,21 +21,24 @@ 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.data.GlucoseStatus;
|
||||
import info.nightscout.androidaps.data.PumpEnactResult;
|
||||
import info.nightscout.androidaps.db.BgReading;
|
||||
import info.nightscout.androidaps.db.DatabaseHelper;
|
||||
import info.nightscout.androidaps.events.EventPreferenceChange;
|
||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||
import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPlugin;
|
||||
import info.nightscout.androidaps.plugins.Loop.LoopPlugin;
|
||||
import info.nightscout.androidaps.plugins.OpenAPSMA.IobTotal;
|
||||
import info.nightscout.androidaps.data.IobTotal;
|
||||
import info.nightscout.androidaps.plugins.Overview.Notification;
|
||||
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
|
||||
import info.nightscout.androidaps.plugins.SmsCommunicator.events.EventNewSMS;
|
||||
import info.nightscout.androidaps.plugins.SmsCommunicator.events.EventSmsCommunicatorUpdateGui;
|
||||
import info.nightscout.client.data.NSProfile;
|
||||
import info.nightscout.utils.DecimalFormatter;
|
||||
import info.nightscout.utils.SafeParse;
|
||||
import info.nightscout.utils.XdripCalibrations;
|
||||
|
||||
/**
|
||||
* Created by mike on 05.08.2016.
|
||||
|
@ -61,6 +64,7 @@ public class SmsCommunicatorPlugin implements PluginBase {
|
|||
String confirmCode;
|
||||
double bolusRequested = 0d;
|
||||
double tempBasal = 0d;
|
||||
double calibrationRequested = 0d;
|
||||
|
||||
public Sms(SmsMessage message) {
|
||||
phoneNumber = message.getOriginatingAddress();
|
||||
|
@ -92,6 +96,7 @@ public class SmsCommunicatorPlugin implements PluginBase {
|
|||
Sms cancelTempBasalWaitingForConfirmation = null;
|
||||
Sms tempBasalWaitingForConfirmation = null;
|
||||
Sms bolusWaitingForConfirmation = null;
|
||||
Sms calibrationWaitingForConfirmation = null;
|
||||
Date lastRemoteBolusTime = new Date(0);
|
||||
|
||||
ArrayList<Sms> messages = new ArrayList<>();
|
||||
|
@ -116,6 +121,17 @@ public class SmsCommunicatorPlugin implements PluginBase {
|
|||
return MainApp.sResources.getString(R.string.smscommunicator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNameShort() {
|
||||
String name = MainApp.sResources.getString(R.string.smscommunicator_shortname);
|
||||
if (!name.trim().isEmpty()) {
|
||||
//only if translation exists
|
||||
return name;
|
||||
}
|
||||
// use long name as fallback
|
||||
return getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(int type) {
|
||||
return type == GENERAL && fragmentEnabled;
|
||||
|
@ -199,8 +215,8 @@ public class SmsCommunicatorPlugin implements PluginBase {
|
|||
if (splited.length > 0) {
|
||||
switch (splited[0].toUpperCase()) {
|
||||
case "BG":
|
||||
BgReading actualBG = MainApp.getDbHelper().actualBg();
|
||||
BgReading lastBG = MainApp.getDbHelper().lastBg();
|
||||
BgReading actualBG = GlucoseStatus.actualBg();
|
||||
BgReading lastBG = GlucoseStatus.lastBg();
|
||||
|
||||
NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile();
|
||||
String units = profile.getUnits();
|
||||
|
@ -213,16 +229,14 @@ public class SmsCommunicatorPlugin implements PluginBase {
|
|||
} else if (lastBG != null) {
|
||||
reply = MainApp.sResources.getString(R.string.sms_lastbg) + " " + lastBG.valueToUnitsToString(units) + " " + String.format(MainApp.sResources.getString(R.string.sms_minago), agoMin) + ", ";
|
||||
}
|
||||
DatabaseHelper.GlucoseStatus glucoseStatus = MainApp.getDbHelper().getGlucoseStatusData();
|
||||
GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData();
|
||||
if (glucoseStatus != null)
|
||||
reply += MainApp.sResources.getString(R.string.sms_delta) + " " + NSProfile.toUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units) + " " + units + ", ";
|
||||
|
||||
MainApp.getConfigBuilder().getActiveTreatments().updateTotalIOB();
|
||||
IobTotal bolusIob = MainApp.getConfigBuilder().getActiveTreatments().getLastCalculation().round();
|
||||
if (bolusIob == null) bolusIob = new IobTotal();
|
||||
MainApp.getConfigBuilder().getActiveTempBasals().updateTotalIOB();
|
||||
IobTotal basalIob = MainApp.getConfigBuilder().getActiveTempBasals().getLastCalculation().round();
|
||||
if (basalIob == null) basalIob = new IobTotal();
|
||||
|
||||
reply += MainApp.sResources.getString(R.string.sms_iob) + " " + DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U ("
|
||||
+ MainApp.sResources.getString(R.string.sms_bolus) + " " + DecimalFormatter.to2Decimal(bolusIob.iob) + "U "
|
||||
|
@ -293,12 +307,12 @@ public class SmsCommunicatorPlugin implements PluginBase {
|
|||
case "DANAR":
|
||||
DanaRPlugin danaRPlugin = (DanaRPlugin) MainApp.getSpecificPlugin(DanaRPlugin.class);
|
||||
if (danaRPlugin != null && danaRPlugin.isEnabled(PluginBase.PUMP)) {
|
||||
reply = danaRPlugin.shortStatus();
|
||||
reply = danaRPlugin.shortStatus(true);
|
||||
sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date()));
|
||||
}
|
||||
DanaRKoreanPlugin danaRKoreanPlugin = (DanaRKoreanPlugin) MainApp.getSpecificPlugin(DanaRKoreanPlugin.class);
|
||||
if (danaRKoreanPlugin != null && danaRKoreanPlugin.isEnabled(PluginBase.PUMP)) {
|
||||
reply = danaRKoreanPlugin.shortStatus();
|
||||
reply = danaRKoreanPlugin.shortStatus(true);
|
||||
sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date()));
|
||||
}
|
||||
receivedSms.processed = true;
|
||||
|
@ -355,6 +369,23 @@ public class SmsCommunicatorPlugin implements PluginBase {
|
|||
}
|
||||
}
|
||||
break;
|
||||
case "CAL":
|
||||
if (splited.length > 1) {
|
||||
amount = SafeParse.stringToDouble(splited[1]);
|
||||
boolean remoteCommandsAllowed = sharedPreferences.getBoolean("smscommunicator_remotecommandsallowed", false);
|
||||
if (amount > 0d && remoteCommandsAllowed) {
|
||||
passCode = generatePasscode();
|
||||
reply = String.format(MainApp.sResources.getString(R.string.smscommunicator_calibrationreplywithcode), amount, passCode);
|
||||
receivedSms.processed = true;
|
||||
resetWaitingMessages();
|
||||
sendSMS(calibrationWaitingForConfirmation = new Sms(receivedSms.phoneNumber, reply, new Date(), passCode));
|
||||
calibrationWaitingForConfirmation.calibrationRequested = amount;
|
||||
} else {
|
||||
reply = MainApp.sResources.getString(R.string.smscommunicator_remotecalibrationnotallowed);
|
||||
sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date()));
|
||||
}
|
||||
}
|
||||
break;
|
||||
default: // expect passCode here
|
||||
if (bolusWaitingForConfirmation != null && !bolusWaitingForConfirmation.processed &&
|
||||
bolusWaitingForConfirmation.confirmCode.equals(splited[0]) && new Date().getTime() - bolusWaitingForConfirmation.date.getTime() < CONFIRM_TIMEOUT) {
|
||||
|
@ -365,12 +396,12 @@ public class SmsCommunicatorPlugin implements PluginBase {
|
|||
PumpEnactResult result = pumpInterface.deliverTreatment(bolusWaitingForConfirmation.bolusRequested, 0, null);
|
||||
if (result.success) {
|
||||
reply = String.format(MainApp.sResources.getString(R.string.smscommunicator_bolusdelivered), result.bolusDelivered);
|
||||
if (danaRPlugin != null) reply += "\n" + danaRPlugin.shortStatus();
|
||||
if (danaRPlugin != null) reply += "\n" + danaRPlugin.shortStatus(true);
|
||||
lastRemoteBolusTime = new Date();
|
||||
sendSMSToAllNumbers(new Sms(receivedSms.phoneNumber, reply, new Date()));
|
||||
} else {
|
||||
reply = MainApp.sResources.getString(R.string.smscommunicator_bolusfailed);
|
||||
if (danaRPlugin != null) reply += "\n" + danaRPlugin.shortStatus();
|
||||
if (danaRPlugin != null) reply += "\n" + danaRPlugin.shortStatus(true);
|
||||
sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date()));
|
||||
}
|
||||
}
|
||||
|
@ -383,11 +414,11 @@ public class SmsCommunicatorPlugin implements PluginBase {
|
|||
PumpEnactResult result = pumpInterface.setTempBasalAbsolute(tempBasalWaitingForConfirmation.tempBasal, 30);
|
||||
if (result.success) {
|
||||
reply = String.format(MainApp.sResources.getString(R.string.smscommunicator_tempbasalset), result.absolute, result.duration);
|
||||
if (danaRPlugin != null) reply += "\n" + danaRPlugin.shortStatus();
|
||||
if (danaRPlugin != null) reply += "\n" + danaRPlugin.shortStatus(true);
|
||||
sendSMSToAllNumbers(new Sms(receivedSms.phoneNumber, reply, new Date()));
|
||||
} else {
|
||||
reply = MainApp.sResources.getString(R.string.smscommunicator_tempbasalfailed);
|
||||
if (danaRPlugin != null) reply += "\n" + danaRPlugin.shortStatus();
|
||||
if (danaRPlugin != null) reply += "\n" + danaRPlugin.shortStatus(true);
|
||||
sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date()));
|
||||
}
|
||||
}
|
||||
|
@ -400,14 +431,25 @@ public class SmsCommunicatorPlugin implements PluginBase {
|
|||
PumpEnactResult result = pumpInterface.cancelTempBasal();
|
||||
if (result.success) {
|
||||
reply = String.format(MainApp.sResources.getString(R.string.smscommunicator_tempbasalcanceled));
|
||||
if (danaRPlugin != null) reply += "\n" + danaRPlugin.shortStatus();
|
||||
if (danaRPlugin != null) reply += "\n" + danaRPlugin.shortStatus(true);
|
||||
sendSMSToAllNumbers(new Sms(receivedSms.phoneNumber, reply, new Date()));
|
||||
} else {
|
||||
reply = MainApp.sResources.getString(R.string.smscommunicator_tempbasalcancelfailed);
|
||||
if (danaRPlugin != null) reply += "\n" + danaRPlugin.shortStatus();
|
||||
if (danaRPlugin != null) reply += "\n" + danaRPlugin.shortStatus(true);
|
||||
sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date()));
|
||||
}
|
||||
}
|
||||
} else if (calibrationWaitingForConfirmation != null && !calibrationWaitingForConfirmation.processed &&
|
||||
calibrationWaitingForConfirmation.confirmCode.equals(splited[0]) && new Date().getTime() - calibrationWaitingForConfirmation.date.getTime() < CONFIRM_TIMEOUT) {
|
||||
calibrationWaitingForConfirmation.processed = true;
|
||||
boolean result = XdripCalibrations.sendIntent(calibrationWaitingForConfirmation.calibrationRequested);
|
||||
if (result) {
|
||||
reply = String.format(MainApp.sResources.getString(R.string.smscommunicator_calibrationsent));
|
||||
sendSMSToAllNumbers(new Sms(receivedSms.phoneNumber, reply, new Date()));
|
||||
} else {
|
||||
reply = MainApp.sResources.getString(R.string.smscommunicator_calibrationfailed);
|
||||
sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date()));
|
||||
}
|
||||
} else {
|
||||
sendSMS(new Sms(receivedSms.phoneNumber, MainApp.sResources.getString(R.string.smscommunicator_unknowncommand), new Date()));
|
||||
}
|
||||
|
@ -437,8 +479,13 @@ public class SmsCommunicatorPlugin implements PluginBase {
|
|||
SmsManager smsManager = SmsManager.getDefault();
|
||||
sms.text = stripAccents(sms.text);
|
||||
if (sms.text.length() > 140) sms.text = sms.text.substring(0, 139);
|
||||
smsManager.sendTextMessage(sms.phoneNumber, null, sms.text, null, null);
|
||||
messages.add(sms);
|
||||
try {
|
||||
smsManager.sendTextMessage(sms.phoneNumber, null, sms.text, null, null);
|
||||
messages.add(sms);
|
||||
} catch (IllegalArgumentException e) {
|
||||
Notification notification = new Notification(Notification.INVALID_PHONE_NUMBER, MainApp.sResources.getString(R.string.smscommunicator_invalidphonennumber), Notification.NORMAL);
|
||||
MainApp.bus().post(new EventNewNotification(notification));
|
||||
}
|
||||
}
|
||||
|
||||
private String generatePasscode() {
|
||||
|
@ -455,6 +502,7 @@ public class SmsCommunicatorPlugin implements PluginBase {
|
|||
tempBasalWaitingForConfirmation = null;
|
||||
cancelTempBasalWaitingForConfirmation = null;
|
||||
bolusWaitingForConfirmation = null;
|
||||
calibrationWaitingForConfirmation = null;
|
||||
}
|
||||
|
||||
public static String stripAccents(String s) {
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue