Profile fragment

This commit is contained in:
Milos Kozak 2016-06-05 01:40:35 +02:00
parent 9b749202fd
commit 629ed62e03
29 changed files with 1733 additions and 9 deletions

View file

@ -37,7 +37,7 @@
<ConfirmationsSetting value="0" id="Add" />
<ConfirmationsSetting value="0" id="Remove" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">

View file

@ -24,5 +24,11 @@ dependencies {
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.4.0'
compile 'com.android.support:support-v4:23.4.0'
compile 'com.android.support:cardview-v7:23.0.+'
compile 'com.android.support:recyclerview-v7:23.0.+'}
compile 'com.android.support:cardview-v7:23.4.0'
compile 'com.android.support:recyclerview-v7:23.4.0'
compile 'com.squareup:otto:1.3.7'
compile 'com.j256.ormlite:ormlite-core:4.46'
compile 'com.j256.ormlite:ormlite-android:4.46'
compile 'com.github.tony19:logback-android-classic:1.1.1-4'
compile 'org.slf4j:slf4j-api:1.7.12'
}

View file

@ -2,19 +2,51 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="info.nightscout.androidaps">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:name=".MainApp"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:process=":mainProcess"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- Receiver from NSClient -->
<receiver
android:name="info.nightscout.client.receivers.NSClientDataReceiver"
android:enabled="true"
android:exported="true"
android:process=":mainProcess">
<intent-filter>
<action android:name="info.nightscout.client.NEW_TREATMENT" />
<action android:name="info.nightscout.client.CHANGED_TREATMENT" />
<action android:name="info.nightscout.client.REMOVED_TREATMENT" />
<action android:name="info.nightscout.client.NEW_PROFILE" />
<action android:name="info.nightscout.client.NEW_SGV" />
<action android:name="info.nightscout.client.NEW_STATUS" />
</intent-filter>
</receiver>
</application>
</manifest>

View file

@ -0,0 +1,35 @@
<configuration>
<!-- Create a file appender for a log in the application's data directory -->
<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>/storage/sdcard0/AndroidAPS/AndroidAPS.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- daily rollover. Make sure the path matches the one in the file element or else
the rollover logs are placed in the working directory. -->
<fileNamePattern>/storage/sdcard0/AndroidAPS/AndroidAPS._%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>5MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!-- keep 30 days' worth of history -->
<maxHistory>120</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<appender name="logcat" class="ch.qos.logback.classic.android.LogcatAppender">
<tagEncoder>
<pattern>%logger{0}</pattern>
</tagEncoder>
<encoder>
<pattern>[%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<!-- Write INFO (and higher-level) messages to the log file -->
<root level="DEBUG">
<appender-ref ref="file" />
<appender-ref ref="logcat" />
</root>
</configuration>

View file

@ -1,5 +1,7 @@
package info.nightscout.androidaps;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
@ -7,11 +9,19 @@ import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import info.nightscout.androidaps.plugins.ProfileViewer.ProfileViewerFragment;
import info.nightscout.androidaps.tabs.*;
import info.nightscout.androidaps.plugins.Objectives.ObjectivesFragment;
import info.nightscout.androidaps.plugins.Test.TestFragment;
import info.nightscout.client.broadcasts.Intents;
public class MainActivity extends AppCompatActivity implements ObjectivesFragment.OnFragmentInteractionListener {
private static Logger log = LoggerFactory.getLogger(MainActivity.class);
private Toolbar toolbar;
private SlidingTabLayout mTabs;
@ -26,6 +36,7 @@ public class MainActivity extends AppCompatActivity implements ObjectivesFragmen
// Register all tabs in app here
mAdapter = new TabPageAdapter(getSupportFragmentManager());
mAdapter.registerNewFragment("Test", TestFragment.newInstance());
mAdapter.registerNewFragment("Profile", ProfileViewerFragment.newInstance());
mAdapter.registerNewFragment("Objectives", ObjectivesFragment.newInstance());
toolbar = (Toolbar) findViewById(R.id.toolbar);
@ -34,7 +45,11 @@ public class MainActivity extends AppCompatActivity implements ObjectivesFragmen
mPager.setAdapter(mAdapter);
mTabs = (SlidingTabLayout) findViewById(R.id.tabs);
mTabs.setViewPager(mPager);
registerBus();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
@ -53,4 +68,15 @@ public class MainActivity extends AppCompatActivity implements ObjectivesFragmen
public void onFragmentInteraction(String param) {
}
private void registerBus() {
try {
MainApp.bus().unregister(this);
} catch (RuntimeException x) {
// Ignore
}
MainApp.bus().register(this);
}
}

View file

@ -0,0 +1,109 @@
package info.nightscout.androidaps;
import android.app.Application;
import android.content.SharedPreferences;
import com.j256.ormlite.android.apptools.OpenHelperManager;
import com.squareup.otto.Bus;
import com.squareup.otto.ThreadEnforcer;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Date;
import info.nightscout.androidaps.data.Pump;
import info.nightscout.client.data.NSProfile;
import info.nightscout.androidaps.db.DatabaseHelper;
public class MainApp extends Application {
private static Logger log = LoggerFactory.getLogger(MainApp.class);
public static final String PREFS_NAME = "NightscoutProfile";
private static Bus sBus;
private static MainApp sInstance;
private static NSProfile nsProfile = null;
private static String activeProfile = null;
private static Pump activePump = null;
private static DatabaseHelper databaseHelper = null;
@Override
public void onCreate() {
super.onCreate();
sBus = new Bus(ThreadEnforcer.ANY);
sInstance = this;
log.debug("Loading stored profile");
SharedPreferences store = getSharedPreferences(PREFS_NAME, 0);
activeProfile = store.getString("activeProfile", null);
String profileString = store.getString("profile", null);
if (profileString != null) {
try {
log.debug("Loaded profile: " + profileString);
log.debug("Loaded active profile: " + activeProfile);
setNSProfile(new NSProfile(new JSONObject(profileString), activeProfile));
} catch (JSONException e) {
}
} else
log.debug("Stored profile not found");
}
public static Bus bus() {
return sBus;
}
public static MainApp instance() {
return sInstance;
}
public static DatabaseHelper getDbHelper() {
if (databaseHelper == null) {
databaseHelper = OpenHelperManager.getHelper(sInstance, DatabaseHelper.class);
}
return databaseHelper;
}
public static void closeDbHelper() {
if (databaseHelper != null) {
databaseHelper.close();
databaseHelper = null;
}
}
@Override
public void onTerminate() {
super.onTerminate();
databaseHelper.close();
}
public static NSProfile getNSProfile() {
return nsProfile;
}
public static void setNSProfile(NSProfile profile) {
nsProfile = profile;
}
public static String getActiveProfile() {
return activeProfile;
}
public static void setActiveProfile(String activeprofile) {
activeProfile = activeprofile;
}
public static Pump getActivePump() {
return activePump;
}
public static void setActivePump(Pump activepump) {
activePump = activepump;
}
}

View file

@ -0,0 +1,10 @@
package info.nightscout.androidaps.data;
/**
* Created by mike on 04.06.2016.
*/
public abstract class Pump {
// Upload to pump new basal profile from MainApp.getNSProfile()
public abstract void setNewBasalProfile();
}

View file

@ -0,0 +1,92 @@
package info.nightscout.androidaps.db;
import java.sql.SQLException;
import java.util.List;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper;
import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.stmt.QueryBuilder;
import com.j256.ormlite.support.ConnectionSource;
import com.j256.ormlite.table.TableUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
private static Logger log = LoggerFactory.getLogger(DatabaseHelper.class);
public static final String DATABASE_NAME = "AndroidAPSDb";
private static final int DATABASE_VERSION = 1;
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase database, ConnectionSource connectionSource) {
try {
log.info("onCreate");
TableUtils.createTableIfNotExists(connectionSource, TempBasal.class);
TableUtils.createTableIfNotExists(connectionSource, Treatment.class);
// TODO: add bg support
} catch (SQLException e) {
log.error(DatabaseHelper.class.getName(), "Can't create database", e);
throw new RuntimeException(e);
}
}
@Override
public void onUpgrade(SQLiteDatabase database, ConnectionSource connectionSource, int oldVersion, int newVersion) {
try {
log.info(DatabaseHelper.class.getName(), "onUpgrade");
TableUtils.dropTable(connectionSource, TempBasal.class, true);
TableUtils.dropTable(connectionSource, Treatment.class, true);
onCreate(database, connectionSource);
} catch (SQLException e) {
log.error(DatabaseHelper.class.getName(), "Can't drop databases", e);
throw new RuntimeException(e);
}
}
/**
* Close the database connections and clear any cached DAOs.
*/
@Override
public void close() {
super.close();
}
public void resetDatabases() {
try {
TableUtils.dropTable(connectionSource, TempBasal.class, true);
TableUtils.dropTable(connectionSource, Treatment.class, true);
TableUtils.createTableIfNotExists(connectionSource, TempBasal.class);
TableUtils.createTableIfNotExists(connectionSource, Treatment.class);
} catch (SQLException e) {
e.printStackTrace();
}
}
public void resetTreatments() {
try {
TableUtils.dropTable(connectionSource, Treatment.class, true);
TableUtils.createTableIfNotExists(connectionSource, Treatment.class);
} catch (SQLException e) {
e.printStackTrace();
}
}
public Dao<TempBasal, Long> getDaoTempBasals() throws SQLException {
return getDao(TempBasal.class);
}
public Dao<Treatment, Long> getDaoTreatments() throws SQLException {
return getDao(Treatment.class);
}
}

