Skip to content

Commit

Permalink
Initial Support for Pebble2 and Pebble Health
Browse files Browse the repository at this point in the history
  • Loading branch information
jamorham committed Nov 8, 2016
1 parent a3f32d9 commit 595ee45
Show file tree
Hide file tree
Showing 12 changed files with 502 additions and 10 deletions.
2 changes: 1 addition & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
android:value="41" />
<meta-data
android:name="AA_MODELS"
android:value="com.eveningoutpost.dexdrip.Models.ActiveBgAlert,com.eveningoutpost.dexdrip.Models.ActiveBluetoothDevice,com.eveningoutpost.dexdrip.Models.AlertType,com.eveningoutpost.dexdrip.Models.BgReading,com.eveningoutpost.dexdrip.Models.BgReading,com.eveningoutpost.dexdrip.Models.Calibration,com.eveningoutpost.dexdrip.Models.Calibration,com.eveningoutpost.dexdrip.Models.CalibrationRequest,com.eveningoutpost.dexdrip.Models.Sensor,com.eveningoutpost.dexdrip.Models.TransmitterData,com.eveningoutpost.dexdrip.Models.Treatments,com.eveningoutpost.dexdrip.Models.UserError,com.eveningoutpost.dexdrip.Models.UserNotification,com.eveningoutpost.dexdrip.ShareModels.Models,com.eveningoutpost.dexdrip.UtilityModels.BgSendQueue,com.eveningoutpost.dexdrip.UtilityModels.CalibrationSendQueue,com.eveningoutpost.dexdrip.UtilityModels.SensorSendQueue"/>
android:value="com.eveningoutpost.dexdrip.Models.ActiveBgAlert,com.eveningoutpost.dexdrip.Models.ActiveBluetoothDevice,com.eveningoutpost.dexdrip.Models.AlertType,com.eveningoutpost.dexdrip.Models.BgReading,com.eveningoutpost.dexdrip.Models.BgReading,com.eveningoutpost.dexdrip.Models.Calibration,com.eveningoutpost.dexdrip.Models.Calibration,com.eveningoutpost.dexdrip.Models.CalibrationRequest,com.eveningoutpost.dexdrip.Models.Sensor,com.eveningoutpost.dexdrip.Models.TransmitterData,com.eveningoutpost.dexdrip.Models.Treatments,com.eveningoutpost.dexdrip.Models.UserError,com.eveningoutpost.dexdrip.Models.UserNotification,com.eveningoutpost.dexdrip.ShareModels.Models,com.eveningoutpost.dexdrip.UtilityModels.BgSendQueue,com.eveningoutpost.dexdrip.UtilityModels.CalibrationSendQueue,com.eveningoutpost.dexdrip.UtilityModels.SensorSendQueue,com.eveningoutpost.dexdrip.Models.HeartRate,com.eveningoutpost.dexdrip.Models.PebbleMovement"/>

