Added support for watch info settins in SdDataSourceGarmin. Started converting to sqlite database data logging rather than text file.

This commit is contained in:
Graham Jones
2020-01-06 20:51:14 +00:00
parent f40c363808
commit 5df5ef66c6
10 changed files with 450 additions and 12 deletions

View File

@@ -1,13 +1,114 @@
package uk.org.openseizuredetector;
import android.app.DatePickerDialog;
import android.app.TimePickerDialog;
import android.content.Context;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.TimePicker;
import java.util.Calendar;
public class DBQueryActivity extends AppCompatActivity
implements View.OnClickListener {
String TAG = "DBQueryActivity";
Button mDateBtn;
Button mTimeBtn;
Button mExportBtn;
EditText mDateTxt;
EditText mTimeTxt;
EditText mDurationTxt;
int mYear;
int mMonth;
int mDay;
int mHour;
int mMinute;
double mDuration;
OsdUtil mUtil;
Handler mHandler;
public class DBQueryActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dbquery);
mHandler = new Handler();
mUtil = new OsdUtil(this, mHandler);
mDateBtn = (Button)findViewById(R.id.dateBtn);
mDateBtn.setOnClickListener(this);
mTimeBtn = (Button)findViewById(R.id.timeBtn);
mTimeBtn.setOnClickListener(this);
mExportBtn = (Button)findViewById(R.id.exportBtn);
mExportBtn.setOnClickListener(this);
mDateTxt = (EditText)findViewById(R.id.endDateText);
mTimeTxt = (EditText)findViewById(R.id.endTimeText);
mDurationTxt = (EditText)findViewById(R.id.durationText);
// Get Current Date
final Calendar c = Calendar.getInstance();
mYear = c.get(Calendar.YEAR);
mMonth = c.get(Calendar.MONTH);
mDay = c.get(Calendar.DAY_OF_MONTH);
mHour = c.get(Calendar.HOUR_OF_DAY);
mMinute = c.get(Calendar.MINUTE);
mDateTxt.setText(String.format("%02d-%02d-%04d",mDay, mMonth+1, mYear));
mTimeTxt.setText(String.format("%02d:%02d:%02d", mHour, mMinute, 00));
mDuration = 2.0;
mDurationTxt.setText(String.format("%03.1f", mDuration));
}
@Override
public void onClick(View view) {
Log.v(TAG, "onClick()");
if (view == mDateBtn) {
DatePickerDialog datePickerDialog = new DatePickerDialog(this,
new DatePickerDialog.OnDateSetListener() {
@Override
public void onDateSet(DatePicker view, int year,
int monthOfYear, int dayOfMonth) {
mDay = dayOfMonth;
mMonth = monthOfYear;
mYear = year;
mDateTxt.setText(String.format("%02d-%02d-%04d",mDay, mMonth+1, mYear));
}
}, mYear, mMonth, mDay);
datePickerDialog.show();
}
if (view == mTimeBtn) {
// Launch Time Picker Dialog
TimePickerDialog timePickerDialog = new TimePickerDialog(this,
new TimePickerDialog.OnTimeSetListener() {
@Override
public void onTimeSet(TimePicker view, int hourOfDay,
int minute) {
mHour = hourOfDay;
mMinute = minute;
mTimeTxt.setText(String.format("%02d:%02d:%02d", mHour, mMinute, 00));
}
}, mHour, mMinute, false);
timePickerDialog.show();
}
if (view == mExportBtn) {
mDateTxt.setText(String.format("%02d-%02d-%04d",mDay, mMonth+1, mYear));
mTimeTxt.setText(String.format("%02d:%02d:%02d", mHour, mMinute, 00));
mDuration = Double.parseDouble(mDurationTxt.getText().toString());
mUtil.showToast(String.format("EndDate=%s %s, Duration=%3.1f hrs",
mDateTxt.getText().toString(), mTimeTxt.getText().toString() ,mDuration));
}
}
}

View File