View file

@ -0,0 +1,132 @@
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.Calendar;
import java.util.Date;
import java.util.TimeZone;
@DatabaseTable(tableName = "TempBasals")
public class TempBasal {
private static Logger log = LoggerFactory.getLogger(TempBasal.class);
public long getTimeIndex() {
return (long) Math.ceil(timeStart.getTime() / 60000d);
}
public void setTimeIndex(long timeIndex) {
this.timeIndex = timeIndex;
}
@DatabaseField(id = true, useGetSet = true)
public long timeIndex;
@DatabaseField
public Date timeStart;
@DatabaseField
public Date timeEnd;
@DatabaseField
public int percent; // In % of current basal
@DatabaseField
public int absolute; // Absolute value in U
@DatabaseField
public int duration; // in minutes
@DatabaseField
public boolean isExtended; // true if set as extended bolus
@DatabaseField
public boolean isAbsolute; // true if if set as absolute value in U
/*
public Iob calcIob() {
Iob iob = new Iob();
long msAgo = getMillisecondsFromStart();
Calendar startAdjusted = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
startAdjusted.setTime(this.timeStart);
int minutes = startAdjusted.get(Calendar.MINUTE);
minutes = minutes % 4;
if (startAdjusted.get(Calendar.SECOND) > 0 && minutes == 0) {
minutes += 4;
}
startAdjusted.add(Calendar.MINUTE, minutes);
startAdjusted.set(Calendar.SECOND, 0);
IobCalc iobCalc = new IobCalc();
iobCalc.setTime(new Date());
iobCalc.setAmount(-1.0d * (baseRatio - tempRatio) / 15.0d / 100.0d);
long timeStartTime = startAdjusted.getTimeInMillis();
Date currentTimeEnd = timeEnd;
if (currentTimeEnd == null) {
currentTimeEnd = new Date();
if (getPlannedTimeEnd().getTime() < currentTimeEnd.getTime()) {
currentTimeEnd = getPlannedTimeEnd();
}
}
for (long time = timeStartTime; time < currentTimeEnd.getTime(); time += 4 * 60_000) {
Date start = new Date(time);
iobCalc.setTimeStart(start);
iob.plus(iobCalc.invoke());
}
if (Settings.logTempIOBCalculation) {
log.debug("TempIOB start: " + this.timeStart + " end: " + this.timeEnd + " Percent: " + this.percent + " Duration: " + this.duration + " CalcDurat: " + (int) ((currentTimeEnd.getTime() - this.timeStart.getTime()) / 1000 / 60)
+ "min minAgo: " + (int) (msAgo / 1000 / 60) + " IOB: " + iob.iobContrib + " Activity: " + iob.activityContrib + " Impact: " + (-0.01d * (baseRatio - tempRatio) * ((currentTimeEnd.getTime() - this.timeStart.getTime()) / 1000 / 60) / 60)
);
}
return iob;
}
*/
// Determine end of basal
public Date getTimeEnd() {
Date tempBasalTimePlannedEnd = getPlannedTimeEnd();
// End already exists in database
if (timeEnd != null) {
return timeEnd;
}
// if not return planned time
return tempBasalTimePlannedEnd;
}
public Date getPlannedTimeEnd() {
return new Date(timeStart.getTime() + 60 * 1_000 * duration);
}
public long getMillisecondsFromStart() {
return new Date().getTime() - timeStart.getTime();
}
public int getRemainingMinutes() {
long remainingMin = (getTimeEnd().getTime() - new Date().getTime()) / 1000 / 60;
return (remainingMin < 0) ? 0 : (int) remainingMin;
}
@Override
public String toString() {
return "TempBasal{" +
"timeIndex=" + timeIndex +
", timeStart=" + timeStart +
", timeEnd=" + timeEnd +
", percent=" + percent +
", absolute=" + absolute +
", duration=" + duration +
", isAbsolute=" + isAbsolute +
", isExtended=" + isExtended +
'}';
}
}