<provider
android:name="com.activeandroid.content.ContentProvider"
Expand Down
54 changes: 50 additions & 4 deletions app/src/main/java/com/eveningoutpost/dexdrip/Home.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageButton;
Expand All @@ -55,7 +56,9 @@
import com.eveningoutpost.dexdrip.Models.ActiveBluetoothDevice;
import com.eveningoutpost.dexdrip.Models.BgReading;
import com.eveningoutpost.dexdrip.Models.Calibration;
import com.eveningoutpost.dexdrip.Models.HeartRate;
import com.eveningoutpost.dexdrip.Models.JoH;
import com.eveningoutpost.dexdrip.Models.PebbleMovement;
import com.eveningoutpost.dexdrip.Models.Sensor;
import com.eveningoutpost.dexdrip.Models.Treatments;
import com.eveningoutpost.dexdrip.Models.UserError;
Expand Down Expand Up @@ -171,6 +174,8 @@ public class Home extends ActivityWithMenu {
public static final int SHOWCASE_STATISTICS = 8;
private static double last_speech_time = 0;
private PreviewLineChartView previewChart;
private Button stepsButton;
private Button bpmButton;
private TextView dexbridgeBattery;
private TextView parakeetBattery;
private TextView sensorAge;
Expand Down Expand Up @@ -250,6 +255,8 @@ protected void onCreate(Bundle savedInstanceState) {
this.sensorAge = (TextView) findViewById(R.id.libstatus);
this.extraStatusLineText = (TextView) findViewById(R.id.extraStatusLine);
this.currentBgValueText = (TextView) findViewById(R.id.currentBgValueRealTime);
this.bpmButton = (Button) findViewById(R.id.bpmButton);
this.stepsButton = (Button) findViewById(R.id.walkButton);

extraStatusLineText.setText("");
dexbridgeBattery.setText("");
Expand Down Expand Up @@ -1315,6 +1322,7 @@ else if(BgGraphBuilder.isLargeTablet(getApplicationContext())) {
public void onReceive(Context ctx, Intent intent) {
if (intent.getAction().compareTo(Intent.ACTION_TIME_TICK) == 0) {
updateCurrentBgInfo("time tick");
updateHealthInfo("time_tick");
}
}
};
Expand All @@ -1323,6 +1331,7 @@ public void onReceive(Context ctx, Intent intent) {
public void onReceive(Context ctx, Intent intent) {
holdViewport.set(0, 0, 0, 0);
updateCurrentBgInfo("new data");
updateHealthInfo("new_data");
}
};
registerReceiver(_broadcastReceiver, new IntentFilter(Intent.ACTION_TIME_TICK));
Expand All @@ -1335,6 +1344,7 @@ public void onReceive(Context ctx, Intent intent) {
}
activityVisible = true;
updateCurrentBgInfo("generic on resume");
updateHealthInfo("generic on resume");

if (!JoH.getWifiSleepPolicyNever()) {
if (JoH.ratelimit("policy-never", 3600)) {
Expand Down Expand Up @@ -1530,6 +1540,30 @@ public static boolean get_holo() {
return Home.is_holo;
}

public void toggleStepsVisibility(View v) {
setPreferencesBoolean("show_pebble_movement_line", !getPreferencesBoolean("show_pebble_movement_line", true));
staticRefreshBGCharts();
}

private void updateHealthInfo(String caller) {
final PebbleMovement pm = PebbleMovement.last();
if (pm != null) {
stepsButton.setText(Integer.toString(pm.metric));
stepsButton.setVisibility(View.VISIBLE);
stepsButton.setAlpha(getPreferencesBoolean("show_pebble_movement_line", true) ? 1.0f : 0.3f);
} else {
stepsButton.setVisibility(View.INVISIBLE);
}

final HeartRate hr = HeartRate.last();
if (hr != null) {
bpmButton.setText(Integer.toString(hr.bpm));
bpmButton.setVisibility(View.VISIBLE);
} else {
bpmButton.setVisibility(View.INVISIBLE);
}
}

private void updateCurrentBgInfo(String source) {
Log.d(TAG, "updateCurrentBgInfo from: " + source);

Expand Down Expand Up @@ -1869,6 +1903,15 @@ private void displayCurrentInfo() {
predictive = false;
}
if (lastBgReading != null) {

// detect broken data from G5 or other sources
if ((lastBgReading.raw_data != 0) && (lastBgReading.raw_data * 2 == lastBgReading.filtered_data)) {
if (JoH.ratelimit("g5-corrupt-data-warning", 1200)) {
final String msg = "filtered data appears to be exactly double raw sensor data which looks completely wrong! " + lastBgReading.raw_data;
toaststaticnext(msg);
}
}

displayCurrentInfoFromReading(lastBgReading, predictive);
} else {
display_delta = "";
Expand Down Expand Up @@ -2002,6 +2045,7 @@ private void displayCurrentInfoFromReading(BgReading lastBgReading, boolean pred
double estimated_delta = 0;
if (lastBgReading == null) return;
final BestGlucose.DisplayGlucose dg = BestGlucose.getDisplayGlucose();
if (dg == null) return;
//String slope_arrow = lastBgReading.slopeArrow();
String slope_arrow = dg.delta_arrow;
String extrastring = "";
Expand Down Expand Up @@ -2091,8 +2135,8 @@ private void displayCurrentInfoFromReading(BgReading lastBgReading, boolean pred
if (bgReadingList != null && bgReadingList.size() == 2) {
// same logic as in xDripWidget (refactor that to BGReadings to avoid redundancy / later inconsistencies)?

display_delta = bgGraphBuilder.unitizedDeltaString(true, true, is_follower);

//display_delta = bgGraphBuilder.unitizedDeltaString(true, true, is_follower);
display_delta = dg.unitized_delta;
// TODO reduce duplication of logic
if ((BgGraphBuilder.last_noise > BgGraphBuilder.NOISE_TRIGGER)
&& (BgGraphBuilder.best_bg_estimate > 0)
Expand All @@ -2119,7 +2163,7 @@ private void displayCurrentInfoFromReading(BgReading lastBgReading, boolean pred

// TODO this should be made more efficient probably
if (Home.getPreferencesBooleanDefaultFalse("display_glucose_from_plugin") && (PluggableCalibration.getCalibrationPluginFromPreferences() != null)) {
currentBgValueText.setText("\u24C5" + currentBgValueText.getText()); // adds warning P in circle icon
currentBgValueText.setText(getString(R.string.p_in_circle) + currentBgValueText.getText()); // adds warning P in circle icon
}
}

Expand Down Expand Up @@ -2556,8 +2600,10 @@ public static String getPreferencesStringWithDefault(final String pref, final St
}
if (prefs != null) {
return prefs.getString(pref, def);
} else {
UserError.Log.wtf(TAG, "Could not initialize preferences in getPreferencesStringWithDefault: "+pref);
return "";
}
return "";
}

public static long getPreferencesLong(final String pref, final long def) {
Expand Down
81 changes: 81 additions & 0 deletions app/src/main/java/com/eveningoutpost/dexdrip/Models/HeartRate.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package com.eveningoutpost.dexdrip.Models;

import android.provider.BaseColumns;

import com.activeandroid.Model;
import com.activeandroid.annotation.Column;
import com.activeandroid.annotation.Table;
import com.activeandroid.query.Select;
import com.activeandroid.util.SQLiteUtils;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.annotations.Expose;

/**
* Created by jamorham on 01/11/2016.
*/


@Table(name = "HeartRate", id = BaseColumns._ID)
public class HeartRate extends Model {

private static boolean patched = false;
private final static String TAG = "HeartRate";

@Expose
@Column(name = "timestamp", unique = true, onUniqueConflicts = Column.ConflictAction.IGNORE)
public long timestamp;

@Expose
@Column(name = "bpm")
public int bpm;


// patches and saves
public Long saveit() {
fixUpTable();
return save();
}

public String toS() {
final Gson gson = new GsonBuilder()
.excludeFieldsWithoutExposeAnnotation()
.create();
return gson.toJson(this);
}

public static HeartRate last() {
try {
return new Select()
.from(HeartRate.class)
.orderBy("timestamp desc")
.executeSingle();
} catch (android.database.sqlite.SQLiteException e) {
fixUpTable();
return null;
}
}

// create the table ourselves without worrying about model versioning and downgrading
private static void fixUpTable() {
if (patched) return;
String[] patchup = {
"CREATE TABLE HeartRate (_id INTEGER PRIMARY KEY AUTOINCREMENT);",
"ALTER TABLE HeartRate ADD COLUMN timestamp INTEGER;",
"ALTER TABLE HeartRate ADD COLUMN bpm INTEGER;",
"CREATE UNIQUE INDEX index_HeartRate_timestamp on HeartRate(timestamp);"};

for (String patch : patchup) {
try {
SQLiteUtils.execSql(patch);
// UserError.Log.e(TAG, "Processed patch should not have succeeded!!: " + patch);
} catch (Exception e) {
// UserError.Log.d(TAG, "Patch: " + patch + " generated exception as it should: " + e.toString());
}
}
patched = true;
}
}



Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package com.eveningoutpost.dexdrip.Models;

import android.provider.BaseColumns;

import com.activeandroid.Model;
import com.activeandroid.annotation.Column;
import com.activeandroid.annotation.Table;
import com.activeandroid.query.Select;
import com.activeandroid.util.SQLiteUtils;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.annotations.Expose;

import java.util.List;

/**
* Created by jamorham on 01/11/2016.
*/


@Table(name = "PebbleMovement", id = BaseColumns._ID)
public class PebbleMovement extends Model {

private static boolean patched = false;
private final static String TAG = "PebbleMovement";

@Expose
@Column(name = "timestamp", unique = true, onUniqueConflicts = Column.ConflictAction.IGNORE)
public long timestamp;

@Expose
@Column(name = "metric")
public int metric;


// patches and saves
public Long saveit() {
fixUpTable();
return save();
}

public String toS() {
final Gson gson = new GsonBuilder()
.excludeFieldsWithoutExposeAnnotation()
.create();
return gson.toJson(this);
}


// static methods

public static PebbleMovement last() {
try {
return new Select()
.from(PebbleMovement.class)
.orderBy("timestamp desc")
.executeSingle();
} catch (android.database.sqlite.SQLiteException e) {
fixUpTable();
return null;
}
}

public static List<PebbleMovement> latestForGraph(int number, double startTime) {
return latestForGraph(number, (long) startTime, Long.MAX_VALUE);
}

public static List<PebbleMovement> latestForGraph(int number, long startTime) {
return latestForGraph(number, startTime, Long.MAX_VALUE);
}

public static List<PebbleMovement> latestForGraph(int number, long startTime, long endTime) {
return new Select()
.from(PebbleMovement.class)
.where("timestamp >= " + Math.max(startTime, 0))
.where("timestamp <= " + endTime)
.orderBy("timestamp asc") // warn asc!
.limit(number)
.execute();
}

// expects pre-sorted in asc order?
public static List<PebbleMovement> deltaListFromMovementList(List<PebbleMovement> mList) {
int last_metric = -1;
int temp_metric = -1;
for (PebbleMovement pm : mList) {
// first item in list
if (last_metric == -1) {
last_metric = pm.metric;
pm.metric = 0;
} else {
// normal incrementing calculate delta
if (pm.metric >= last_metric) {
temp_metric = pm.metric - last_metric;
last_metric = pm.metric;
pm.metric = temp_metric;
} else {
last_metric = pm.metric;
}
}
}
return mList;
}


// create the table ourselves without worrying about model versioning and downgrading
private static void fixUpTable() {
if (patched) return;
String[] patchup = {
"CREATE TABLE PebbleMovement (_id INTEGER PRIMARY KEY AUTOINCREMENT);",
"ALTER TABLE PebbleMovement ADD COLUMN timestamp INTEGER;",
"ALTER TABLE PebbleMovement ADD COLUMN metric INTEGER;",
"CREATE UNIQUE INDEX index_PebbleMovement_timestamp on PebbleMovement(timestamp);"};

for (String patch : patchup) {
try {
SQLiteUtils.execSql(patch);
// UserError.Log.e(TAG, "Processed patch should not have succeeded!!: " + patch);
} catch (Exception e) {
// UserError.Log.d(TAG, "Patch: " + patch + " generated exception as it should: " + e.toString());
}
}
patched = true;
}
}



Loading

0 comments on commit 595ee45

Please sign in to comment.