@@ -28,9 +28,25 @@ import android.database.DatabaseUtils;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.AsyncTask;
import android.os.CountDownTimer;
import android.os.Handler;
import android.text.format.Time;
import android.util.Log;
import org.apache.commons.codec.binary.Base64;
import org.json.JSONObject;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import static android.database.sqlite.SQLiteDatabase.openOrCreateDatabase;
/**
@@ -47,7 +63,10 @@ public class LogManager {
private int mOSDWearerId;
private String mOSDUrl;
private OsdDbHelper mOSDDb;
private RemoteLogTimer mRemoteLogTimer;
private Context mContext;
private OsdUtil mUtil;
public LogManager(boolean logRemote,
boolean logRemoteMobile,
@@ -64,6 +83,9 @@ public class LogManager {
mOSDUrl = OSDUrl;
mContext = context;
Handler handler = new Handler();
mUtil = new OsdUtil(mContext, handler);
try {
mOSDDb = new OsdDbHelper(mDbTableName, mContext);
if (!checkTableExists(mOSDDb, mDbTableName)) {
@@ -72,9 +94,12 @@ public class LogManager {
} catch (SQLException e) {
Log.e(TAG, "Failed to open Database: " + e.toString());
}
startRemoteLogTimer();
}
private boolean checkTableExists(OsdDbHelper osdDb, String osdTableName) {
Cursor c = null;
boolean tableExists = false;
@@ -126,8 +151,142 @@ public class LogManager {
}
public void writeToRemoteServer() {
Log.v(TAG,"writeToRemoteServer()");
if (!mLogRemote) {
Log.v(TAG,"mLogRemote not set, not doing anything");
return;
}
if (!mLogRemoteMobile) {
// Check network state - are we using mobile data?
if (mUtil.isMobileDataActive()) {
Log.v(TAG,"Using mobile data, so not doing anything");
return;
}
}
if (!mUtil.isNetworkConnected()) {
Log.v(TAG,"No network connection - doing nothing");
return;
}
Log.v(TAG,"Requirements for remote logging met!");
uploadSdData();
}
/**
* Upload a batch of seizure detector data records to the server..
* Uses the UploadSdDataTask class to upload the data in the
* background. DownloadSdDataTask.onPostExecute() is called on completion.
*/
public void uploadSdData() {
Log.v(TAG, "uploadSdData()");
String dataStr = "data string to upload";
//new PostDataTask().execute("http://" + mOSDUrl + ":8080/data", dataStr, mOSDUname, mOSDPasswd);
new PostDataTask().execute("http://192.168.43.175:8765/datapoints/add", dataStr, mOSDUname, mOSDPasswd);
}
private class PostDataTask extends AsyncTask<String, Void, String> {
@Override
protected String doInBackground(String... params) {
// params comes from the execute() call:
// params[0] is the url,
// params[1] is the data to send.
// params[2] is the user name
// params[3] is the password
int MAXLEN = 500; // Maximum length of response that we will accept (bytes)
InputStream is = null;
String urlStr = params[0];
String dataStr = params[1];
String uname = params[2];
String passwd = params[3];
String resultStr = "Not Initialised";
Log.v(TAG,"doInBackgound(): url="+urlStr+" data="+dataStr+" uname="+uname+" passwd="+passwd);
try {
URL url = new URL(urlStr);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(2000 /* milliseconds */);
conn.setConnectTimeout(5000 /* milliseconds */);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/json; utf-8");
conn.setRequestProperty("Accept", "application/json");
String auth = uname + ":" + passwd;
byte[] encodedAuth = Base64.encodeBase64(auth.getBytes("utf-8"));
String authHeaderValue = "Basic " + new String(encodedAuth);
conn.setRequestProperty("Authorization", authHeaderValue);
conn.setDoInput(true);
// Put our data into the outputstream associated with the connection.
OutputStream os = conn.getOutputStream();
byte[] input = dataStr.getBytes("utf-8");
os.write(input, 0, input.length);
// Starts the query
conn.connect();
int response = conn.getResponseCode();
Log.d(TAG, "The response code is: " + response);
is = conn.getInputStream();
// Convert the InputStream into a string
Reader reader = new InputStreamReader(is, "UTF-8");
char[] buffer = new char[MAXLEN];
reader.read(buffer);
resultStr = new String(buffer);
} catch (IOException e) {
Log.v(TAG,"doInBackground(): IOException - "+e.toString());
resultStr = "Error"+e.toString();
// Makes sure that the InputStream is closed after the app is
// finished using it.
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
Log.v(TAG,"doInBackground(): IOException - "+e.toString());
resultStr = "Error"+e.toString();
}
}
}
if (resultStr.startsWith("Unable to retrieve web page")) {
Log.v(TAG,"doInBackground() - Unable to retrieve data");
} else {
Log.v(TAG,"doInBackground(): result = "+resultStr);
}
return (resultStr);
}
// onPostExecute displays the results of the AsyncTask.
@Override
protected void onPostExecute(String result) {
Log.v(TAG,"onPostExecute() - result = "+result);
}
}
public void close() {
mOSDDb.close();
stopRemoteLogTimer();
}
public JSONObject queryDatapoints(String endDateStr, Double duration) {
Log.d(TAG,"queryDatapoints() - endDateStr="+endDateStr);
Cursor c = null;
try {
c = mOSDDb.getWritableDatabase().query(mDbTableName, null,
null, null, null, null, null);
//c.query("Select * from ? where DataTime < ?", mDbTableName, endDateStr);
}
catch (Exception e) {
Log.d(TAG, mDbTableName+" doesn't exist :(((");
}
return(null);
}
public class OsdDbHelper extends SQLiteOpenHelper {
@@ -170,4 +329,54 @@ public class LogManager {
onUpgrade(db, oldVersion, newVersion);
}
}
/*
* Start the timer that will send and SMS alert after a given period.
*/
private void startRemoteLogTimer() {
if (mRemoteLogTimer != null) {
Log.v(TAG, "startRemoteLogTimer -timer already running - cancelling it");
mRemoteLogTimer.cancel();
mRemoteLogTimer = null;
}
Log.v(TAG, "startRemoteLogTimer() - starting RemoteLogTimer");
mRemoteLogTimer =
new RemoteLogTimer(10 * 1000, 1000);
mRemoteLogTimer.start();
}
/*
* Cancel the SMS timer to prevent the SMS message being sent..
*/
public void stopRemoteLogTimer() {
if (mRemoteLogTimer != null) {
Log.v(TAG, "stopRemoteLogTimer(): cancelling Remote Log timer");
mRemoteLogTimer.cancel();
mRemoteLogTimer = null;
}
}
/**
* Inhibit fault alarm initiation for a period to avoid spurious warning
* beeps caused by short term network interruptions.
*/
private class RemoteLogTimer extends CountDownTimer {
public RemoteLogTimer(long startTime, long interval) {
super(startTime, interval);
}
@Override
public void onTick(long l) {
// Do Nothing
}
@Override
public void onFinish() {
Log.v(TAG, "mRemoteLogTimer - onFinish");
writeToRemoteServer();
start();
}
}
}