View file

@ -0,0 +1,173 @@
package info.nightscout.androidaps.db;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Date;
import java.util.List;
import info.nightscout.client.broadcasts.Intents;
import info.nightscout.androidaps.MainApp;
import info.nightscout.utils.DateUtil;
@DatabaseTable(tableName = "Treatments")
public class Treatment {
private static Logger log = LoggerFactory.getLogger(Treatment.class);
public long getTimeIndex() {
return (long) Math.ceil(created_at.getTime() / 60000d);
}
public void setTimeIndex(long timeIndex) {
this.timeIndex = timeIndex;
}
@DatabaseField(id = true, useGetSet = true)
public long timeIndex;
@DatabaseField
public String _id;
@DatabaseField
public Date created_at;
@DatabaseField
public Double insulin;
@DatabaseField
public Double carbs;
public void copyFrom(Treatment t) {
this._id = t._id;
this.created_at = t.created_at;
this.insulin = t.insulin;
this.carbs = t.carbs;
}
/*
public Iob iobCalc(Date time, Double dia) {
Double diaratio = 3.0 / dia;
Double peak = 75d;
Double end = 180d;
//var sens = profile_data.sens;
Iob results = new Iob();
if (insulin != 0) {
long bolusTime = created_at.getTime();
Double minAgo = diaratio * (time.getTime() - bolusTime) / 1000 / 60;
Double iobContrib = 0d;
Double activityContrib = 0d;
if (minAgo < peak) {
Double x = (minAgo/5 + 1);
iobContrib = insulin * (1 - 0.001852 * x * x + 0.001852 * x);
//activityContrib=sens*treatment.insulin*(2/dia/60/peak)*minAgo;
activityContrib = insulin * (2 / dia / 60 / peak) * minAgo;
} else if (minAgo < end) {
Double y = (minAgo-peak)/5;
iobContrib = insulin * (0.001323 * y * y - .054233 * y + .55556);
//activityContrib=sens*treatment.insulin*(2/dia/60-(minAgo-peak)*2/dia/60/(60*dia-peak));
activityContrib = insulin * (2 / dia / 60 - (minAgo - peak) * 2 / dia / 60 / (60 * dia - peak));
}
results.iobContrib = iobContrib;
results.activityContrib = activityContrib;
}
return results;
}
public Iob calcIobOpenAPS() {
IobCalc calc = new IobCalc(created_at,insulin,new Date());
calc.setBolusDiaTimesTwo();
Iob iob = calc.invoke();
return iob;
}
public Iob calcIob() {
IobCalc calc = new IobCalc(created_at,insulin,new Date());
Iob iob = calc.invoke();
return iob;
}
*/
public long getMillisecondsFromStart() {
return new Date().getTime() - created_at.getTime();
}
public String log() {
return "Treatment{" +
"timeIndex: " + timeIndex +
", _id: " + _id +
", insulin: " + insulin +
", carbs: " + carbs +
", created_at: " +
"}";
}
public void sendToNSClient() {
Context context = MainApp.instance().getApplicationContext();
Bundle bundle = new Bundle();
bundle.putString("action", "dbAdd");
bundle.putString("collection", "treatments");
JSONObject data = new JSONObject();
try {
data.put("eventType", "Meal Bolus");
if (insulin != 0d) data.put("insulin", insulin);
if (carbs != 0d) data.put("carbs", carbs.intValue());
data.put("created_at", DateUtil.toISOString(created_at));
data.put("timeIndex", timeIndex);
} catch (JSONException e) {
e.printStackTrace();
}
bundle.putString("data", data.toString());
Intent intent = new Intent(Intents.ACTION_DATABASE);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
context.sendBroadcast(intent);
List<ResolveInfo> q = context.getPackageManager().queryBroadcastReceivers(intent, 0);
if (q.size() < 1) {
log.error("DBADD No receivers");
} else log.debug("DBADD dbAdd " + q.size() + " receivers " + data.toString());
}
public void updateToNSClient() {
Context context = MainApp.instance().getApplicationContext();
Bundle bundle = new Bundle();
bundle.putString("action", "dbUpdate");
bundle.putString("collection", "treatments");
JSONObject data = new JSONObject();
try {
data.put("eventType", "Meal Bolus");
data.put("insulin", insulin);
data.put("carbs", carbs.intValue());
data.put("created_at", DateUtil.toISOString(created_at));
data.put("timeIndex", timeIndex);
} catch (JSONException e) {
e.printStackTrace();
}
bundle.putString("data", data.toString());
bundle.putString("_id", _id);
Intent intent = new Intent(Intents.ACTION_DATABASE);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
context.sendBroadcast(intent);
List<ResolveInfo> q = context.getPackageManager().queryBroadcastReceivers(intent, 0);
if (q.size() < 1) {
log.error("DBUPDATE No receivers");
} else log.debug("DBUPDATE dbUpdate " + q.size() + " receivers " + _id + " " + data.toString());
}
}

View file

@ -0,0 +1,8 @@
package info.nightscout.androidaps.events;
/**
* Created by mike on 04.06.2016.
*/
public class EventNewBasalProfile {
// TODO: implement proper GUI update
}

View file

@ -0,0 +1,7 @@
package info.nightscout.androidaps.events;
/**
* Created by mike on 04.06.2016.
*/
public class EventTreatmentChange {
}

View file

@ -14,7 +14,6 @@ import android.widget.TextView;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.StringTokenizer;
import info.nightscout.androidaps.R;
@ -139,7 +138,7 @@ public class ObjectivesFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_objectives, container, false);
View view = inflater.inflate(R.layout.objectives_fragment, container, false);
recyclerView = (RecyclerView) view.findViewById(R.id.objectives_recyclerview);
recyclerView.setHasFixedSize(true);

View file

@ -0,0 +1,96 @@
package info.nightscout.androidaps.plugins.ProfileViewer;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.squareup.otto.Subscribe;
import java.text.DecimalFormat;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.events.EventNewBasalProfile;
import info.nightscout.client.data.NSProfile;
public class ProfileViewerFragment extends Fragment {
private static TextView noProfile;
private static TextView dia;
private static TextView activeProfile;
private static TextView ic;
private static TextView isf;
private static TextView basal;
private static TextView target;
private static DecimalFormat formatNumber2decimalplaces = new DecimalFormat("0.00");
public ProfileViewerFragment() {
}
public static ProfileViewerFragment newInstance(String param1, String param2) {
ProfileViewerFragment fragment = new ProfileViewerFragment();
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
registerBus();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View layout = inflater.inflate(R.layout.profileviewer_fragment, container, false);
noProfile = (TextView) layout.findViewById(R.id.profileview_noprofile);
dia = (TextView) layout.findViewById(R.id.profileview_dia);
activeProfile = (TextView) layout.findViewById(R.id.profileview_activeprofile);
ic = (TextView) layout.findViewById(R.id.profileview_ic);
isf = (TextView) layout.findViewById(R.id.profileview_isf);
basal = (TextView) layout.findViewById(R.id.profileview_basal);
target = (TextView) layout.findViewById(R.id.profileview_target);
setContent();
return layout;
}
public static ProfileViewerFragment newInstance() {
ProfileViewerFragment fragment = new ProfileViewerFragment();
return fragment;
}
private void setContent() {
NSProfile profile = MainApp.getNSProfile();
if (profile == null) {
noProfile.setVisibility(View.VISIBLE);
} else {
noProfile.setVisibility(View.GONE);
}
dia.setText(formatNumber2decimalplaces.format(profile.getDia()) + " h");
activeProfile.setText(profile.getActiveProfile());
ic.setText(profile.getIcList());
isf.setText(profile.getIsfList());
basal.setText(profile.getBasalList());
target.setText(profile.getTargetList());
}
private void registerBus() {
try {
MainApp.bus().unregister(this);
} catch (RuntimeException x) {
// Ignore
}
MainApp.bus().register(this);
}
@Subscribe
public void onStatusEvent(final EventNewBasalProfile ev) {
setContent();
}
}

View file