View File

@@ -238,6 +238,17 @@ public class MainActivity extends AppCompatActivity {
mConnection.mSdServer.sendSMSAlarm();
}
return true;
case R.id.action_export:
Log.i(TAG, "action_export");
try {
Intent i = new Intent(
MainActivity.this,
DBQueryActivity.class);
this.startActivity(i);
} catch (Exception ex) {
Log.i(TAG, "exception starting export activity " + ex.toString());
}
return true;
case R.id.action_logs:
Log.i(TAG, "action_logs");
try {

View File

@@ -49,6 +49,8 @@ import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
@@ -295,6 +297,24 @@ public class OsdUtil implements ActivityCompat.OnRequestPermissionsResultCallbac
return null;
}
public boolean isMobileDataActive() {
// return true if we are using mobile data, otherwise return false
ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
if (activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE) {
return true;
} else {
return false;
}
}
public boolean isNetworkConnected() {
// return true if we have a network connection, otherwise false.
ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
return (activeNetwork.isConnected());
}
/**
* Display a Toast message on screen.
*

View File

@@ -354,6 +354,10 @@ public class SdDataSourceGarmin extends SdDataSource {
// Returns a message string that is passed back to the watch.
public String updateFromJSON(String jsonStr) {
String retVal = "undefined";
String watchPartNo;
String watchFwVersion;
String sdVersion;
String sdName;
Log.v(TAG,"updateFromJSON - "+jsonStr);
try {
@@ -397,6 +401,23 @@ public class SdDataSourceGarmin extends SdDataSource {
mSampleFreq = (short)dataObject.getInt("sampleFreq");
mSdData.batteryPc = (short)dataObject.getInt("battery");
Log.v(TAG,"updateFromJSON - mSamplePeriod="+mSamplePeriod+" mSampleFreq="+mSampleFreq);
mUtil.writeToSysLogFile("SdDataSourceGarmin.updateFromJSON - Settings Received");
mUtil.writeToSysLogFile(" * mSamplePeriod="+mSamplePeriod+" mSampleFreq="+mSampleFreq);
mUtil.writeToSysLogFile(" * batteryPc = "+mSdData.batteryPc);
try {
watchPartNo = dataObject.getString("watchPartNo");
watchFwVersion = dataObject.getString("watchFwVersion");
sdVersion = dataObject.getString("sdVersion");
sdName = dataObject.getString("sdName");
mUtil.writeToSysLogFile(" * sdName = "+sdName+" version "+sdVersion);
mUtil.writeToSysLogFile(" * watchPartNo = "+watchPartNo+" fwVersion "+watchFwVersion);
} catch (Exception e) {
Log.e(TAG,"updateFromJSON - Error Parsing V3.2 JSON String - "+e.toString());
mUtil.writeToSysLogFile("updateFromJSON - Error Parsing V3.2 JSON String - "+e.toString());
mUtil.writeToSysLogFile(" This is probably because of an out of date watch app - please upgrade!");
e.printStackTrace();
}
mSdData.haveSettings = true;
mSdData.mSampleFreq = mSampleFreq;
mWatchAppRunningCheck = true;
@@ -407,6 +428,7 @@ public class SdDataSourceGarmin extends SdDataSource {
}
} catch (Exception e) {
Log.e(TAG,"updateFromJSON - Error Parsing JSON String - "+e.toString());
mUtil.writeToSysLogFile("updateFromJSON - Error Parsing JSON String - "+e.toString());
e.printStackTrace();
retVal = "ERROR";
}

View File

@@ -371,6 +371,9 @@ public class SdServer extends Service implements SdDataReceiver {
}
*/
// Stop the log Manager
mLm.close();
try {
// Cancel the notification.
@@ -386,9 +389,6 @@ public class SdServer extends Service implements SdDataReceiver {
mToneGenerator.release();
mToneGenerator = null;
// Stop the log Manager
mLm.close();
// stop this service.
Log.v(TAG, "onDestroy(): calling stopSelf()");
mUtil.writeToSysLogFile("SdServer.onDestroy() - stopping self");