@ -30,7 +30,7 @@ public class TestFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstance) {
View layout = inflater.inflate(R.layout.app_fragment, container, false);
View layout = inflater.inflate(R.layout.test_fragment, container, false);
textView = (TextView) layout.findViewById(R.id.position);
Bundle bundle = getArguments();
if (bundle != null) {

View file

@ -0,0 +1,15 @@
package info.nightscout.client.broadcasts;
public interface Intents {
// NSClient -> App
String ACTION_NEW_TREATMENT = "info.nightscout.client.NEW_TREATMENT";
String ACTION_CHANGED_TREATMENT = "info.nightscout.client.CHANGED_TREATMENT";
String ACTION_REMOVED_TREATMENT = "info.nightscout.client.REMOVED_TREATMENT";
String ACTION_NEW_PROFILE = "info.nightscout.client.NEW_PROFILE";
String ACTION_NEW_SGV = "info.nightscout.client.NEW_SGV";
String ACTION_NEW_STATUS = "info.nightscout.client.NEW_STATUS";
// App -> NSClient
String ACTION_DATABASE = "info.nightscout.client.DBACCESS";
}

View file

@ -0,0 +1,22 @@
package info.nightscout.client.data;
import org.json.JSONException;
import org.json.JSONObject;
public class NSCal {
public long date;
public double slope;
public double intercept;
public double scale = 1;
public void set(JSONObject json) {
try {
date = json.getLong("date");
slope = json.getDouble("slope");
intercept = json.getDouble("intercept");
scale = json.getDouble("scale");
} catch (JSONException e) {
e.printStackTrace();
}
}
}

View file

@ -0,0 +1,282 @@
package info.nightscout.client.data;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.text.DecimalFormat;
import java.util.Calendar;
import java.util.TimeZone;
public class NSProfile {
private JSONObject json = null;
private String activeProfile = null;
public NSProfile(JSONObject json, String activeProfile) {
this.json = json;
this.activeProfile = activeProfile;
}
JSONObject getDefaultProfile() {
String defaultProfileName = null;
JSONObject store;
JSONObject profile = null;
try {
defaultProfileName = (String) json.get("defaultProfile");
store = json.getJSONObject("store");
if (activeProfile != null && store.has(activeProfile)) {
defaultProfileName = activeProfile;
}
profile = store.getJSONObject(defaultProfileName);
} catch (JSONException e) {
e.printStackTrace();
}
return profile;
}
public String log() {
String ret = "\n";
for (Integer hour = 0; hour < 24; hour ++) {
double value = getBasal(hour * 60 * 60);
ret += "NS basal value for " + hour + ":00 is " + value + "\n";
}
ret += "NS units: " + getUnits();
return ret;
}
public JSONObject getData () {
return json;
}
public Double getDia() {
Double dia;
JSONObject profile = getDefaultProfile();
if (profile != null) {
try {
dia = profile.getDouble("dia");
return dia;
} catch (JSONException e) {
e.printStackTrace();
}
}
return 3D;
}
public Double getCarbAbsorbtionRate() {
Double carbAbsorptionRate;
JSONObject profile = getDefaultProfile();
if (profile != null) {
try {
carbAbsorptionRate = profile.getDouble("carbs_hr");
return carbAbsorptionRate;
} catch (JSONException e) {
e.printStackTrace();
}
}
return 0D;
}
// mmol or mg/dl
public String getUnits() {
String units;
JSONObject profile = getDefaultProfile();
if (profile != null) {
try {
units = profile.getString("units");
return units;
} catch (JSONException e) {
e.printStackTrace();
}
}
return "mg/dl";
}
public TimeZone getTimeZone() {
TimeZone timeZone;
JSONObject profile = getDefaultProfile();
if (profile != null) {
try {
return TimeZone.getTimeZone(profile.getString("timezone"));
} catch (JSONException e) {
e.printStackTrace();
}
}
return TimeZone.getDefault();
}
public Double getValueToTime(JSONArray array, Integer timeAsSeconds) {
Double lastValue = null;
for(Integer index = 0; index < array.length(); index++) {
try {
JSONObject o = array.getJSONObject(index);
Integer tas = o.getInt("timeAsSeconds");
Double value = o.getDouble("value");
if (lastValue == null) lastValue = value;
if (timeAsSeconds < tas) {
break;
}
lastValue = value;
} catch (JSONException e) {
e.printStackTrace();
}
}
return lastValue;
}
public String getValuesList(JSONArray array, JSONArray array2, DecimalFormat format, String units) {
String retValue = "";
for(Integer index = 0; index < array.length(); index++) {
try {
JSONObject o = array.getJSONObject(index);
retValue += o.getString("time");
retValue += " ";
retValue += format.format(o.getDouble("value"));
if (array2 != null) {
JSONObject o2 = array2.getJSONObject(index);
retValue += " - ";
retValue += format.format(o2.getDouble("value"));
}
retValue += " " + units;
retValue += "\n";
} catch (JSONException e) {
e.printStackTrace();
}
}
return retValue;
}
public Double getIsf(Integer timeAsSeconds) {
JSONObject profile = getDefaultProfile();
if (profile != null) {
try {
return getValueToTime(profile.getJSONArray("sens"),timeAsSeconds);
} catch (JSONException e) {
e.printStackTrace();
}
}
return 0D;
}
public String getIsfList() {
JSONObject profile = getDefaultProfile();
if (profile != null) {
try {
return getValuesList(profile.getJSONArray("sens"), null, new DecimalFormat("0"), getUnits() + "/U");
} catch (JSONException e) {
e.printStackTrace();
}
}
return "";
}
public Double getIc(Integer timeAsSeconds) {
JSONObject profile = getDefaultProfile();
if (profile != null) {
try {
return getValueToTime(profile.getJSONArray("carbratio"),timeAsSeconds);
} catch (JSONException e) {
e.printStackTrace();
}
}
return 0D;
}
public String getIcList() {
JSONObject profile = getDefaultProfile();
if (profile != null) {
try {
return getValuesList(profile.getJSONArray("carbratio"), null, new DecimalFormat("0"), "g");
} catch (JSONException e) {
e.printStackTrace();
}
}
return "";
}
public Double getBasal(Integer timeAsSeconds) {
JSONObject profile = getDefaultProfile();
if (profile != null) {
try {
return getValueToTime(profile.getJSONArray("basal"),timeAsSeconds);
} catch (JSONException e) {
e.printStackTrace();
}
}
return 0D;
}
public String getBasalList() {
JSONObject profile = getDefaultProfile();
if (profile != null) {
try {
return getValuesList(profile.getJSONArray("basal"), null, new DecimalFormat("0.00"), "U");
} catch (JSONException e) {
e.printStackTrace();
}
}
return "";
}
public Double getTargetLow(Integer timeAsSeconds) {
JSONObject profile = getDefaultProfile();
if (profile != null) {
try {
return getValueToTime(profile.getJSONArray("target_low"),timeAsSeconds);
} catch (JSONException e) {
e.printStackTrace();
}
}
return 0D;
}
public Double getTargetHigh(Integer timeAsSeconds) {
JSONObject profile = getDefaultProfile();
if (profile != null) {
try {
return getValueToTime(profile.getJSONArray("target_high"), timeAsSeconds);
} catch (JSONException e) {
e.printStackTrace();
}
}
return 0D;
}
public String getTargetList() {
JSONObject profile = getDefaultProfile();
if (profile != null) {
try {
return getValuesList(profile.getJSONArray("target_low"),profile.getJSONArray("target_high"), new DecimalFormat("0.0"), getUnits());
} catch (JSONException e) {
e.printStackTrace();
}
}
return "";
}
public String getActiveProfile() {
return activeProfile;
}
public Double getMaxDailyBasal() {
Double max = 0d;
for (Integer hour = 0; hour < 24; hour ++) {
double value = getBasal(hour * 60 * 60);
if (value > max) max = value;
}
return max;
}
public static int secondsFromMidnight() {
Calendar c = Calendar.getInstance();
long now = c.getTimeInMillis();
c.set(Calendar.HOUR_OF_DAY, 0);
c.set(Calendar.MINUTE, 0);
c.set(Calendar.SECOND, 0);
c.set(Calendar.MILLISECOND, 0);
long passed = now - c.getTimeInMillis();
return (int) (passed / 1000);
}
}

View file

@ -0,0 +1,63 @@
package info.nightscout.client.data;
import org.json.JSONException;
import org.json.JSONObject;
/**
*
* {"mgdl":105,"mills":1455136282375,"device":"xDrip-BluetoothWixel","direction":"Flat","filtered":98272,"unfiltered":98272,"noise":1,"rssi":100}
*/
public class NSSgv {
private JSONObject data;
public NSSgv(JSONObject obj) {
this.data = obj;
}
private String getStringOrNull(String key) {
String ret = null;
if (data.has(key)) {
try {
ret = data.getString(key);
} catch (JSONException e) {
e.printStackTrace();
}
}
return ret;
};
private Integer getIntegerOrNull(String key) {
Integer ret = null;
if (data.has(key)) {
try {
ret = data.getInt(key);
} catch (JSONException e) {
e.printStackTrace();
}
}
return ret;
};
private Long getLongOrNull(String key) {
Long ret = null;
if (data.has(key)) {
try {
ret = data.getLong(key);
} catch (JSONException e) {
e.printStackTrace();
}
}
return ret;
};
public JSONObject getData () { return data; }
public Integer getMgdl () { return getIntegerOrNull("mgdl"); }
public Integer getFiltered () { return getIntegerOrNull("filtered"); }
public Integer getUnfiltered () { return getIntegerOrNull("unfiltered"); }
public Integer getNoise () { return getIntegerOrNull("noise"); }
public Integer getRssi () { return getIntegerOrNull("rssi"); }
public Long getMills () { return getLongOrNull("mills"); }
public String getDevice () { return getStringOrNull("device"); }
public String getDirection () { return getStringOrNull("direction"); }
}

View file

@ -0,0 +1,105 @@
package info.nightscout.client.data;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.Date;
/**
{
status: 'ok'
, name: env.name
, version: env.version
, versionNum: versionNum (for ver 1.2.3 contains 10203)
, serverTime: new Date().toISOString()
, apiEnabled: apiEnabled
, careportalEnabled: apiEnabled && env.settings.enable.indexOf('careportal') > -1
, boluscalcEnabled: apiEnabled && env.settings.enable.indexOf('boluscalc') > -1
, head: env.head
, settings: env.settings
, extendedSettings: ctx.plugins && ctx.plugins.extendedClientSettings ? ctx.plugins.extendedClientSettings(env.extendedSettings) : {}
, activeProfile ..... calculated from treatments or missing
}
*/
public class NSStatus {
private JSONObject data;
public NSStatus(JSONObject obj) {
this.data = obj;
}
public String getName () { return getStringOrNull("name"); }
public String getVersion () { return getStringOrNull("version"); }
public Integer getVersionNum () { return getIntegerOrNull("versionNum"); }
public Date getServerTime () { return getDateOrNull("versionNum"); }
public boolean getApiEnabled () { return getBooleanOrNull("apiEnabled"); }
public boolean getCareportalEnabled () { return getBooleanOrNull("careportalEnabled"); }
public boolean getBoluscalcEnabled () { return getBooleanOrNull("boluscalcEnabled"); }
public String getHead () { return getStringOrNull("head"); }
public String getSettings () { return getStringOrNull("settings"); }
public String getExtendedSettings () { return getStringOrNull("extendedSettings"); }
public String getActiveProfile () { return getStringOrNull("activeProfile"); }
private String getStringOrNull(String key) {
String ret = null;
if (data.has(key)) {
try {
ret = data.getString(key);
} catch (JSONException e) {
e.printStackTrace();
}
}
return ret;
};
private Integer getIntegerOrNull(String key) {
Integer ret = null;
if (data.has(key)) {
try {
ret = data.getInt(key);
} catch (JSONException e) {
e.printStackTrace();
}
}
return ret;
};
private Long getLongOrNull(String key) {
Long ret = null;
if (data.has(key)) {
try {
ret = data.getLong(key);
} catch (JSONException e) {
e.printStackTrace();
}
}
return ret;
};
private Date getDateOrNull(String key) {
Date ret = null;
if (data.has(key)) {
try {
ret = new Date(data.getString(key));
} catch (JSONException e) {
e.printStackTrace();
}
}
return ret;
};
private boolean getBooleanOrNull(String key) {
boolean ret = false;
if (data.has(key)) {
try {
ret = data.getBoolean(key);
} catch (JSONException e) {
e.printStackTrace();
}
}
return ret;
};
public JSONObject getData () { return data; }
}

View file

@ -0,0 +1,89 @@
package info.nightscout.client.data;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.Date;
public class NSTreatment {
private JSONObject data;
private String action = null; // "update", "remove" or null (add)
public NSTreatment(JSONObject obj) {
this.data = obj;
this.action = getStringOrNull("action");
this.data.remove("action");
}
private String getStringOrNull(String key) {
String ret = null;
if (data.has(key)) {
try {
ret = data.getString(key);
} catch (JSONException e) {
e.printStackTrace();
}
}
return ret;
};
private Double getDoubleOrNull(String key) {
Double ret = null;
if (data.has(key)) {
try {
ret = data.getDouble(key);
} catch (JSONException e) {
e.printStackTrace();
}
}
return ret;
};
private Integer getIntegerOrNull(String key) {
Integer ret = null;
if (data.has(key)) {
try {
ret = data.getInt(key);
} catch (JSONException e) {
e.printStackTrace();
}
}
return ret;
};
private Long getLongOrNull(String key) {
Long ret = null;
if (data.has(key)) {
try {
ret = data.getLong(key);
} catch (JSONException e) {
e.printStackTrace();
}
}
return ret;
};
private Date getDateOrNull(String key) {
Date ret = null;
if (data.has(key)) {
try {
ret = new Date(data.getString(key));
} catch (JSONException e) {
e.printStackTrace();
}
}
return ret;
};
public String getAction() { return action; }
public JSONObject getData() { return data; }
public String get_id() { return getStringOrNull("_id"); }
public String getEnteredBy() { return getStringOrNull("enteredBy"); }
public String getEventType() { return getStringOrNull("eventType"); }
public Integer getHapp_id() { return getIntegerOrNull("happ_id"); }
public Integer getDuration() { return getIntegerOrNull("duration"); }
public Integer getMgdl() { return getIntegerOrNull("mgdl"); }
public Double getAbsolute() { return getDoubleOrNull("absolute"); }
public Long getMills() { return getLongOrNull("mills"); }
public Date getCreated_at() { return getDateOrNull("created_at"); }
}

View file

@ -0,0 +1,258 @@
package info.nightscout.client.receivers;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.stmt.PreparedQuery;
import com.j256.ormlite.stmt.QueryBuilder;
import com.j256.ormlite.stmt.Where;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.sql.SQLException;
import java.util.Date;
import java.util.List;
import info.nightscout.androidaps.events.EventNewBasalProfile;
import info.nightscout.androidaps.events.EventTreatmentChange;
import info.nightscout.client.broadcasts.Intents;
import info.nightscout.client.data.NSProfile;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.db.Treatment;
public class NSClientDataReceiver extends BroadcastReceiver {
private static Logger log = LoggerFactory.getLogger(NSClientDataReceiver.class);
public NSClientDataReceiver() {
}
@Override
public void onReceive(Context context, Intent intent) {
Bundle bundles = intent.getExtras();
if (bundles == null) return;
// Handle profile
if (intent.getAction().equals(Intents.ACTION_NEW_PROFILE)){
try {
String activeProfile = bundles.getString("activeprofile");
String profile = bundles.getString("profile");
NSProfile nsProfile = new NSProfile(new JSONObject(profile), activeProfile);
MainApp.instance().setNSProfile(nsProfile);
MainApp.instance().setActiveProfile(activeProfile);
storeNSProfile();
if (MainApp.getActivePump() != null) {
MainApp.getActivePump().setNewBasalProfile();
} else {
log.error("No active pump selected");
}
log.debug("Received profile: " + activeProfile + " " + profile);
MainApp.bus().post(new EventNewBasalProfile());
} catch (JSONException e) {
e.printStackTrace();
}
}
if (intent.getAction().equals(Intents.ACTION_NEW_TREATMENT)) {
try {
String trstring = bundles.getString("treatment");
JSONObject trJson = new JSONObject(trstring);
if (!trJson.has("insulin") && !trJson.has("carbs")) {
log.debug("ADD: Uninterested treatment: " + trstring);
return;
}
Treatment stored = null;
trJson = new JSONObject(trstring);
String _id = trJson.getString("_id");
if (trJson.has("timeIndex")) {
log.debug("ADD: timeIndex found: " + trstring);
stored = findByTimeIndex(trJson.getLong("timeIndex"));
} else {
stored = findById(_id);
}
if (stored != null) {
log.debug("ADD: Existing treatment: " + trstring);
if (trJson.has("timeIndex")) {
stored._id = _id;
MainApp.getDbHelper().getDaoTreatments().update(stored);
}
return;
} else {
log.debug("ADD: New treatment: " + trstring);
Treatment treatment = new Treatment();
treatment._id = _id;
treatment.carbs = trJson.has("carbs") ? trJson.getDouble("carbs") : 0;
treatment.insulin = trJson.has("insulin") ? trJson.getDouble("insulin") : 0d;
treatment.created_at = new Date(trJson.getLong("mills"));
treatment.setTimeIndex(treatment.getTimeIndex());
try {
MainApp.getDbHelper().getDaoTreatments().create(treatment);
log.debug("ADD: Stored treatment: " + treatment.log());
MainApp.bus().post(new EventTreatmentChange());
} catch (SQLException e) {
e.printStackTrace();
}
}
} catch (JSONException e) {
e.printStackTrace();
} catch (Exception e1) {
e1.printStackTrace();
}
}
if (intent.getAction().equals(Intents.ACTION_CHANGED_TREATMENT)) {
try {
String trstring = bundles.getString("treatment");
JSONObject trJson = new JSONObject(trstring);
if (!trJson.has("insulin") && !trJson.has("carbs")) {
log.debug("CHANGE: Uninterested treatment: " + trstring);
return;
}
trJson = new JSONObject(trstring);
String _id = trJson.getString("_id");
Treatment stored;
if (trJson.has("timeIndex")) {
log.debug("ADD: timeIndex found: " + trstring);
stored = findByTimeIndex(trJson.getLong("timeIndex"));
} else {
stored = findById(_id);
}
if (stored != null) {
log.debug("CHANGE: Existing treatment: " + trstring);
stored._id = _id;
stored.carbs = trJson.has("carbs") ? trJson.getDouble("carbs") : 0;
stored.insulin = trJson.has("insulin") ? trJson.getDouble("insulin") : 0d;
stored.created_at = new Date(trJson.getLong("mills"));
MainApp.getDbHelper().getDaoTreatments().update(stored);
MainApp.bus().post(new EventTreatmentChange());
} else {
log.debug("CHANGE: New treatment: " + trstring);
Treatment treatment = new Treatment();
treatment._id = _id;
treatment.carbs = trJson.has("carbs") ? trJson.getDouble("carbs") : 0;
treatment.insulin = trJson.has("insulin") ? trJson.getDouble("insulin") : 0d;
//treatment.created_at = DateUtil.fromISODateString(trJson.getString("created_at"));
treatment.created_at = new Date(trJson.getLong("mills"));
treatment.setTimeIndex(treatment.getTimeIndex());
try {
MainApp.getDbHelper().getDaoTreatments().create(treatment);
log.debug("CHANGE: Stored treatment: " + treatment.log());
MainApp.bus().post(new EventTreatmentChange());
} catch (SQLException e) {
e.printStackTrace();
}
}
} catch (JSONException e) {
e.printStackTrace();
} catch (Exception e1) {
e1.printStackTrace();
}
}
if (intent.getAction().equals(Intents.ACTION_REMOVED_TREATMENT)) {
try {
if (bundles.containsKey("treatment")) {
String trstring = bundles.getString("treatment");
JSONObject trJson = new JSONObject(trstring);
String _id = trJson.getString("_id");
removeTreatmentFromDb(_id);
}
if (bundles.containsKey("treatments")) {
String trstring = bundles.getString("treatments");
JSONArray jsonArray = new JSONArray(trstring);
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject trJson = jsonArray.getJSONObject(i);
String _id = trJson.getString("_id");
removeTreatmentFromDb(_id);
}
}
} catch (JSONException e) {
e.printStackTrace();
} catch (Exception e1) {
e1.printStackTrace();
}
}
}
public void storeNSProfile() {
SharedPreferences settings = MainApp.instance().getApplicationContext().getSharedPreferences(MainApp.instance().PREFS_NAME, 0);
SharedPreferences.Editor editor = settings.edit();
editor.putString("profile", MainApp.instance().getNSProfile().getData().toString());
editor.putString("activeProfile", MainApp.instance().getActiveProfile());
editor.commit();
}
public static Treatment findById(String _id) {
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("_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;
}
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);
MainApp.getDbHelper().getDaoTreatments().delete(stored);
MainApp.bus().post(new EventTreatmentChange());
} else {
log.debug("REMOVE: Not stored treatment (ignoring): " + _id);
}
}
}

View file

@ -0,0 +1,52 @@
package info.nightscout.utils;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
/**
* The Class DateUtil. A simple wrapper around SimpleDateFormat to ease the handling of iso date string &lt;-&gt; date obj
* with TZ
*/
public class DateUtil
{
/** The date format in iso. */
public static String FORMAT_DATE_ISO="yyyy-MM-dd'T'HH:mm:ssZ";
/**
* Takes in an ISO date string of the following format:
* yyyy-mm-ddThh:mm:ss.ms+HoMo
*
* @param isoDateString the iso date string
* @return the date
* @throws Exception the exception
*/
public static Date fromISODateString(String isoDateString)
throws Exception
{
DateFormat f = new SimpleDateFormat(FORMAT_DATE_ISO);
return f.parse(isoDateString);
}
/**
* Render date
*
* @param date the date obj
* @param format - if not specified, will use FORMAT_DATE_ISO
* @param tz - tz to set to, if not specified uses local timezone
* @return the iso-formatted date string
*/
public static String toISOString(Date date, String format, TimeZone tz)
{
if( format == null ) format = FORMAT_DATE_ISO;
if( tz == null ) tz = TimeZone.getDefault();
DateFormat f = new SimpleDateFormat(format);
f.setTimeZone(tz);
return f.format(date);
}
public static String toISOString(Date date)
{ return toISOString(date,FORMAT_DATE_ISO,TimeZone.getTimeZone("UTC")); }
}

View file

@ -3,7 +3,7 @@
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/objectives_cardview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
card_view:cardBackgroundColor="@color/cardColorBackground"
card_view:cardCornerRadius="6dp"

View file

@ -0,0 +1,106 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".plugins.ProfileViewer.ProfileViewerFragment">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/profileview_noprofile"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/profileview_noprofile_text"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="@android:color/holo_red_light"
android:textStyle="bold"
android:gravity="center_horizontal" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/profileview_activeprofile_label"
android:textAppearance="?android:attr/textAppearanceLarge"
android:layout_marginLeft="10dp" />
<TextView
android:id="@+id/profileview_activeprofile"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="25dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/profileview_dia_label"
android:textAppearance="?android:attr/textAppearanceLarge"
android:layout_marginLeft="10dp" />
<TextView
android:id="@+id/profileview_dia"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="25dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/profileview_ic_label"
android:textAppearance="?android:attr/textAppearanceLarge"
android:layout_marginLeft="10dp" />
<TextView
android:id="@+id/profileview_ic"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="25dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/profileview_isf_label"
android:textAppearance="?android:attr/textAppearanceLarge"
android:layout_marginLeft="10dp" />
<TextView
android:id="@+id/profileview_isf"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="25dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/profileview_basal_label"
android:textAppearance="?android:attr/textAppearanceLarge"
android:layout_marginLeft="10dp" />
<TextView
android:id="@+id/profileview_basal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="25dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/profileview_target_label"
android:textAppearance="?android:attr/textAppearanceLarge"
android:layout_marginLeft="10dp" />
<TextView
android:id="@+id/profileview_target"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp" />
</LinearLayout>
</ScrollView>
</FrameLayout>

View file

@ -3,7 +3,7 @@
<color name="colorPrimary">#3F51B5</color>
<color name="colorPrimaryDark">#303F9F</color>
<color name="colorAccent">#FF4081</color>
<color name="cardColorBackground">#121212</color>
<color name="cardColorBackground">#121212</color>
<color name="cardObjectiveText">#779ECB</color>
</resources>

View file

@ -27,5 +27,12 @@
<string name="objectives_gate_label_string">Gate:</string>
<string name="objectives_button_start">Start</string>
<string name="objectives_button_verify">Verify</string>
<string name="profileview_dia_label">DIA:</string>
<string name="profileview_activeprofile_label">Active profile:</string>
<string name="profileview_ic_label">IC:</string>
<string name="profileview_isf_label">ISF:</string>
<string name="profileview_basal_label">Basal:</string>
<string name="profileview_target_label">Target:</string>
<string name="profileview_noprofile_text">NO PROFILE SET</string>
</resources>