Merge branch 'Logging_firebase' into Logging
This commit is contained in:
@@ -2,8 +2,8 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="uk.org.openseizuredetector"
|
||||
android:versionCode="99"
|
||||
android:versionName="4.0.2">
|
||||
android:versionCode="100"
|
||||
android:versionName="4.1.1">
|
||||
<!-- android:allowBackup="false" -->
|
||||
<uses-permission android:name="android.permission.BLUETOOTH" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
|
||||
|
||||
@@ -5,6 +5,9 @@ import android.content.SharedPreferences;
|
||||
import android.net.Uri;
|
||||
import android.os.Handler;
|
||||
import android.preference.PreferenceManager;
|
||||
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import android.os.Bundle;
|
||||
@@ -15,19 +18,28 @@ import android.widget.EditText;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.firebase.ui.auth.AuthUI;
|
||||
import com.firebase.ui.auth.FirebaseAuthUIActivityResultContract;
|
||||
import com.google.android.gms.tasks.OnCompleteListener;
|
||||
import com.google.android.gms.tasks.Task;
|
||||
import com.google.firebase.auth.FirebaseAuth;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class AuthenticateActivity extends AppCompatActivity {
|
||||
private String TAG = "AuthenticateActivity";
|
||||
private OsdUtil mUtil;
|
||||
private EditText mUnameEt;
|
||||
private EditText mPasswdEt;
|
||||
private SdServiceConnection mConnection;
|
||||
final Handler serverStatusHandler = new Handler();
|
||||
private WebApiConnection mWac;
|
||||
private LogManager mLm;
|
||||
private SdServiceConnection mConnection;
|
||||
private OsdUtil mUtil;
|
||||
final Handler serverStatusHandler = new Handler();
|
||||
private String TOKEN_ID = "webApiAuthToken";
|
||||
private static final String TOKEN_ID = "webApiAuthToken";
|
||||
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
@@ -36,50 +48,88 @@ public class AuthenticateActivity extends AppCompatActivity {
|
||||
setContentView(R.layout.activity_authenticate);
|
||||
|
||||
mUtil = new OsdUtil(getApplicationContext(), serverStatusHandler);
|
||||
|
||||
if (!mUtil.isServerRunning()) {
|
||||
mUtil.showToast(getString(R.string.error_server_not_running));
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
mConnection = new SdServiceConnection(getApplicationContext());
|
||||
|
||||
Button cancelBtn =
|
||||
(Button) findViewById(R.id.cancelBtn);
|
||||
cancelBtn.setOnClickListener(onCancel);
|
||||
Button OKBtn = (Button) findViewById(R.id.OKBtn);
|
||||
OKBtn.setOnClickListener(onOK);
|
||||
Button loginBtn = (Button) findViewById(R.id.loginBtn);
|
||||
loginBtn.setOnClickListener(onLogin);
|
||||
Button logoutCancelBtn =
|
||||
(Button) findViewById(R.id.logoutCancelBtn);
|
||||
logoutCancelBtn.setOnClickListener(onCancel);
|
||||
Button logoutBtn = (Button)findViewById(R.id.logoutBtn);
|
||||
Button logoutBtn = (Button) findViewById(R.id.logoutBtn);
|
||||
logoutBtn.setOnClickListener(onLogout);
|
||||
Button registerBtn = (Button) findViewById(R.id.RegisterBtn);
|
||||
registerBtn.setOnClickListener(onRegister);
|
||||
Button resetPasswordBtn = (Button) findViewById(R.id.ResetPasswordBtn);
|
||||
resetPasswordBtn.setOnClickListener(onResetPassword);
|
||||
|
||||
mUnameEt = (EditText) findViewById(R.id.username);
|
||||
mPasswdEt = (EditText) findViewById(R.id.password);
|
||||
//mWac = new WebApiConnection(this, String tokenStr);
|
||||
//mLm = new LogManager(this);
|
||||
// Components required only for osdapi backend
|
||||
if (LogManager.USE_FIREBASE_BACKEND) { }
|
||||
else {
|
||||
mConnection = new SdServiceConnection(getApplicationContext());
|
||||
|
||||
Button registerBtn = (Button) findViewById(R.id.RegisterBtn);
|
||||
registerBtn.setOnClickListener(onRegister);
|
||||
Button resetPasswordBtn = (Button) findViewById(R.id.ResetPasswordBtn);
|
||||
resetPasswordBtn.setOnClickListener(onResetPassword);
|
||||
|
||||
mUnameEt = (EditText) findViewById(R.id.username);
|
||||
mPasswdEt = (EditText) findViewById(R.id.password);
|
||||
}
|
||||
|
||||
Button aboutDataSharingBtn = (Button) findViewById(R.id.aboutDataSharingBtn);
|
||||
aboutDataSharingBtn.setOnClickListener(
|
||||
new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
Log.v(TAG,"aboutDataSharingBtn.onClick()");
|
||||
String url = OsdUtil.DATA_SHARING_URL;
|
||||
Intent i = new Intent(Intent.ACTION_VIEW);
|
||||
i.setData(Uri.parse(url));
|
||||
startActivity(i);
|
||||
}
|
||||
}
|
||||
);
|
||||
Button privacyPolicyBtn = (Button) findViewById(R.id.privacyPolicyBtn);
|
||||
privacyPolicyBtn.setOnClickListener(
|
||||
new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
Log.v(TAG,"privacyPolicyBtn.onClick()");
|
||||
String url = OsdUtil.PRIVACY_POLICY_URL;
|
||||
Intent i = new Intent(Intent.ACTION_VIEW);
|
||||
i.setData(Uri.parse(url));
|
||||
startActivity(i);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
Log.d(TAG, "onStart()");
|
||||
super.onStart();
|
||||
mUtil.bindToServer(getApplicationContext(), mConnection);
|
||||
waitForConnection();
|
||||
if (LogManager.USE_FIREBASE_BACKEND) {
|
||||
updateUi();
|
||||
} else {
|
||||
mUtil.bindToServer(getApplicationContext(), mConnection);
|
||||
waitForConnection();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
Log.d(TAG, "onStop()");
|
||||
super.onStop();
|
||||
mUtil.unbindFromServer(getApplicationContext(), mConnection);
|
||||
}
|
||||
if (LogManager.USE_FIREBASE_BACKEND) {
|
||||
|
||||
} else {
|
||||
mUtil.unbindFromServer(getApplicationContext(), mConnection);
|
||||
}
|
||||
}
|
||||
|
||||
private void waitForConnection() {
|
||||
// We want the UI to update as soon as it is displayed, but it takes a finite time for
|
||||
@@ -100,52 +150,65 @@ public class AuthenticateActivity extends AppCompatActivity {
|
||||
}
|
||||
|
||||
private void initialiseServiceConnection() {
|
||||
Log.v(TAG,"initialiseServiceConnection()");
|
||||
mLm = mConnection.mSdServer.mLm;
|
||||
mWac = mConnection.mSdServer.mLm.mWac;
|
||||
updateUi();
|
||||
}
|
||||
|
||||
private void updateUi() {
|
||||
SharedPreferences prefs;
|
||||
String storedAuthToken;
|
||||
LinearLayout loginLl = (LinearLayout)findViewById(R.id.login_ui);
|
||||
LinearLayout logoutLl = (LinearLayout)findViewById(R.id.logout_ui);
|
||||
Log.i(TAG, "switchUi()");
|
||||
storedAuthToken = getAuthToken(); //mWac.getStoredToken();
|
||||
//prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
//storedAuthToken = (prefs.getString("webApiAuthToken", null));
|
||||
Log.v(TAG, "storedAuthToken=" + storedAuthToken);
|
||||
|
||||
// Check if we are already logged in
|
||||
if (storedAuthToken == null || storedAuthToken.length() == 0) {
|
||||
Log.v(TAG, "Not Logged in - showing log in UI");
|
||||
loginLl.setVisibility(View.VISIBLE);
|
||||
logoutLl.setVisibility(View.GONE);
|
||||
} else {
|
||||
|
||||
// Called after the Firebase Auth UI has completed
|
||||
private ActivityResultLauncher<Intent> signInLauncher = registerForActivityResult(
|
||||
new FirebaseAuthUIActivityResultContract(),
|
||||
(result) -> {
|
||||
Log.i(TAG, "FirebaseAuthUIActivityResult - " + result.toString());
|
||||
updateUi();
|
||||
});
|
||||
|
||||
// ...
|
||||
|
||||
|
||||
private void updateUi() {
|
||||
Log.v(TAG,"updateUi()");
|
||||
LinearLayout loginLl = (LinearLayout) findViewById(R.id.login_ui);
|
||||
LinearLayout osdApiLoginLl = (LinearLayout) findViewById(R.id.login_osdapi_ui);
|
||||
LinearLayout logoutLl = (LinearLayout) findViewById(R.id.logout_ui);
|
||||
|
||||
if (mWac == null) {
|
||||
Log.i(TAG,"mWac is null - not updating UI");
|
||||
return;
|
||||
}
|
||||
|
||||
if (mWac.isLoggedIn()) {
|
||||
Log.v(TAG, "Already Logged in - showing Log Out prompt");
|
||||
loginLl.setVisibility(View.GONE);
|
||||
logoutLl.setVisibility(View.VISIBLE);
|
||||
//TextView tv = (TextView)findViewById(R.id.tokenTv);
|
||||
//tv.setText("Logged in with Token: "+storedAuthToken);
|
||||
if (mWac != null) {
|
||||
mWac.getUserProfile((JSONObject profileObj) -> {
|
||||
try {
|
||||
Long userId = profileObj.getLong("id");
|
||||
String userName = profileObj.getString("username");
|
||||
TextView tv2 = (TextView) findViewById(R.id.userIdTv);
|
||||
tv2.setText(userId.toString());
|
||||
tv2 = (TextView) findViewById(R.id.usernameTv);
|
||||
tv2.setText(userName);
|
||||
} catch (JSONException e) {
|
||||
Log.e(TAG, "Error Parsing profileObj: " + e.getMessage());
|
||||
mUtil.showToast("Error Parsing profileObj - this should not happen!!!");
|
||||
}
|
||||
});
|
||||
} else {
|
||||
Log.i(TAG,"UpdateUI - not retrieving profile because mWac is null");
|
||||
if (!LogManager.USE_FIREBASE_BACKEND) {
|
||||
osdApiLoginLl.setVisibility(View.GONE);
|
||||
}
|
||||
mWac.getUserProfile((JSONObject profileObj) -> {
|
||||
try {
|
||||
String userId = profileObj.getString("id");
|
||||
String userName = profileObj.getString("username");
|
||||
TextView tv2 = (TextView) findViewById(R.id.userIdTv);
|
||||
tv2.setText(userId);
|
||||
tv2 = (TextView) findViewById(R.id.usernameTv);
|
||||
tv2.setText(userName);
|
||||
} catch (JSONException e) {
|
||||
Log.e(TAG, "Error Parsing profileObj: " + e.getMessage());
|
||||
mUtil.showToast("Error Parsing profileObj - this should not happen!!!");
|
||||
}
|
||||
});
|
||||
} else {
|
||||
Log.v(TAG,"updateUi() - not logged in..");
|
||||
loginLl.setVisibility(View.VISIBLE);
|
||||
logoutLl.setVisibility(View.GONE);
|
||||
if (!LogManager.USE_FIREBASE_BACKEND) {
|
||||
osdApiLoginLl.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
View.OnClickListener onCancel =
|
||||
@@ -158,45 +221,78 @@ public class AuthenticateActivity extends AppCompatActivity {
|
||||
}
|
||||
};
|
||||
|
||||
View.OnClickListener onOK =
|
||||
View.OnClickListener onLogin =
|
||||
new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
//m_status=true;
|
||||
Log.v(TAG, "onOK()");
|
||||
String uname = mUnameEt.getText().toString();
|
||||
String passwd = mPasswdEt.getText().toString();
|
||||
Log.v(TAG,"onOK() - uname="+uname+", passwd="+passwd);
|
||||
mWac.authenticate(uname, passwd, new WebApiConnection.StringCallback() {
|
||||
@Override
|
||||
public void accept(String retVal) {
|
||||
if (retVal != null) {
|
||||
Log.d(TAG,"Authentication Success - token is "+retVal);
|
||||
mUtil.showToast("Login Successful");
|
||||
saveAuthToken(retVal);
|
||||
updateUi();
|
||||
} else {
|
||||
Log.e(TAG,"onOk: Authentication failure for "+uname+", "+passwd);
|
||||
mUtil.showToast("ERROR: Authentication Failed - Please Try Again");
|
||||
mUtil.writeToSysLogFile("AuthActivity - Authorisation failed for "+uname+", "+passwd);
|
||||
if (LogManager.USE_FIREBASE_BACKEND) {
|
||||
Log.v(TAG, "onLogin() - using Firebase Login");
|
||||
Intent signInIntent = AuthUI.getInstance()
|
||||
.createSignInIntentBuilder()
|
||||
.setAvailableProviders(Arrays.asList(
|
||||
new AuthUI.IdpConfig.GoogleBuilder().build(),
|
||||
//new AuthUI.IdpConfig.FacebookBuilder().build(),
|
||||
//new AuthUI.IdpConfig.TwitterBuilder().build(),
|
||||
//new AuthUI.IdpConfig.MicrosoftBuilder().build(),
|
||||
//new AuthUI.IdpConfig.YahooBuilder().build(),
|
||||
//new AuthUI.IdpConfig.AppleBuilder().build(),
|
||||
new AuthUI.IdpConfig.EmailBuilder().build()
|
||||
//new AuthUI.IdpConfig.PhoneBuilder().build()
|
||||
//new AuthUI.IdpConfig.AnonymousBuilder().build()))
|
||||
))
|
||||
// ... options ...
|
||||
.build();
|
||||
signInLauncher.launch(signInIntent);
|
||||
} else {
|
||||
// Use Username and password authentication for OSDAPI.
|
||||
// FIXME - make this work with Google Authentication like we do for Firebase.
|
||||
String uname = mUnameEt.getText().toString();
|
||||
String passwd = mPasswdEt.getText().toString();
|
||||
Log.v(TAG,"onOK() - uname="+uname+", passwd="+passwd);
|
||||
mWac.authenticate(uname, passwd, new WebApiConnection.StringCallback() {
|
||||
@Override
|
||||
public void accept(String retVal) {
|
||||
if (retVal != null) {
|
||||
Log.d(TAG,"Authentication Success - token is "+retVal);
|
||||
mUtil.showToast("Login Successful");
|
||||
saveAuthToken(retVal);
|
||||
updateUi();
|
||||
} else {
|
||||
Log.e(TAG,"onOk: Authentication failure for "+uname+", "+passwd);
|
||||
mUtil.showToast("ERROR: Authentication Failed - Please Try Again");
|
||||
mUtil.writeToSysLogFile("AuthActivity - Authorisation failed for "+uname+", "+passwd);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
//finish();
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
View.OnClickListener onLogout =
|
||||
new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
Log.v(TAG, "onLogout");
|
||||
//m_status=false;
|
||||
mWac.logout();
|
||||
saveAuthToken(null);
|
||||
updateUi();
|
||||
View.OnClickListener onLogout = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
Log.v(TAG, "onLogout");
|
||||
if (LogManager.USE_FIREBASE_BACKEND) {
|
||||
AuthUI.getInstance()
|
||||
.signOut(getApplicationContext())
|
||||
.addOnCompleteListener(new OnCompleteListener<Void>() {
|
||||
public void onComplete(@NonNull Task<Void> task) {
|
||||
// user is now signed out
|
||||
updateUi();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (mWac != null) {
|
||||
mWac.logout();
|
||||
saveAuthToken(null);
|
||||
} else {
|
||||
Log.e(TAG,"logout() - mWac is null - not doing anything");
|
||||
}
|
||||
}
|
||||
};
|
||||
updateUi();
|
||||
}
|
||||
};
|
||||
|
||||
View.OnClickListener onRegister =
|
||||
new View.OnClickListener() {
|
||||
@@ -244,5 +340,4 @@ public class AuthenticateActivity extends AppCompatActivity {
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -35,7 +35,7 @@ public class EditEventActivity extends AppCompatActivity {
|
||||
private HashMap<String, ArrayList<String>> mEventSubTypesHashMap = null;
|
||||
private String mEventTypeStr = null;
|
||||
private String mEventSubTypeStr = null;
|
||||
private Long mEventId;
|
||||
private String mEventId;
|
||||
private String mEventNotes = "";
|
||||
//private Date mEventDateTime;
|
||||
private RadioGroup mEventTypeRg;
|
||||
@@ -59,7 +59,7 @@ public class EditEventActivity extends AppCompatActivity {
|
||||
|
||||
Bundle extras = getIntent().getExtras();
|
||||
if (extras != null) {
|
||||
Long eventId = extras.getLong("eventId");
|
||||
String eventId = extras.getString("eventId");
|
||||
mEventId = eventId;
|
||||
Log.v(TAG, "onCreate - mEventId=" + mEventId);
|
||||
}
|
||||
@@ -68,7 +68,7 @@ public class EditEventActivity extends AppCompatActivity {
|
||||
Button cancelBtn =
|
||||
(Button) findViewById(R.id.cancelBtn);
|
||||
cancelBtn.setOnClickListener(onCancel);
|
||||
Button OKBtn = (Button) findViewById(R.id.OKBtn);
|
||||
Button OKBtn = (Button) findViewById(R.id.loginBtn);
|
||||
OKBtn.setOnClickListener(onOK);
|
||||
|
||||
mEventTypeRg = findViewById(R.id.eventTypeRg);
|
||||
@@ -159,10 +159,10 @@ public class EditEventActivity extends AppCompatActivity {
|
||||
mWac.getEvent(mEventId, new WebApiConnection.JSONObjectCallback() {
|
||||
@Override
|
||||
public void accept(JSONObject eventObj) {
|
||||
Log.v(TAG, "onCreate.getEvent");
|
||||
Log.v(TAG, "initialiseServiceConnection.getEvent");
|
||||
if (eventObj != null) {
|
||||
mEventObj = eventObj;
|
||||
Log.v(TAG, "onCreate.getEvent: eventObj=" + eventObj.toString());
|
||||
Log.v(TAG, "initialiseServiceConnection.getEvent: eventObj=" + eventObj.toString());
|
||||
updateUi();
|
||||
// FIXME: modify updateUi to use mEventObj
|
||||
} else {
|
||||
@@ -198,20 +198,27 @@ public class EditEventActivity extends AppCompatActivity {
|
||||
try {
|
||||
if (mEventObj != null) {
|
||||
tv = (TextView) findViewById(R.id.eventIdTv);
|
||||
tv.setText(String.valueOf(mEventObj.getLong("id")));
|
||||
tv.setText(mEventId);
|
||||
tv = (TextView) findViewById(R.id.eventAlarmStateTv);
|
||||
tv.setText(mEventObj.getString("alarmStateStr"));
|
||||
String alarmStateStr = mEventObj.getString("osdAlarmState");
|
||||
try {
|
||||
int alarmStateVal = Integer.parseInt(alarmStateStr);
|
||||
alarmStateStr = mUtil.alarmStatusToString(alarmStateVal);
|
||||
} catch (Exception e) {
|
||||
Log.v(TAG,"updateUi: alarmState does not parse to int so displaying it as string: " +alarmStateStr);
|
||||
}
|
||||
tv.setText(alarmStateStr);
|
||||
tv = (TextView) findViewById(R.id.eventNotsTv);
|
||||
tv.setText(mEventObj.getString("desc"));
|
||||
|
||||
|
||||
tv = (TextView) findViewById(R.id.eventDateTv);
|
||||
try {
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
|
||||
Date dataTime = dateFormat.parse(mEventObj.getString("dataTime"));
|
||||
dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
String dateStr = mEventObj.getString("dataTime");
|
||||
Date dataTime = mUtil.string2date(dateStr);
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
tv.setText(dateFormat.format(dataTime));
|
||||
} catch (ParseException e) {
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG,"updateUI: Error Parsing dataDate "+e.getLocalizedMessage());
|
||||
tv.setText("---");
|
||||
}
|
||||
@@ -283,12 +290,12 @@ public class EditEventActivity extends AppCompatActivity {
|
||||
TextView tv = (TextView)findViewById(R.id.eventNotsTv);
|
||||
try {
|
||||
mEventObj.put("desc",tv.getText());
|
||||
mEventObj.put("id",mEventId); // Add event Id to event object manually because firestore does not include it by default.
|
||||
} catch (JSONException e) {
|
||||
Log.e(TAG,"Error writing mEventObj: "+e.getMessage());
|
||||
}
|
||||
Log.v(TAG, "onOK() - eventObj="+mEventObj.toString());
|
||||
|
||||
|
||||
try {
|
||||
mWac.updateEvent(mEventObj, new WebApiConnection.JSONObjectCallback() {
|
||||
@Override
|
||||
@@ -307,7 +314,7 @@ public class EditEventActivity extends AppCompatActivity {
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG,"ERROR:"+e.getMessage());
|
||||
Log.e(TAG,"onOK() - ERROR: "+e.getMessage()+" : " +e.toString());
|
||||
e.printStackTrace();
|
||||
mUtil.showToast("Error Updating Event");
|
||||
updateUi();
|
||||
|
||||
@@ -68,6 +68,7 @@ public class LogManager {
|
||||
static final private String TAG = "LogManager";
|
||||
//private String mDbName = "osdData";
|
||||
final static private String mDpTableName = "datapoints";
|
||||
final static private String mEventsTableName = "events";
|
||||
private boolean mLogRemote;
|
||||
private boolean mLogRemoteMobile;
|
||||
private String mAuthToken;
|
||||
@@ -76,13 +77,15 @@ public class LogManager {
|
||||
private static Context mContext;
|
||||
private OsdUtil mUtil;
|
||||
public static WebApiConnection mWac;
|
||||
public static final boolean USE_FIREBASE_BACKEND = false;
|
||||
|
||||
private boolean mUploadInProgress;
|
||||
private long mEventDuration = 120; // event duration in seconds - uploads datapoints that cover this time range centred on the event time.
|
||||
public long mDataRetentionPeriod = 1; // Prunes the local db so it only retains data younger than this duration (in days)
|
||||
private long mRemoteLogPeriod = 60; // Period in seconds between uploads to the remote server.
|
||||
private ArrayList<JSONObject> mDatapointsToUploadList;
|
||||
private int mCurrentEventId;
|
||||
private String mCurrentEventRemoteId;
|
||||
private long mCurrentEventLocalId = -1;
|
||||
private int mCurrentDatapointId;
|
||||
private long mAutoPrunePeriod = 3600; // Prune the database every hour
|
||||
private boolean mAutoPruneDb;
|
||||
@@ -121,7 +124,12 @@ public class LogManager {
|
||||
mUtil = new OsdUtil(mContext, handler);
|
||||
openDb();
|
||||
Log.i(TAG, "Starting Remote Database Interface");
|
||||
mWac = new WebApiConnection(mContext);
|
||||
if (USE_FIREBASE_BACKEND) {
|
||||
mWac = new WebApiConnection_firebase(mContext);
|
||||
} else {
|
||||
mWac = new WebApiConnection_osdapi(mContext);
|
||||
}
|
||||
|
||||
mWac.setStoredToken(mAuthToken);
|
||||
|
||||
if (mLogRemote) {
|
||||
@@ -162,7 +170,7 @@ public class LogManager {
|
||||
try {
|
||||
datapoint.put("id", c.getString(c.getColumnIndex("id")));
|
||||
datapoint.put("dataTime", c.getString(c.getColumnIndex("dataTime")));
|
||||
datapoint.put("status", c.getString(c.getColumnIndex("Status")));
|
||||
datapoint.put("status", c.getString(c.getColumnIndex("status")));
|
||||
datapoint.put("dataJSON", c.getString(c.getColumnIndex("dataJSON")));
|
||||
datapoint.put("uploaded", c.getString(c.getColumnIndex("uploaded")));
|
||||
//Log.v(TAG,"cursor2json() - datapoint="+datapoint.toString());
|
||||
@@ -177,6 +185,41 @@ public class LogManager {
|
||||
return dataPointArray.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a JSON String representing an array of events that are selected from sqlite cursor c.
|
||||
*
|
||||
* @param c sqlite cursor pointing to events query result.
|
||||
* @return JSON String.
|
||||
* from https://stackoverflow.com/a/20488153/2104584
|
||||
*/
|
||||
private String eventCursor2Json(Cursor c) {
|
||||
StringBuilder cNames = new StringBuilder();
|
||||
for (String n : c.getColumnNames()) {
|
||||
cNames.append(", ").append(n);
|
||||
}
|
||||
c.moveToFirst();
|
||||
Log.v(TAG, "eventCursor2Json: size of cursor=" + c.getCount());
|
||||
JSONArray eventsArray = new JSONArray();
|
||||
int i = 0;
|
||||
while (!c.isAfterLast()) {
|
||||
JSONObject event = new JSONObject();
|
||||
try {
|
||||
event.put("id", c.getString(c.getColumnIndex("id")));
|
||||
event.put("dataTime", c.getString(c.getColumnIndex("dataTime")));
|
||||
event.put("status", c.getString(c.getColumnIndex("status")));
|
||||
event.put("uploaded", c.getString(c.getColumnIndex("uploaded")));
|
||||
c.moveToNext();
|
||||
eventsArray.put(i, event);
|
||||
i++;
|
||||
} catch (JSONException e) {
|
||||
Log.e(TAG, "eventCursor2Json(): error creating JSON Object");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
Log.v(TAG, "eventCursor2JSON(): returning " + eventsArray.toString());
|
||||
return eventsArray.toString();
|
||||
}
|
||||
|
||||
|
||||
private static boolean openDb() {
|
||||
Log.d(TAG, "openDb");
|
||||
@@ -187,11 +230,14 @@ public class LogManager {
|
||||
} else {
|
||||
Log.i(TAG, "openDb: mOsdDb has been initialised already so not doing anything");
|
||||
}
|
||||
if (!checkTableExists(mOsdDb, mDpTableName)) {
|
||||
Log.e(TAG, "ERROR - Table " + mDpTableName + " does not exist");
|
||||
return false;
|
||||
} else {
|
||||
Log.d(TAG, "table " + mDpTableName + " exists ok");
|
||||
String[] tableNames = new String[]{mDpTableName, mEventsTableName};
|
||||
for (String tableName : tableNames) {
|
||||
if (!checkTableExists(mOsdDb, tableName)) {
|
||||
Log.e(TAG, "ERROR - Table " + tableName + " does not exist");
|
||||
return false;
|
||||
} else {
|
||||
Log.d(TAG, "table " + tableName + " exists ok");
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
Log.e(TAG, "Failed to open Database: " + e.toString());
|
||||
@@ -221,17 +267,19 @@ public class LogManager {
|
||||
* FIXME - I am sure we should not be using raw SQL Srings to do this!
|
||||
*/
|
||||
public void writeDatapointToLocalDb(SdData sdData) {
|
||||
Log.v(TAG, "writeDatapointToLocalDb()");
|
||||
//Log.v(TAG, "writeDatapointToLocalDb()");
|
||||
Date curDate = new Date();
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
String dateStr = dateFormat.format(curDate);
|
||||
String SQLStr = "SQLStr";
|
||||
|
||||
if (mOsdDb == null) {
|
||||
Log.e(TAG, "writeDatapointToLocalDb(): mOsdDb is null - doing nothing");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
//double roiRatio = -1;
|
||||
//if (sdData.specPower != 0)
|
||||
// roiRatio = 10. * sdData.roiPower / sdData.specPower;
|
||||
// Write Datapoint to database
|
||||
SQLStr = "INSERT INTO " + mDpTableName
|
||||
+ "(dataTime, status, dataJSON, uploaded)"
|
||||
+ " VALUES("
|
||||
@@ -240,20 +288,55 @@ public class LogManager {
|
||||
+ DatabaseUtils.sqlEscapeString(sdData.toJSON(true)) + ","
|
||||
+ 0
|
||||
+ ")";
|
||||
if (mOsdDb != null) {
|
||||
mOsdDb.execSQL(SQLStr);
|
||||
Log.v(TAG, "writeDatapointToLocalDb(): data written to database");
|
||||
} else {
|
||||
Log.e(TAG,"writeDatapointToLocalDb(): mOsdDb is null");
|
||||
}
|
||||
mOsdDb.execSQL(SQLStr);
|
||||
Log.v(TAG, "writeDatapointToLocalDb(): datapoint written to database");
|
||||
|
||||
if (sdData.alarmState != 0) {
|
||||
Log.i(TAG, "writeDatapointToLocalDb(): adding event to local DB");
|
||||
createLocalEvent(dateStr, sdData.alarmState);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
Log.e(TAG, "writeToLocalDb(): Error Writing Data: " + e.toString());
|
||||
Log.e(TAG, "SQLStr was " + SQLStr);
|
||||
} catch (NullPointerException e) {
|
||||
Log.e(TAG, "writeToLocalDb(): Null Pointer Exception: " + e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public boolean createLocalEvent(String dataTime, long status) {
|
||||
// Expects dataTime to be in format: SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
Log.d(TAG,"createLocalEvent() - dataTime="+dataTime+", status="+status);
|
||||
// Write Datapoint to database
|
||||
String SQLStr = "INSERT INTO " + mEventsTableName
|
||||
+ "(dataTime, status)"
|
||||
+ " VALUES("
|
||||
+ "'" + dataTime + "',"
|
||||
+ status
|
||||
+ ")";
|
||||
mOsdDb.execSQL(SQLStr);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a json representation of locally stored event 'id'.
|
||||
*
|
||||
* @param id event id to return
|
||||
* @return JSON representation of requested event (single element JSON array)
|
||||
*/
|
||||
public String getLocalEventById(long id) {
|
||||
Log.d(TAG, "getLocalEventById() - id=" + id);
|
||||
Cursor c;
|
||||
String retVal;
|
||||
try {
|
||||
String selectStr = "select * from " + mEventsTableName + " where id=" + id + ";";
|
||||
c = mOsdDb.rawQuery(selectStr, null);
|
||||
retVal = eventCursor2Json(c);
|
||||
} catch (Exception e) {
|
||||
Log.d(TAG, "getLocalEventById(): Error Querying Database: " + e.getLocalizedMessage());
|
||||
retVal = null;
|
||||
}
|
||||
Log.d(TAG, "getLocalEventById() - returning " + retVal);
|
||||
return (retVal);
|
||||
}
|
||||
|
||||
|
||||
@@ -269,9 +352,6 @@ public class LogManager {
|
||||
String retVal;
|
||||
try {
|
||||
String selectStr = "select * from " + mDpTableName + " where id=" + id + ";";
|
||||
//String[] selectArgs = new String[]{String.format("%d", id)};
|
||||
//c = mOSDDb.getWritableDatabase().query(mDbTableName, null,
|
||||
// selectStr, selectArgs, null, null, null);
|
||||
c = mOsdDb.rawQuery(selectStr, null);
|
||||
retVal = cursor2Json(c);
|
||||
} catch (Exception e) {
|
||||
@@ -279,7 +359,6 @@ public class LogManager {
|
||||
retVal = null;
|
||||
}
|
||||
return (retVal);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -289,15 +368,17 @@ public class LogManager {
|
||||
* @param eventId - the eventId associated with the uploaded datapoint - the 'uploaded' field is set to this value.
|
||||
* @return True on success or False on failure.
|
||||
*/
|
||||
public boolean setDatapointToUploaded(int id, int eventId) {
|
||||
public boolean setDatapointToUploaded(int id, String eventId) {
|
||||
Log.d(TAG, "setDatapointToUploaded() - id=" + id);
|
||||
if (mOsdDb == null) {
|
||||
Log.e(TAG,"setDatapointToUploaded() - mOsdDb is null - not doing anything");
|
||||
return false;
|
||||
}
|
||||
ContentValues cv = new ContentValues();
|
||||
cv.put("uploaded", eventId);
|
||||
int nRowsUpdated = mOsdDb.update(mDpTableName, cv, "id = ?",
|
||||
new String[]{String.format("%d", id)});
|
||||
|
||||
return (nRowsUpdated == 1);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -356,7 +437,7 @@ public class LogManager {
|
||||
String whereClause = getEventWhereClause(includeWarnings);
|
||||
//sqlStr = "SELECT * from " + mDbTableName + " where Status in (" + statusListStr + ") order by dataTime desc;";
|
||||
String[] columns = {"*"};
|
||||
new SelectQueryTask(mDpTableName, columns, whereClause, whereArgs,
|
||||
new SelectQueryTask(mEventsTableName, columns, whereClause, whereArgs,
|
||||
null, null, "dataTime DESC", (Cursor cursor) -> {
|
||||
Log.v(TAG, "getEventsList - returned " + cursor);
|
||||
if (cursor != null) {
|
||||
@@ -365,7 +446,7 @@ public class LogManager {
|
||||
HashMap<String, String> event = new HashMap<>();
|
||||
//event.put("id", cursor.getString(cursor.getColumnIndex("id")));
|
||||
event.put("dataTime", cursor.getString(cursor.getColumnIndex("dataTime")));
|
||||
int status = cursor.getInt(cursor.getColumnIndex("Status"));
|
||||
int status = cursor.getInt(cursor.getColumnIndex("status"));
|
||||
String statusStr = mUtil.alarmStatusToString(status);
|
||||
event.put("status", statusStr);
|
||||
event.put("uploaded", cursor.getString(cursor.getColumnIndex("uploaded")));
|
||||
@@ -385,25 +466,48 @@ public class LogManager {
|
||||
*/
|
||||
public int pruneLocalDb() {
|
||||
Log.d(TAG, "pruneLocalDb()");
|
||||
int retVal;
|
||||
int retVal = 0;
|
||||
long currentDateMillis = new Date().getTime();
|
||||
long endDateMillis = currentDateMillis - 24 * 3600 * 1000 * mDataRetentionPeriod;
|
||||
//long endDateMillis = currentDateMillis - 3600*1000* mDataRetentionPeriod; // Using hours rather than days for testing
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
String endDateStr = dateFormat.format(new Date(endDateMillis));
|
||||
try {
|
||||
String selectStr = "DataTime<=?";
|
||||
String[] selectArgs = {endDateStr};
|
||||
retVal = mOsdDb.delete(mDpTableName, selectStr, selectArgs);
|
||||
} catch (Exception e) {
|
||||
Log.d(TAG, "Error deleting datapoints" + e.toString());
|
||||
retVal = 0;
|
||||
String[] tableNames = new String[]{mDpTableName, mEventsTableName};
|
||||
for (String tableName : tableNames) {
|
||||
Log.i(TAG, "pruneLocalDb - pruning table " + tableName);
|
||||
try {
|
||||
String selectStr = "DataTime<=?";
|
||||
String[] selectArgs = {endDateStr};
|
||||
retVal = mOsdDb.delete(tableName, selectStr, selectArgs);
|
||||
} catch (Exception e) {
|
||||
Log.d(TAG, "Error deleting data " + e.toString());
|
||||
retVal = 0;
|
||||
}
|
||||
Log.d(TAG, String.format("pruneLocalDb() - deleted %d records from table %s", retVal, tableName));
|
||||
}
|
||||
Log.d(TAG, String.format("pruneLocalDb() - deleted %d records", retVal));
|
||||
return (retVal);
|
||||
}
|
||||
|
||||
/**
|
||||
* setEventToUploaded
|
||||
*
|
||||
* @param localEventId - local Event ID to change
|
||||
* @param remoteEventId - the remote eventId associated with the uploaded datapoint - the 'uploaded' field is set to this value.
|
||||
* @return True on success or False on failure.
|
||||
*/
|
||||
public boolean setEventToUploaded(long localEventId, String remoteEventId) {
|
||||
Log.d(TAG, "setEventToUploaded() - local id=" + localEventId + " remote id="+remoteEventId);
|
||||
if (mOsdDb == null) {
|
||||
Log.e(TAG,"setEventToUploaded() - mOsdDb is null - not doing anything");
|
||||
return false;
|
||||
}
|
||||
ContentValues cv = new ContentValues();
|
||||
cv.put("uploaded", remoteEventId);
|
||||
int nRowsUpdated = mOsdDb.update(mEventsTableName, cv, "id = ?",
|
||||
new String[]{String.format("%d", localEventId)});
|
||||
return (nRowsUpdated == 1);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the ID of the next event (alarm, warning, fall etc that needs to be uploaded (alarm or warning condition and has not yet been uploaded.
|
||||
@@ -423,7 +527,7 @@ public class LogManager {
|
||||
long endDateMillis = currentDateMillis - 1000 * mEventDuration;
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
String endDateStr = dateFormat.format(new Date(endDateMillis));
|
||||
String whereClauseUploaded = "uploaded = 0";
|
||||
String whereClauseUploaded = "uploaded is null";
|
||||
String whereClauseDate = "DataTime<?";
|
||||
String whereClause = whereClauseStatus + " AND " + whereClauseUploaded + " AND " + whereClauseDate;
|
||||
|
||||
@@ -432,9 +536,8 @@ public class LogManager {
|
||||
whereArgs[i] = whereArgsStatus[i];
|
||||
}
|
||||
whereArgs[whereArgsStatus.length] = endDateStr;
|
||||
new SelectQueryTask(mDpTableName, columns, whereClause, whereArgs,
|
||||
new SelectQueryTask(mEventsTableName, columns, whereClause, whereArgs,
|
||||
null, null, "dataTime DESC", (Cursor cursor) -> {
|
||||
Log.v(TAG, "getEventsList - returned " + cursor);
|
||||
Long recordId = new Long(-1);
|
||||
if (cursor != null) {
|
||||
Log.v(TAG, "getNextEventToUpload - returned " + cursor.getCount() + " records");
|
||||
@@ -443,9 +546,8 @@ public class LogManager {
|
||||
Log.v(TAG, "getNextEventToUpload() - no events to Upload - exiting");
|
||||
recordId = new Long(-1);
|
||||
} else {
|
||||
String recordStr = cursor.getString(3);
|
||||
recordId = cursor.getLong(0);
|
||||
Log.d(TAG, "getNextEventToUpload(): id=" + recordId + ", recordStr=" + recordStr);
|
||||
Log.d(TAG, "getNextEventToUpload(): id=" + recordId);
|
||||
}
|
||||
}
|
||||
callback.accept(recordId);
|
||||
@@ -494,13 +596,13 @@ public class LogManager {
|
||||
* @return True on successful start or false if call fails.
|
||||
*/
|
||||
public boolean getLocalEventsCount(boolean includeWarnings, WebApiConnection.LongCallback callback) {
|
||||
Log.v(TAG, "getLocalEventsCount- includeWarnings=" + includeWarnings);
|
||||
//Log.v(TAG, "getLocalEventsCount- includeWarnings=" + includeWarnings);
|
||||
String[] whereArgs = getEventWhereArgs(includeWarnings);
|
||||
String whereClause = getEventWhereClause(includeWarnings);
|
||||
String[] columns = {"*"};
|
||||
new SelectQueryTask(mDpTableName, columns, whereClause, whereArgs,
|
||||
new SelectQueryTask(mEventsTableName, columns, whereClause, whereArgs,
|
||||
null, null, null, (Cursor cursor) -> {
|
||||
Log.v(TAG, "getLocalEventsCount - returned " + cursor);
|
||||
//Log.v(TAG, "getLocalEventsCount - returned " + cursor);
|
||||
Long eventCount = Long.valueOf(0);
|
||||
if (cursor != null) {
|
||||
eventCount = Long.valueOf(cursor.getCount());
|
||||
@@ -517,13 +619,13 @@ public class LogManager {
|
||||
* @return True on successful start or false if call fails.
|
||||
*/
|
||||
public boolean getLocalDatapointsCount(WebApiConnection.LongCallback callback) {
|
||||
Log.v(TAG, "getLocalDatapointsCount");
|
||||
//Log.v(TAG, "getLocalDatapointsCount");
|
||||
String[] whereArgs = null;
|
||||
String whereClause = null;
|
||||
String[] columns = {"*"};
|
||||
new SelectQueryTask(mDpTableName, columns, whereClause, whereArgs,
|
||||
null, null, null, (Cursor cursor) -> {
|
||||
Log.v(TAG, "getLocalDatapointsCount - returned " + cursor);
|
||||
//Log.v(TAG, "getLocalDatapointsCount - returned " + cursor);
|
||||
Long eventCount = Long.valueOf(0);
|
||||
if (cursor != null) {
|
||||
eventCount = Long.valueOf(cursor.getCount());
|
||||
@@ -568,7 +670,7 @@ public class LogManager {
|
||||
|
||||
@Override
|
||||
protected Cursor doInBackground(Void... params) {
|
||||
Log.v(TAG, "runSelect.doInBackground()");
|
||||
//Log.v(TAG, "runSelect.doInBackground()");
|
||||
Log.v(TAG, "SelectQueryTask.doInBackground: mTable=" + mTable + ", mColumns=" + Arrays.toString(mColumns)
|
||||
+ ", mSelection=" + mSelection + ", mSelectionArgs=" + Arrays.toString(mSelectionArgs) + ", mGroupBy=" + mGroupBy
|
||||
+ ", mHaving =" + mHaving + ", mOrderBy=" + mOrderBy);
|
||||
@@ -659,17 +761,24 @@ public class LogManager {
|
||||
*/
|
||||
public void uploadSdData() {
|
||||
//int eventId = -1;
|
||||
Log.v(TAG, "uploadSdData()");
|
||||
//Log.v(TAG, "uploadSdData()");
|
||||
// First try uploading full alarms, and only if we do not have any of those, upload warnings.
|
||||
boolean warningsArr[] = { false, true };
|
||||
for (int n=0; n<warningsArr.length; n++) {
|
||||
//boolean warningsArr[] = {false, true};
|
||||
// Upload everything - alarms and warnings - we can sort it out in post-processing the data!
|
||||
boolean warningsArr[] = {true};
|
||||
for (int n = 0; n < warningsArr.length; n++) {
|
||||
boolean warningsVal = warningsArr[n];
|
||||
Log.i(TAG, "uploadSdData(): warningsVal=" + warningsVal);
|
||||
if (mUploadInProgress) {
|
||||
Log.d(TAG, "uploadSdData - upload already in progress - not doing anything");
|
||||
return;
|
||||
}
|
||||
mUploadInProgress = true;
|
||||
getNextEventToUpload(warningsVal, (Long eventId) -> {
|
||||
if (eventId != -1) {
|
||||
Log.v(TAG, "uploadSdData() - eventId=" + eventId);
|
||||
String eventJsonStr = getDatapointById(eventId);
|
||||
Log.v(TAG, "uploadSdData() - eventJsonStr=" + eventJsonStr);
|
||||
Log.i(TAG, "uploadSdData() - next Event to Upload eventId=" + eventId);
|
||||
String eventJsonStr = getLocalEventById(eventId);
|
||||
Log.v(TAG, "uploadSdData() - event to upload eventJsonStr=" + eventJsonStr);
|
||||
//int eventType;
|
||||
JSONObject eventObj;
|
||||
int eventAlarmStatus;
|
||||
@@ -680,36 +789,42 @@ public class LogManager {
|
||||
eventObj = datapointJsonArr.getJSONObject(0); // We only look at the first (and hopefully only) item in the array.
|
||||
eventAlarmStatus = Integer.parseInt(eventObj.getString("status"));
|
||||
eventDateStr = eventObj.getString("dataTime");
|
||||
Log.v(TAG, "uploadSdData - data from local DB is:" + eventJsonStr + ", eventAlarmStatus="
|
||||
Log.d(TAG, "uploadSdData - data from local DB is:" + eventJsonStr + ", eventAlarmStatus="
|
||||
+ eventAlarmStatus + ", eventDateStr=" + eventDateStr);
|
||||
} catch (JSONException e) {
|
||||
Log.e(TAG, "ERROR parsing event JSON Data" + eventJsonStr);
|
||||
Log.e(TAG, "uploadSdData(): ERROR parsing event JSON Data" + eventJsonStr);
|
||||
e.printStackTrace();
|
||||
return;
|
||||
} catch (NullPointerException e) {
|
||||
Log.e(TAG, "ERROR null pointer exception parsing event JSON Data" + eventJsonStr);
|
||||
Log.e(TAG, "uploadSdData(): ERROR null pointer exception parsing event JSON Data" + eventJsonStr);
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
try {
|
||||
eventDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(eventDateStr);
|
||||
} catch (ParseException e) {
|
||||
Log.e(TAG, "Error parsing date " + eventDateStr);
|
||||
Log.e(TAG, "UploadSdData(): Error parsing date " + eventDateStr);
|
||||
return;
|
||||
}
|
||||
|
||||
Log.i(TAG, "uploadSdData - calling mWac.createEvent");
|
||||
mCurrentEventLocalId = eventId;
|
||||
mWac.createEvent(eventAlarmStatus, eventDate, "", this::createEventCallback);
|
||||
} else {
|
||||
Log.v(TAG, "UploadSdData - no data to upload");
|
||||
Log.v(TAG, "uploadSdData - no data to upload "); //(warnings="+warningsVal+")");
|
||||
mUploadInProgress = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Mark the relevant member variables to show we are not currently doing an upload, so a new one can be
|
||||
// Mark the relevant member variables to show we are not cuurrently doing an upload, so a new one can be
|
||||
// started if necessary.
|
||||
public void finishUpload() {
|
||||
mCurrentEventId = -1;
|
||||
mCurrentEventRemoteId = null;
|
||||
mCurrentEventLocalId = -1;
|
||||
mCurrentDatapointId = -1;
|
||||
mDatapointsToUploadList = null;
|
||||
mUploadInProgress = false;
|
||||
}
|
||||
@@ -717,82 +832,97 @@ public class LogManager {
|
||||
// Called by WebApiConnection when a new event record is created.
|
||||
// Once the event is created it queries the local database to find the datapoints associated with the event
|
||||
// and uploads those as a batch of data points.
|
||||
public void createEventCallback(String eventStr) {
|
||||
Log.v(TAG, "eventCallback(): " + eventStr);
|
||||
Date eventDate;
|
||||
String eventDateStr;
|
||||
int eventId;
|
||||
try {
|
||||
JSONObject eventObj = new JSONObject(eventStr);
|
||||
eventDateStr = eventObj.getString("dataTime");
|
||||
eventId = eventObj.getInt("id");
|
||||
} catch (JSONException e) {
|
||||
Log.e(TAG, "eventCallback() - Error parsing eventStr: " + eventStr);
|
||||
finishUpload();
|
||||
return;
|
||||
}
|
||||
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
|
||||
try {
|
||||
eventDate = dateFormat.parse(eventDateStr);
|
||||
} catch (ParseException e) {
|
||||
Log.e(TAG, "eventCallback() - error parsing date string " + eventDateStr);
|
||||
finishUpload();
|
||||
return;
|
||||
}
|
||||
Log.v(TAG, "eventCallback() EventId=" + eventId + ", eventDateStr=" + eventDateStr + ", eventDate=" + eventDate);
|
||||
long eventDateMillis = eventDate.getTime();
|
||||
long startDateMillis = eventDateMillis - 1000 * mEventDuration / 2;
|
||||
long endDateMillis = eventDateMillis + 1000 * mEventDuration / 2;
|
||||
dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
getDatapointsByDate(
|
||||
dateFormat.format(new Date(startDateMillis)),
|
||||
dateFormat.format(new Date(endDateMillis)), (String datapointsJsonStr) -> {
|
||||
Log.v(TAG, "eventCallback() - datapointsJsonStr=" + datapointsJsonStr);
|
||||
JSONArray dataObj;
|
||||
mDatapointsToUploadList = new ArrayList<JSONObject>();
|
||||
public void createEventCallback(String eventId) {
|
||||
Log.v(TAG, "createEventCallback(): " + eventId);
|
||||
Log.v(TAG, "createEventCallback(): Retrieving remote event details");
|
||||
mWac.getEvent(eventId, new WebApiConnection.JSONObjectCallback() {
|
||||
@Override
|
||||
public void accept(JSONObject eventObj) {
|
||||
if (eventObj == null) {
|
||||
Log.e(TAG,"createEventCallback() - eventObj is null - failed to create event");
|
||||
mUtil.showToast("Error Creating Remote Event");
|
||||
} else {
|
||||
Log.v(TAG, "createEventCallback() - eventObj=" + eventObj.toString());
|
||||
Date eventDate;
|
||||
String eventDateStr = "";
|
||||
try {
|
||||
//DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
|
||||
dataObj = new JSONArray(datapointsJsonStr);
|
||||
for (int i = 0; i < dataObj.length(); i++) {
|
||||
mDatapointsToUploadList.add(dataObj.getJSONObject(i));
|
||||
}
|
||||
String dateStr= eventObj.getString("dataTime");
|
||||
eventDate = mUtil.string2date(dateStr);
|
||||
} catch (JSONException e) {
|
||||
Log.v(TAG, "Error Creating JSON Object from string " + datapointsJsonStr);
|
||||
dataObj = null;
|
||||
Log.e(TAG, "createEventCallback() - Error parsing JSONObject: " + eventObj.toString());
|
||||
finishUpload();
|
||||
return;
|
||||
}
|
||||
if (eventDate != null) {
|
||||
Log.v(TAG, "createEventCallback() EventId=" + eventId + ", eventDateStr=" + eventDateStr + ", eventDate=" + eventDate);
|
||||
mUploadInProgress = true;
|
||||
long eventDateMillis = eventDate.getTime();
|
||||
long startDateMillis = eventDateMillis - 1000 * mEventDuration / 2;
|
||||
long endDateMillis = eventDateMillis + 1000 * mEventDuration / 2;
|
||||
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
getDatapointsByDate(
|
||||
dateFormat.format(new Date(startDateMillis)),
|
||||
dateFormat.format(new Date(endDateMillis)),
|
||||
(String datapointsJsonStr) -> {
|
||||
//Log.v(TAG, "createEventCallback() - datapointsJsonStr=" + datapointsJsonStr);
|
||||
JSONArray dataObj;
|
||||
mDatapointsToUploadList = new ArrayList<JSONObject>();
|
||||
try {
|
||||
//DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
|
||||
dataObj = new JSONArray(datapointsJsonStr);
|
||||
Log.v(TAG, "createEventCallback() - datapointsObj length=" + dataObj.length());
|
||||
for (int i = 0; i < dataObj.length(); i++) {
|
||||
mDatapointsToUploadList.add(dataObj.getJSONObject(i));
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
Log.v(TAG, "createEventCallback(): Error Creating JSON Object from string " + datapointsJsonStr);
|
||||
dataObj = null;
|
||||
finishUpload();
|
||||
}
|
||||
// This starts the process of uploading the datapoints, one at a time.
|
||||
mCurrentEventRemoteId = eventId;
|
||||
Log.v(TAG, "createEventCallback() - starting datapoints upload with eventId " + mCurrentEventRemoteId +
|
||||
" Uploading " + mDatapointsToUploadList.size() + " datapoints");
|
||||
uploadNextDatapoint();
|
||||
|
||||
});
|
||||
} else {
|
||||
Log.e(TAG,"createEventCallback() - Error - event date is null - not doing anything");
|
||||
mUtil.showToast("Error uploading event - date is null");
|
||||
finishUpload();
|
||||
}
|
||||
// This starts the process of uploading the datapoints, one at a time.
|
||||
mCurrentEventId = eventId;
|
||||
mUploadInProgress = true;
|
||||
Log.v(TAG, "eventCallback() - starting datapoints upload with eventId " + mCurrentEventId);
|
||||
uploadNextDatapoint();
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// takes the next datapoint of the list mDatapointsToUploadList and uploads it to the remote server.
|
||||
// datapointCallback is called when the upload is complete.
|
||||
public void uploadNextDatapoint() {
|
||||
Log.v(TAG, "uploadDatapoint()");
|
||||
if (mDatapointsToUploadList.size() > 0) {
|
||||
mUploadInProgress = true;
|
||||
try {
|
||||
mCurrentDatapointId = mDatapointsToUploadList.get(0).getInt("id");
|
||||
} catch (JSONException e) {
|
||||
Log.e(TAG, "Error reading currentDatapointID from mDatapointsToUploadList[0]" + e.getMessage());
|
||||
Log.e(TAG, "Removing mDatapointsToUploadList[0] and trying the next datapoint");
|
||||
mDatapointsToUploadList.remove(0);
|
||||
uploadNextDatapoint();
|
||||
//Log.v(TAG, "uploadNextDatapoint()");
|
||||
if (mDatapointsToUploadList != null) {
|
||||
if (mDatapointsToUploadList.size() > 0) {
|
||||
mUploadInProgress = true;
|
||||
try {
|
||||
mCurrentDatapointId = mDatapointsToUploadList.get(0).getInt("id");
|
||||
} catch (JSONException e) {
|
||||
Log.e(TAG, "uploadNextDatapoint(): Error reading currentDatapointID from mDatapointsToUploadList[0]" + e.getMessage());
|
||||
Log.e(TAG, "uploadNextDatapoint(): Removing mDatapointsToUploadList[0] and trying the next datapoint");
|
||||
mDatapointsToUploadList.remove(0);
|
||||
uploadNextDatapoint();
|
||||
}
|
||||
|
||||
Log.v(TAG, "uploadNextDatapoint() - " + mDatapointsToUploadList.size() + " datapoints to upload. Uploading datapoint ID:" + mCurrentDatapointId);
|
||||
mWac.createDatapoint(mDatapointsToUploadList.get(0), mCurrentEventRemoteId, this::datapointCallback);
|
||||
|
||||
} else {
|
||||
Log.i(TAG, "uploadNextDatapoint() - All datapoints uploaded!");
|
||||
setEventToUploaded(mCurrentEventLocalId, mCurrentEventRemoteId);
|
||||
finishUpload();
|
||||
}
|
||||
|
||||
Log.v(TAG, "uploadDatapoint() - uploading datapoint with local id of " + mCurrentDatapointId);
|
||||
mWac.createDatapoint(mDatapointsToUploadList.get(0), mCurrentEventId, this::datapointCallback);
|
||||
|
||||
} else {
|
||||
mCurrentEventId = -1;
|
||||
mCurrentDatapointId = -1;
|
||||
mUploadInProgress = false;
|
||||
Log.w(TAG,"uploadNextDatapoint - mDatapointsToUploadList is null - I don't thin this should have happened!");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -800,11 +930,15 @@ public class LogManager {
|
||||
// a datapoint based on mDatapointsToUploadList(0) so removes that from the list and calls UploadDatapoint()
|
||||
// to upload the next one.
|
||||
public void datapointCallback(String datapointStr) {
|
||||
Log.v(TAG, "datapointCallback() " + datapointStr + ", mCurrentEventId=" + mCurrentEventId);
|
||||
if (mDatapointsToUploadList.size() > 0) {
|
||||
mDatapointsToUploadList.remove(0);
|
||||
Log.v(TAG, "datapointCallback() dataPointId="+mCurrentDatapointId+" remote datapointID=" + datapointStr + ", mCurrentEventId=" + mCurrentEventRemoteId);
|
||||
if (mDatapointsToUploadList != null) {
|
||||
if (mDatapointsToUploadList.size() > 0) {
|
||||
mDatapointsToUploadList.remove(0);
|
||||
}
|
||||
} else {
|
||||
Log.w(TAG,"datapointCallback - mDatapointsToUploadList is null - I don't thin this should have happened!");
|
||||
}
|
||||
setDatapointToUploaded(mCurrentDatapointId, mCurrentEventId);
|
||||
setDatapointToUploaded(mCurrentDatapointId, mCurrentEventRemoteId);
|
||||
uploadNextDatapoint();
|
||||
}
|
||||
|
||||
@@ -903,9 +1037,19 @@ public class LogManager {
|
||||
String SQLStr = "CREATE TABLE IF NOT EXISTS " + mDpTableName + "("
|
||||
+ "id INTEGER PRIMARY KEY,"
|
||||
+ "dataTime DATETIME,"
|
||||
+ "Status INT,"
|
||||
+ "status INT,"
|
||||
+ "dataJSON TEXT,"
|
||||
+ "uploaded INT"
|
||||
+ "uploaded TEXT" // Stores the ID of the datapoint in the remote database if uploaded, otherwise empty
|
||||
+ ");";
|
||||
db.execSQL(SQLStr);
|
||||
Log.i(TAG, "onCreate - TableName=" + mEventsTableName);
|
||||
SQLStr = "CREATE TABLE IF NOT EXISTS " + mEventsTableName + "("
|
||||
+ "id INTEGER PRIMARY KEY,"
|
||||
+ "dataTime DATETIME,"
|
||||
+ "status INT,"
|
||||
+ "type TEXT,"
|
||||
+ "subType TEXT,"
|
||||
+ "uploaded TEXT" // stores the id of the event in the remote dabase if uploaded, otherwise empty
|
||||
+ ");";
|
||||
db.execSQL(SQLStr);
|
||||
}
|
||||
|
||||
@@ -11,9 +11,11 @@ import android.os.Bundle;
|
||||
import android.os.CountDownTimer;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
|
||||
import androidx.core.view.MenuCompat;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
@@ -219,14 +221,34 @@ public class LogManagerControlActivity extends AppCompatActivity {
|
||||
// A bit of a hack to display in reverse chronological order
|
||||
for (int i = eventsArray.length() - 1; i >= 0; i--) {
|
||||
JSONObject eventObj = eventsArray.getJSONObject(i);
|
||||
Long id = eventObj.getLong("id");
|
||||
int osdAlarmState = eventObj.getInt("osdAlarmState");
|
||||
String dataTime = eventObj.getString("dataTime");
|
||||
String typeStr = eventObj.getString("type");
|
||||
String subType = eventObj.getString("subType");
|
||||
String desc = eventObj.getString("desc");
|
||||
Log.v(TAG, "getRemoteEvents() - " + eventObj.toString());
|
||||
String id = null;
|
||||
if (!eventObj.isNull("id")) {
|
||||
id = eventObj.getString("id");
|
||||
}
|
||||
int osdAlarmState = -1;
|
||||
if (!eventObj.isNull("osdAlarmState")) {
|
||||
osdAlarmState = eventObj.getInt("osdAlarmState");
|
||||
}
|
||||
String dataTime = "null";
|
||||
if (!eventObj.isNull("dataTime")) {
|
||||
dataTime = eventObj.getString("dataTime");
|
||||
Log.v(TAG, "getRemoteEvents() - dataTime=" + dataTime);
|
||||
}
|
||||
String typeStr = "null";
|
||||
if (!eventObj.isNull("type")) {
|
||||
typeStr = eventObj.getString("type");
|
||||
}
|
||||
String subType = "null";
|
||||
if (!eventObj.isNull("subType")) {
|
||||
subType = eventObj.getString("subType");
|
||||
}
|
||||
String desc = "null";
|
||||
if (!eventObj.isNull("desc")) {
|
||||
desc = eventObj.getString("desc");
|
||||
}
|
||||
HashMap<String, String> eventHashMap = new HashMap<String, String>();
|
||||
eventHashMap.put("id", String.valueOf(id));
|
||||
eventHashMap.put("id", id);
|
||||
eventHashMap.put("osdAlarmState", String.valueOf(osdAlarmState));
|
||||
eventHashMap.put("osdAlarmStateStr", mUtil.alarmStatusToString(osdAlarmState));
|
||||
eventHashMap.put("dataTime", dataTime);
|
||||
@@ -249,7 +271,7 @@ public class LogManagerControlActivity extends AppCompatActivity {
|
||||
|
||||
|
||||
private void updateUi() {
|
||||
Log.i(TAG,"updateUi()");
|
||||
Log.i(TAG, "updateUi()");
|
||||
boolean stopUpdating = true;
|
||||
TextView tv;
|
||||
Button btn;
|
||||
@@ -291,9 +313,9 @@ public class LogManagerControlActivity extends AppCompatActivity {
|
||||
if (mRemoteEventsList != null) {
|
||||
ListView lv = (ListView) findViewById(R.id.remoteEventsLv);
|
||||
ListAdapter adapter = new RemoteEventsAdapter(LogManagerControlActivity.this, mRemoteEventsList, R.layout.log_entry_layout_remote,
|
||||
new String[]{"id","dataTime", "type", "subType", "osdAlarmStateStr", "desc"},
|
||||
new String[]{"id", "dataTime", "type", "subType", "osdAlarmStateStr", "desc"},
|
||||
new int[]{R.id.event_id_remote_tv, R.id.event_date_remote_tv, R.id.event_type_remote_tv, R.id.event_subtype_remote_tv,
|
||||
R.id.event_alarmState_remote_tv, R.id.event_notes_remote_tv});
|
||||
R.id.event_alarmState_remote_tv, R.id.event_notes_remote_tv});
|
||||
lv.setAdapter(adapter);
|
||||
//Log.i(TAG,"adapter[0]="+adapter.getItem(0));
|
||||
//Log.i(TAG,"adapter[3]="+adapter.getItem(3));
|
||||
@@ -328,14 +350,14 @@ public class LogManagerControlActivity extends AppCompatActivity {
|
||||
} //updateUi();
|
||||
|
||||
public void onRadioButtonClicked(View view) {
|
||||
LinearLayout localDataLl = (LinearLayout) findViewById(R.id.local_data_ll);
|
||||
LinearLayout localDataLl = (LinearLayout) findViewById(R.id.local_data_ll);
|
||||
LinearLayout sharedDataLl = (LinearLayout) findViewById(R.id.shared_data_ll);
|
||||
LinearLayout syslogLl = (LinearLayout) findViewById(R.id.syslog_ll);
|
||||
// Is the button now checked?
|
||||
boolean checked = ((RadioButton) view).isChecked();
|
||||
|
||||
// Check which radio button was clicked
|
||||
switch(view.getId()) {
|
||||
switch (view.getId()) {
|
||||
case R.id.local_data_rb:
|
||||
if (checked) {
|
||||
// Switch to the local data view
|
||||
@@ -351,7 +373,7 @@ public class LogManagerControlActivity extends AppCompatActivity {
|
||||
sharedDataLl.setVisibility(View.VISIBLE);
|
||||
syslogLl.setVisibility(View.GONE);
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case R.id.syslog_rb:
|
||||
if (checked) {
|
||||
// Switch to the local data view
|
||||
@@ -411,7 +433,6 @@ public class LogManagerControlActivity extends AppCompatActivity {
|
||||
}
|
||||
|
||||
|
||||
|
||||
View.OnClickListener onAuth =
|
||||
new View.OnClickListener() {
|
||||
@Override
|
||||
@@ -504,7 +525,7 @@ public class LogManagerControlActivity extends AppCompatActivity {
|
||||
public void onItemClick(AdapterView<?> adapter, View v, int position, long id) {
|
||||
Log.v(TAG, "onRemoteEventList Click() - Position=" + position + ", id=" + id);// Confirmation dialog based on: https://stackoverflow.com/a/12213536/2104584
|
||||
HashMap<String, String> eventObj = (HashMap<String, String>) adapter.getItemAtPosition(position);
|
||||
Long eventId = Long.parseLong(eventObj.get("id"));
|
||||
String eventId = eventObj.get("id");
|
||||
Log.d(TAG, "onItemClickListener(): eventId=" + eventId + ", eventObj=" + eventObj);
|
||||
Intent i = new Intent(getApplicationContext(), EditEventActivity.class);
|
||||
i.putExtra("eventId", eventId);
|
||||
@@ -588,9 +609,9 @@ public class LogManagerControlActivity extends AppCompatActivity {
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
View v = super.getView(position, convertView, parent);
|
||||
Map<String, ?> dataItem = (Map<String,?>)getItem(position);
|
||||
Log.v(TAG,"getView() "+dataItem.toString());
|
||||
switch(dataItem.get("type").toString()) {
|
||||
Map<String, ?> dataItem = (Map<String, ?>) getItem(position);
|
||||
Log.v(TAG, "getView() " + dataItem.toString());
|
||||
switch (dataItem.get("type").toString()) {
|
||||
case "null":
|
||||
v.setBackgroundColor(Color.parseColor("#ffaaaa"));
|
||||
break;
|
||||
@@ -603,20 +624,17 @@ public class LogManagerControlActivity extends AppCompatActivity {
|
||||
|
||||
// Convert date format to something more readable.
|
||||
TextView tv = (TextView) v.findViewById(R.id.event_date_remote_tv);
|
||||
try {
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
|
||||
Date dataTime = dateFormat.parse(dataItem.get("dataTime").toString());
|
||||
dateFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
|
||||
Date dataTime = null;
|
||||
String dateStr = (String) dataItem.get("dataTime");
|
||||
dataTime = mUtil.string2date(dateStr);
|
||||
if (dataTime != null) {
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
|
||||
tv.setText(dateFormat.format(dataTime));
|
||||
} catch (ParseException e) {
|
||||
Log.e(TAG,"remoteEventsAdapter.getView: Error Parsing dataDate "+e.getLocalizedMessage());
|
||||
} else {
|
||||
tv.setText("---");
|
||||
}
|
||||
|
||||
|
||||
return(v);
|
||||
return (v);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -631,7 +631,7 @@ public class MainActivity extends AppCompatActivity {
|
||||
tv.setBackgroundColor(okColour);
|
||||
tv.setTextColor(okTextColour);
|
||||
|
||||
if (!mConnection.mSdServer.mLm.mWac.mServerConnectionOk) {
|
||||
if (!mConnection.mSdServer.mLm.mWac.checkServerConnection()) {
|
||||
// Problem connecting to server
|
||||
tv = (TextView) findViewById(R.id.remoteDbTv);
|
||||
tv.setText(getString(R.string.data_sharing_status)
|
||||
|
||||
@@ -59,6 +59,7 @@ import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@@ -453,6 +454,31 @@ public class OsdUtil {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* string2date - returns a Date object represented by string dateStr
|
||||
* It first attempts to parse it as a long integer, in which case it is assumed to
|
||||
* be a unix timestamp.
|
||||
* If that fails it attempts to parse it as yyyy-MM-dd'T'HH:mm:ss'Z' format.
|
||||
* @param dateStr String reprenting a date
|
||||
* @return Date object or null if parsing fails.
|
||||
*/
|
||||
public Date string2date(String dateStr) {
|
||||
Date dataTime = null;
|
||||
try {
|
||||
Long tstamp = Long.parseLong(dateStr);
|
||||
dataTime = new Date(tstamp);
|
||||
} catch (NumberFormatException e) {
|
||||
Log.v(TAG, "remoteEventsAdapter.getView: Error Parsing dataDate as Long: " + e.getLocalizedMessage()+" trying as string");
|
||||
try {
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
|
||||
dataTime = dateFormat.parse(dateStr);
|
||||
} catch (ParseException e2) {
|
||||
Log.e(TAG, "remoteEventsAdapter.getView: Error Parsing dataDate " + e2.getLocalizedMessage());
|
||||
dataTime = null;
|
||||
}
|
||||
}
|
||||
return(dataTime);
|
||||
}
|
||||
|
||||
|
||||
public final int ALARM_STATUS_WARNING = 1;
|
||||
|
||||
@@ -17,6 +17,7 @@ import android.widget.DatePicker;
|
||||
import android.widget.TextView;
|
||||
import android.widget.TimePicker;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
|
||||
/**
|
||||
@@ -40,6 +41,7 @@ public class ReportSeizureActivity extends AppCompatActivity {
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
Log.v(TAG, "onCreate()");
|
||||
super.onCreate(savedInstanceState);
|
||||
mContext = this;
|
||||
mUtil = new OsdUtil(this, serverStatusHandler);
|
||||
if (!mUtil.isServerRunning()) {
|
||||
mUtil.showToast(getString(R.string.error_server_not_running));
|
||||
@@ -65,7 +67,7 @@ public class ReportSeizureActivity extends AppCompatActivity {
|
||||
//mLm= new LogManager(mContext);
|
||||
|
||||
Button okBtn =
|
||||
(Button) findViewById(R.id.OKBtn);
|
||||
(Button) findViewById(R.id.loginBtn);
|
||||
okBtn.setOnClickListener(onOk);
|
||||
|
||||
Button cancelBtn =
|
||||
@@ -142,22 +144,12 @@ public class ReportSeizureActivity extends AppCompatActivity {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
Log.v(TAG, "onOk");
|
||||
//SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
String dateStr=String.format("%4d-%02d-%02d %02d:%02d:30",mYear,mMonth+1,mDay, mHour, mMinute);
|
||||
Log.v(TAG, "onOk() - dateSTr="+dateStr);
|
||||
mMsg = "Finding Nearest Datapoint to Date/Time "+dateStr+"...";
|
||||
mLm.getNearestDatapointToDate(dateStr, (Long id) -> {
|
||||
mMsg = mMsg + "\nNearest Datapoint is "+id;
|
||||
Log.v(TAG, "onOK() - nearest datapoint is "+id);
|
||||
if (id!=-1) {
|
||||
mLm.setDatapointStatus(id,5);
|
||||
mMsg = mMsg + "\nSet Datapoint to Manual Alarm Status";
|
||||
mUtil.showToast(getString(R.string.createdNewEvent));
|
||||
finish();
|
||||
} else {
|
||||
mMsg = mMsg + "\n*** Datapoint not found - not doing anything ***";
|
||||
mUtil.showToast(getString(R.string.DatapointNotFound));
|
||||
}
|
||||
});
|
||||
mLm.createLocalEvent(dateStr,5);
|
||||
mUtil.showToast("Seizure Event Created");
|
||||
finish();
|
||||
}
|
||||
};
|
||||
View.OnClickListener onCancel =
|
||||
|
||||
@@ -138,7 +138,7 @@ public class SdServer extends Service implements SdDataReceiver {
|
||||
private long mEventsTimerPeriod = 60; // Number of seconds between checks to see if there are unvalidated remote events.
|
||||
private long mEventDuration = 120; // event duration in seconds - uploads datapoints that cover this time range centred on the event time.
|
||||
public long mDataRetentionPeriod = 1; // Prunes the local db so it only retains data younger than this duration (in days)
|
||||
private long mRemoteLogPeriod = 60; // Period in seconds between uploads to the remote server.
|
||||
private long mRemoteLogPeriod = 20; // Period in seconds between uploads to the remote server.
|
||||
private long mAutoPrunePeriod = 3600; // Prune the database every hour
|
||||
private boolean mAutoPruneDb;
|
||||
|
||||
@@ -1137,7 +1137,7 @@ public class SdServer extends Service implements SdDataReceiver {
|
||||
//writeToSD();
|
||||
mLm.writeDatapointToLocalDb(mSdData);
|
||||
} else {
|
||||
Log.e(TAG,"logData() - mLm is null - this should not happen");
|
||||
Log.e(TAG, "logData() - mLm is null - this should not happen");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1241,7 +1241,7 @@ public class SdServer extends Service implements SdDataReceiver {
|
||||
|
||||
//prefVal = SP.getString("RemoteLogPeriod", "60");
|
||||
//mRemoteLogPeriod = Integer.parseInt(prefVal);
|
||||
mRemoteLogPeriod = 60;
|
||||
//mRemoteLogPeriod = 60;
|
||||
Log.v(TAG, "mRemoteLogPeriod=" + mRemoteLogPeriod);
|
||||
|
||||
//mOSDUname = SP.getString("OSDUname", "<username>");
|
||||
@@ -1300,8 +1300,8 @@ public class SdServer extends Service implements SdDataReceiver {
|
||||
Log.i(TAG, "SmsTimer.onFinish() - Last Location is Null so sending first SMS without location.");
|
||||
}
|
||||
} else {
|
||||
Log.e(TAG,"SmsTImer.onFinish() - mLocationFinder is NULL - this should not happen!");
|
||||
mUtil.showToast("Error Finding Location - mLocationFinder is null - please report this issue!");
|
||||
Log.e(TAG,"SmsTimer.onFinish - mLocationFinder is null - this should not happen!");
|
||||
mUtil.showToast("SmsTimer.onFinish - mLocationFinder is null - this should not happen! - Please report this issue!");
|
||||
}
|
||||
Log.i(TAG, "SmsTimer.onFinish() - Sending to " + mSMSNumbers.length + " Numbers");
|
||||
mUtil.writeToSysLogFile("SdServer.SmsTimer.onFinish()");
|
||||
@@ -1555,28 +1555,26 @@ public class SdServer extends Service implements SdDataReceiver {
|
||||
// Retrieve events from remote database
|
||||
if (mLm.mWac.getEvents((JSONObject remoteEventsObj) -> {
|
||||
Log.v(TAG, "CheckEvents.getEvents.Callback()");
|
||||
long firstUnvalidatedEvent;
|
||||
Boolean haveUnvalidatedEvent = false;
|
||||
if (remoteEventsObj == null) {
|
||||
Log.e(TAG, "CheckEvents.Callback: Error Retrieving events");
|
||||
} else {
|
||||
try {
|
||||
JSONArray eventsArray = remoteEventsObj.getJSONArray("events");
|
||||
// A bit of a hack to display in reverse chronological order
|
||||
firstUnvalidatedEvent = -1;
|
||||
for (int i = eventsArray.length() - 1; i >= 0; i--) {
|
||||
JSONObject eventObj = eventsArray.getJSONObject(i);
|
||||
Long id = eventObj.getLong("id");
|
||||
String typeStr = eventObj.getString("type");
|
||||
//Log.v(TAG,"CheckEventsTimer: id="+id+", typeStr="+typeStr);
|
||||
if (typeStr.equals("null")) {
|
||||
firstUnvalidatedEvent = id;
|
||||
if (typeStr.equals("null") || typeStr.equals("")) {
|
||||
haveUnvalidatedEvent = true;
|
||||
//Log.v(TAG,"CheckEventsTimer:setting firstUnvalidatedEvent to "+firstUnvalidatedEvent);
|
||||
}
|
||||
}
|
||||
Log.v(TAG, "CheckEventsTimer.onFinish.callback - firstUnvalidatedEvent = " +
|
||||
firstUnvalidatedEvent);
|
||||
if (firstUnvalidatedEvent >= 0) {
|
||||
showEventNotification(firstUnvalidatedEvent);
|
||||
Log.v(TAG, "CheckEventsTimer.onFinish.callback - haveUnvalidatedEvent = " +
|
||||
haveUnvalidatedEvent);
|
||||
if (haveUnvalidatedEvent) {
|
||||
showEventNotification();
|
||||
mNM.cancel(DATASHARE_NOTIFICATION_ID);
|
||||
} else {
|
||||
mNM.cancel(EVENT_NOTIFICATION_ID);
|
||||
@@ -1627,7 +1625,7 @@ public class SdServer extends Service implements SdDataReceiver {
|
||||
/**
|
||||
* Show a notification to tell the user that we have unvalidated events.
|
||||
*/
|
||||
private void showEventNotification(long eventId) {
|
||||
private void showEventNotification() {
|
||||
Log.v(TAG, "showEventNotification()");
|
||||
int iconId;
|
||||
String titleStr;
|
||||
|
||||
@@ -4,6 +4,8 @@ import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.android.volley.AuthFailureError;
|
||||
import com.android.volley.Request;
|
||||
import com.android.volley.RequestQueue;
|
||||
@@ -12,6 +14,18 @@ import com.android.volley.VolleyError;
|
||||
import com.android.volley.VolleyLog;
|
||||
import com.android.volley.toolbox.StringRequest;
|
||||
import com.android.volley.toolbox.Volley;
|
||||
import com.google.android.gms.tasks.OnCompleteListener;
|
||||
import com.google.android.gms.tasks.OnFailureListener;
|
||||
import com.google.android.gms.tasks.OnSuccessListener;
|
||||
import com.google.android.gms.tasks.Task;
|
||||
import com.google.firebase.auth.FirebaseAuth;
|
||||
import com.google.firebase.firestore.DocumentReference;
|
||||
import com.google.firebase.firestore.DocumentSnapshot;
|
||||
import com.google.firebase.firestore.FirebaseFirestore;
|
||||
import com.google.firebase.firestore.Query;
|
||||
import com.google.firebase.firestore.QueryDocumentSnapshot;
|
||||
import com.google.firebase.firestore.QuerySnapshot;
|
||||
import com.google.firebase.firestore.core.OrderBy;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
@@ -22,20 +36,19 @@ import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
// This class is intended to handle all interactions with the OSD WebAPI
|
||||
public class WebApiConnection {
|
||||
public String retVal;
|
||||
public int retCode;
|
||||
public boolean mServerConnectionOk = false;
|
||||
private String mUrlBase = "https://osdApi.ddns.net";
|
||||
public abstract class WebApiConnection {
|
||||
protected Context mContext;
|
||||
protected OsdUtil mUtil;
|
||||
private String TAG = "WebApiConnection";
|
||||
private String mAuthToken;
|
||||
private Context mContext;
|
||||
private OsdUtil mUtil;
|
||||
RequestQueue mQueue;
|
||||
|
||||
|
||||
|
||||
public interface JSONObjectCallback {
|
||||
public void accept(JSONObject retValObj);
|
||||
@@ -51,237 +64,23 @@ public class WebApiConnection {
|
||||
|
||||
public WebApiConnection(Context context) {
|
||||
mContext = context;
|
||||
mQueue = Volley.newRequestQueue(context);
|
||||
mUtil = new OsdUtil(mContext, new Handler());
|
||||
}
|
||||
|
||||
public void close() {
|
||||
Log.i(TAG,"stop()");
|
||||
mQueue.stop();
|
||||
Log.i(TAG, "stop()");
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to authenticate with the web API using user name uname and password passwd. Calls function callback with either
|
||||
* the authentication token on success or null on failure.
|
||||
*
|
||||
* @param uname - user name
|
||||
* @param passwd - password
|
||||
* @param callback - call back function callback(String retVal)
|
||||
* @return true if request sent, or false if failed to send request.
|
||||
*/
|
||||
public boolean authenticate(final String uname, final String passwd, StringCallback callback) {
|
||||
// NOTE: the 'final' keyword is necessary for uname and passwd to be accessible to getParams below - I don't know why!
|
||||
// We know that this command works, so we just need the Java equivalent:
|
||||
// curl -X POST -d 'login=graham4&password=testpwd1' https://osdapi.ddns.net/api/accounts/login/
|
||||
// sending the credentials as a JSONObject postData did not work, so try the method from:
|
||||
// https://protocoderspoint.com/login-and-registration-form-in-android-using-volley-keeping-user-logged-in/#Login_Registration_form_in_android_using_volley_library
|
||||
String urlStr = mUrlBase + "/api/accounts/login/";
|
||||
Log.v(TAG, "urlStr=" + urlStr);
|
||||
|
||||
StringRequest req = new StringRequest(Request.Method.POST, urlStr,
|
||||
new Response.Listener<String>() {
|
||||
@Override
|
||||
public void onResponse(String response) {
|
||||
String tokenStr = null;
|
||||
Log.v(TAG, "Response is: " + response);
|
||||
try {
|
||||
JSONObject jo = new JSONObject(response);
|
||||
tokenStr = jo.getString("token");
|
||||
mServerConnectionOk = true;
|
||||
} catch (JSONException e) {
|
||||
tokenStr = "Error Parsing Rsponse";
|
||||
}
|
||||
setStoredToken(tokenStr);
|
||||
callback.accept(tokenStr);
|
||||
}
|
||||
},
|
||||
new Response.ErrorListener() {
|
||||
@Override
|
||||
public void onErrorResponse(VolleyError error) {
|
||||
if (error != null) {
|
||||
Log.e(TAG, "Login Error: " + error.toString() + ", message:" + error.getMessage());
|
||||
} else {
|
||||
Log.e(TAG, "Login Error: Returned null response");
|
||||
}
|
||||
mServerConnectionOk = false;
|
||||
setStoredToken(null);
|
||||
callback.accept(null);
|
||||
}
|
||||
}) {
|
||||
// Note, this is overriding part of StringRequest, not one of the sub-classes above!
|
||||
@Override
|
||||
protected Map<String, String> getParams() {
|
||||
Map<String, String> params = new HashMap<>();
|
||||
// params.put("name",sname); // passing parameters to server
|
||||
params.put("login", uname);
|
||||
params.put("password", passwd);
|
||||
return params;
|
||||
}
|
||||
};
|
||||
|
||||
mQueue.add(req);
|
||||
return (true);
|
||||
}
|
||||
|
||||
// Remove the stored token so future calls are not authenticated.
|
||||
public void logout() {
|
||||
Log.v(TAG, "logout()");
|
||||
setStoredToken(null);
|
||||
//saveStoredToken(null);
|
||||
}
|
||||
|
||||
public void setStoredToken(String authToken) {
|
||||
mAuthToken = authToken;
|
||||
}
|
||||
|
||||
private String getStoredToken() {
|
||||
return (mAuthToken);
|
||||
}
|
||||
|
||||
public boolean isLoggedIn() {
|
||||
String authToken = getStoredToken();
|
||||
//Log.v(TAG, "isLoggedIn(): token=" + authToken);
|
||||
if (authToken == null || authToken.length() == 0) {
|
||||
//Log.v(TAG, "isLogged in - not logged in");
|
||||
return (false);
|
||||
} else {
|
||||
return (true);
|
||||
}
|
||||
|
||||
}
|
||||
public abstract boolean isLoggedIn();
|
||||
|
||||
|
||||
// Create a new event in the remote database, based on the provided parameters.
|
||||
public boolean createEvent(final int osdAlarmState, final Date eventDate, final String eventDesc, StringCallback callback) {
|
||||
Log.v(TAG, "createEvent()");
|
||||
String urlStr = mUrlBase + "/api/events/";
|
||||
Log.v(TAG, "urlStr=" + urlStr);
|
||||
final String authtoken = getStoredToken();
|
||||
// passes the newly created documentId to function callback on successful completion, or null on error.
|
||||
public abstract boolean createEvent(final int osdAlarmState, final Date eventDate, final String eventDesc, StringCallback callback);
|
||||
|
||||
if (!isLoggedIn()) {
|
||||
Log.v(TAG, "not logged in - doing nothing");
|
||||
return (false);
|
||||
}
|
||||
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
try {
|
||||
jsonObject.put("osdAlarmState", String.valueOf(osdAlarmState));
|
||||
jsonObject.put("dataTime", dateFormat.format(eventDate));
|
||||
jsonObject.put("desc", eventDesc);
|
||||
} catch (JSONException e) {
|
||||
Log.e(TAG, "Error generating event JSON string");
|
||||
}
|
||||
final String dataStr = jsonObject.toString();
|
||||
Log.v(TAG, "createEvent - data=" + dataStr);
|
||||
// calls function callback with a JSONObject representation of the event with id 'eventId'
|
||||
public abstract boolean getEvent(String eventId, JSONObjectCallback callback);
|
||||
|
||||
StringRequest req = new StringRequest(Request.Method.POST, urlStr,
|
||||
new Response.Listener<String>() {
|
||||
@Override
|
||||
public void onResponse(String response) {
|
||||
Log.v(TAG, "Response is: " + response);
|
||||
mServerConnectionOk = true;
|
||||
callback.accept(response);
|
||||
}
|
||||
},
|
||||
new Response.ErrorListener() {
|
||||
@Override
|
||||
public void onErrorResponse(VolleyError error) {
|
||||
mServerConnectionOk = false;
|
||||
if (error != null) {
|
||||
Log.e(TAG, "Create Event Error: " + error.toString() + ", message:" + error.getMessage());
|
||||
callback.accept(null);
|
||||
} else {
|
||||
Log.e(TAG, "Create Event Error - null respones");
|
||||
callback.accept(null);
|
||||
}
|
||||
}
|
||||
}) {
|
||||
// Note, this is overriding part of StringRequest, not one of the sub-classes above!
|
||||
@Override
|
||||
protected Map<String, String> getParams() {
|
||||
Map<String, String> params = new HashMap<>();
|
||||
// params.put("name",sname); // passing parameters to server
|
||||
String authToken = getStoredToken();
|
||||
params.put("Authorization: Token " + authToken, authToken);
|
||||
Log.v(TAG, "getParams: params=" + params.toString());
|
||||
return params;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getHeaders() throws AuthFailureError {
|
||||
Map<String, String> params = new HashMap<String, String>();
|
||||
params.put("Content-Type", "application/json; charset=UTF-8");
|
||||
params.put("Authorization", "Token " + getStoredToken());
|
||||
return params;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getBody() throws AuthFailureError {
|
||||
try {
|
||||
return dataStr == null ? null : dataStr.getBytes("utf-8");
|
||||
} catch (UnsupportedEncodingException uee) {
|
||||
VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s", dataStr, "utf-8");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
mQueue.add(req);
|
||||
return (true);
|
||||
}
|
||||
|
||||
public boolean getEvent(Long eventId, JSONObjectCallback callback) {
|
||||
//Long eventId=Long.valueOf(285);
|
||||
Log.v(TAG, "getEvent()");
|
||||
String urlStr = mUrlBase + "/api/events/" + eventId;
|
||||
Log.v(TAG, "getEvent(): urlStr=" + urlStr);
|
||||
final String authtoken = getStoredToken();
|
||||
|
||||
if (!isLoggedIn()) {
|
||||
Log.v(TAG, "not logged in - doing nothing");
|
||||
return (false);
|
||||
}
|
||||
|
||||
StringRequest req = new StringRequest(Request.Method.GET, urlStr,
|
||||
new Response.Listener<String>() {
|
||||
@Override
|
||||
public void onResponse(String response) {
|
||||
Log.v(TAG, "Response is: " + response);
|
||||
try {
|
||||
JSONObject retObj = new JSONObject(response);
|
||||
retObj.put("alarmStateStr", mUtil.alarmStatusToString(retObj.getInt("osdAlarmState")));
|
||||
callback.accept(retObj);
|
||||
} catch (JSONException e) {
|
||||
Log.e(TAG, "getEventTypes.onRespons(): Error: " + e.getMessage() + "," + e.toString());
|
||||
callback.accept(null);
|
||||
}
|
||||
mServerConnectionOk = true;
|
||||
}
|
||||
},
|
||||
new Response.ErrorListener() {
|
||||
@Override
|
||||
public void onErrorResponse(VolleyError error) {
|
||||
if (error != null) {
|
||||
Log.e(TAG, "Create Event Error: " + error.toString() + ", message:" + error.getMessage());
|
||||
} else {
|
||||
Log.e(TAG, "Create Event Error: returned null response");
|
||||
}
|
||||
mServerConnectionOk = false;
|
||||
callback.accept(null);
|
||||
}
|
||||
}) {
|
||||
|
||||
@Override
|
||||
public Map<String, String> getHeaders() throws AuthFailureError {
|
||||
Map<String, String> params = new HashMap<String, String>();
|
||||
params.put("Content-Type", "application/json; charset=UTF-8");
|
||||
params.put("Authorization", "Token " + getStoredToken());
|
||||
return params;
|
||||
}
|
||||
};
|
||||
mQueue.add(req);
|
||||
return (true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve all events accessible to the logged in user, and pass them to the callback function as a JSONObject
|
||||
@@ -289,305 +88,11 @@ public class WebApiConnection {
|
||||
* @param callback
|
||||
* @return true on success or false on failure to initiate the request.
|
||||
*/
|
||||
public boolean getEvents(JSONObjectCallback callback) {
|
||||
//Long eventId=Long.valueOf(285);
|
||||
Log.v(TAG, "getEvents()");
|
||||
String urlStr = mUrlBase + "/api/events/";
|
||||
Log.v(TAG, "getEvents(): urlStr=" + urlStr);
|
||||
final String authtoken = getStoredToken();
|
||||
|
||||
if (!isLoggedIn()) {
|
||||
Log.v(TAG, "not logged in - doing nothing");
|
||||
return (false);
|
||||
}
|
||||
|
||||
StringRequest req = new StringRequest(Request.Method.GET, urlStr,
|
||||
new Response.Listener<String>() {
|
||||
@Override
|
||||
public void onResponse(String response) {
|
||||
Log.v(TAG, "Response is: " + response);
|
||||
mServerConnectionOk = true;
|
||||
try {
|
||||
JSONObject retObj = new JSONObject();
|
||||
JSONArray eventArray = new JSONArray(response);
|
||||
retObj.put("events", eventArray);
|
||||
callback.accept(retObj);
|
||||
} catch (JSONException e) {
|
||||
Log.e(TAG, "getEventTypes.onRespons(): Error: " + e.getMessage() + "," + e.toString());
|
||||
callback.accept(null);
|
||||
}
|
||||
}
|
||||
},
|
||||
new Response.ErrorListener() {
|
||||
@Override
|
||||
public void onErrorResponse(VolleyError error) {
|
||||
//if ((error != null) && (error.networkResponse != null) && (error.networkResponse.data != null)) {#
|
||||
mServerConnectionOk = false;
|
||||
if (error != null) {
|
||||
if (error.networkResponse != null) {
|
||||
Log.e(TAG, "getEvents(): Error: " + error.toString() + ", message:" + error.getMessage());
|
||||
} else {
|
||||
Log.e(TAG, "getEvents(): Error: - request returned null networkResponse");
|
||||
}
|
||||
} else{
|
||||
Log.e(TAG, "getEvents(): Error: - request returned null response");
|
||||
}
|
||||
callback.accept(null);
|
||||
}
|
||||
}) {
|
||||
|
||||
@Override
|
||||
public Map<String, String> getHeaders() throws AuthFailureError {
|
||||
Map<String, String> params = new HashMap<String, String>();
|
||||
params.put("Content-Type", "application/json; charset=UTF-8");
|
||||
params.put("Authorization", "Token " + getStoredToken());
|
||||
return params;
|
||||
}
|
||||
};
|
||||
mQueue.add(req);
|
||||
return (true);
|
||||
}
|
||||
|
||||
|
||||
public boolean updateEvent(final JSONObject eventObj, JSONObjectCallback callback) {
|
||||
Long eventId;
|
||||
Log.v(TAG, "updateEvent()");
|
||||
final String authtoken = getStoredToken();
|
||||
|
||||
if (!isLoggedIn()) {
|
||||
Log.v(TAG, "not logged in - doing nothing");
|
||||
return (false);
|
||||
}
|
||||
try {
|
||||
eventId = eventObj.getLong("id");
|
||||
} catch (JSONException e) {
|
||||
Log.e(TAG, "updateEvent(): Error reading id from eventObj");
|
||||
eventId = Long.valueOf(-1);
|
||||
}
|
||||
final String dataStr = eventObj.toString();
|
||||
Log.v(TAG, "createEvent - data=" + dataStr);
|
||||
|
||||
|
||||
int reqMethod;
|
||||
String urlStr;
|
||||
if (eventId != -1) {
|
||||
Log.v(TAG, "updateEvent() - found eventId " + eventId + ", Updating event record");
|
||||
urlStr = mUrlBase + "/api/events/" + eventId + "/";
|
||||
Log.v(TAG, "urlStr=" + urlStr);
|
||||
reqMethod = Request.Method.PUT;
|
||||
} else {
|
||||
Log.v(TAG, "updateEvent() - eventId not found - creating new event record");
|
||||
urlStr = mUrlBase + "/api/events/";
|
||||
Log.v(TAG, "urlStr=" + urlStr);
|
||||
reqMethod = Request.Method.POST;
|
||||
}
|
||||
|
||||
StringRequest req = new StringRequest(reqMethod, urlStr,
|
||||
new Response.Listener<String>() {
|
||||
@Override
|
||||
public void onResponse(String response) {
|
||||
Log.v(TAG, "Response is: " + response);
|
||||
mServerConnectionOk = true;
|
||||
try {
|
||||
JSONObject retObj = new JSONObject(response);
|
||||
callback.accept(retObj);
|
||||
} catch (JSONException e) {
|
||||
Log.e(TAG, "getEventTypes.onRespons(): Error: " + e.getMessage() + "," + e.toString());
|
||||
callback.accept(null);
|
||||
}
|
||||
}
|
||||
},
|
||||
new Response.ErrorListener() {
|
||||
@Override
|
||||
public void onErrorResponse(VolleyError error) {
|
||||
mServerConnectionOk = false;
|
||||
if (error != null) {
|
||||
Log.e(TAG, "Create Event Error: " + error.toString() + ", message:" + error.getMessage());
|
||||
} else {
|
||||
Log.e(TAG, "Create Event Error - returned null response");
|
||||
}
|
||||
callback.accept(null);
|
||||
}
|
||||
}) {
|
||||
// Note, this is overriding part of StringRequest, not one of the sub-classes above!
|
||||
@Override
|
||||
protected Map<String, String> getParams() {
|
||||
Map<String, String> params = new HashMap<>();
|
||||
// params.put("name",sname); // passing parameters to server
|
||||
String authToken = getStoredToken();
|
||||
params.put("Authorization: Token " + authToken, authToken);
|
||||
Log.v(TAG, "getParams: params=" + params.toString());
|
||||
//params.put("eventType", String.valueOf(eventType));
|
||||
//params.put("dataTime", dateFormat.format(eventDate));
|
||||
//params.put("desc", eventDesc);
|
||||
return params;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getHeaders() throws AuthFailureError {
|
||||
Map<String, String> params = new HashMap<String, String>();
|
||||
params.put("Content-Type", "application/json; charset=UTF-8");
|
||||
params.put("Authorization", "Token " + getStoredToken());
|
||||
return params;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getBody() throws AuthFailureError {
|
||||
try {
|
||||
return dataStr == null ? null : dataStr.getBytes("utf-8");
|
||||
} catch (UnsupportedEncodingException uee) {
|
||||
VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s", dataStr, "utf-8");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
mQueue.add(req);
|
||||
return (true);
|
||||
}
|
||||
|
||||
|
||||
public boolean createDatapoint(JSONObject dataObj, int eventId, StringCallback callback) {
|
||||
Log.v(TAG, "createDatapoint()");
|
||||
// Create a new event in the remote database, based on the provided parameters.
|
||||
String urlStr = mUrlBase + "/api/datapoints/";
|
||||
Log.v(TAG, "urlStr=" + urlStr);
|
||||
final String authtoken = getStoredToken();
|
||||
|
||||
if (!isLoggedIn()) {
|
||||
Log.v(TAG, "not logged in - doing nothing");
|
||||
return (false);
|
||||
}
|
||||
|
||||
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
try {
|
||||
//jsonObject.put("userId", -1);
|
||||
jsonObject.put("eventId", String.valueOf(eventId));
|
||||
jsonObject.put("dataTime", dataObj.getString("dataTime"));
|
||||
jsonObject.put("dataJSON", dataObj.toString());
|
||||
} catch (JSONException e) {
|
||||
Log.e(TAG, "Error generating event JSON string");
|
||||
}
|
||||
final String dataStr = jsonObject.toString();
|
||||
Log.v(TAG, "createDatapoint - dataStr=" + dataStr);
|
||||
|
||||
|
||||
StringRequest req = new StringRequest(Request.Method.POST, urlStr,
|
||||
new Response.Listener<String>() {
|
||||
@Override
|
||||
public void onResponse(String response) {
|
||||
Log.v(TAG, "Response is: " + response);
|
||||
mServerConnectionOk = true;
|
||||
callback.accept(response);
|
||||
}
|
||||
},
|
||||
new Response.ErrorListener() {
|
||||
@Override
|
||||
public void onErrorResponse(VolleyError error) {
|
||||
mServerConnectionOk = false;
|
||||
if (error != null) {
|
||||
Log.e(TAG, "Create Datapoint Error: " + error.toString() + ", message:" + error.getMessage());
|
||||
callback.accept(null);
|
||||
} else {
|
||||
Log.e(TAG, "Create Datapoint Error - returned null respones");
|
||||
callback.accept(null);
|
||||
}
|
||||
}
|
||||
}) {
|
||||
// Note, this is overriding part of StringRequest, not one of the sub-classes above!
|
||||
@Override
|
||||
protected Map<String, String> getParams() {
|
||||
Map<String, String> params = new HashMap<>();
|
||||
// params.put("name",sname); // passing parameters to server
|
||||
String authToken = getStoredToken();
|
||||
params.put("Authorization: Token " + authToken, authToken);
|
||||
Log.v(TAG, "getParams: params=" + params.toString());
|
||||
return params;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getHeaders() throws AuthFailureError {
|
||||
Map<String, String> params = new HashMap<String, String>();
|
||||
params.put("Content-Type", "application/json; charset=UTF-8");
|
||||
params.put("Authorization", "Token " + getStoredToken());
|
||||
return params;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getBody() throws AuthFailureError {
|
||||
try {
|
||||
return dataStr == null ? null : dataStr.getBytes("utf-8");
|
||||
} catch (UnsupportedEncodingException uee) {
|
||||
VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s", dataStr, "utf-8");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
mQueue.add(req);
|
||||
return (true);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Retieve the user profile of the authenticated user from the server, and return it to the callback function.
|
||||
* @param callback - function to be called with a JSONObject as a parameter that contains the user profile data.
|
||||
* @return true if request sent successfully, or else false.
|
||||
*/
|
||||
public boolean getUserProfile(JSONObjectCallback callback) {
|
||||
Log.v(TAG, "getUserProfile()");
|
||||
String urlStr = mUrlBase + "/api/accounts/profile/";
|
||||
Log.v(TAG, "getUserProfile(): urlStr=" + urlStr);
|
||||
final String authtoken = getStoredToken();
|
||||
|
||||
if (!isLoggedIn()) {
|
||||
Log.v(TAG, "not logged in - doing nothing");
|
||||
return (false);
|
||||
}
|
||||
|
||||
StringRequest req = new StringRequest(Request.Method.GET, urlStr,
|
||||
new Response.Listener<String>() {
|
||||
@Override
|
||||
public void onResponse(String response) {
|
||||
Log.v(TAG, "Response is: " + response);
|
||||
try {
|
||||
JSONObject retObj = new JSONObject(response);
|
||||
callback.accept(retObj);
|
||||
} catch (JSONException e) {
|
||||
Log.e(TAG, "getUserProfile.onRespons(): Error: " + e.getMessage() + "," + e.toString());
|
||||
callback.accept(null);
|
||||
}
|
||||
mServerConnectionOk = true;
|
||||
}
|
||||
},
|
||||
new Response.ErrorListener() {
|
||||
@Override
|
||||
public void onErrorResponse(VolleyError error) {
|
||||
if (error != null) {
|
||||
Log.e(TAG, "Create Event Error: " + error.toString() + ", message:" + error.getMessage());
|
||||
} else {
|
||||
Log.e(TAG, "Create Event Error: returned null response");
|
||||
}
|
||||
mServerConnectionOk = false;
|
||||
callback.accept(null);
|
||||
}
|
||||
}) {
|
||||
|
||||
@Override
|
||||
public Map<String, String> getHeaders() throws AuthFailureError {
|
||||
Map<String, String> params = new HashMap<String, String>();
|
||||
params.put("Content-Type", "application/json; charset=UTF-8");
|
||||
params.put("Authorization", "Token " + getStoredToken());
|
||||
return params;
|
||||
}
|
||||
};
|
||||
mQueue.add(req);
|
||||
return (true);
|
||||
}
|
||||
|
||||
public abstract boolean getEvents(JSONObjectCallback callback);
|
||||
|
||||
public abstract boolean updateEvent(final JSONObject eventObj, JSONObjectCallback callback);
|
||||
|
||||
public abstract boolean createDatapoint(JSONObject dataObj, String eventId, StringCallback callback);
|
||||
|
||||
/**
|
||||
* Retrieve the file containing the standard event types from the server.
|
||||
@@ -595,88 +100,37 @@ public class WebApiConnection {
|
||||
*
|
||||
* @return true if request sent successfully or else false.
|
||||
*/
|
||||
public boolean getEventTypes(JSONObjectCallback callback) {
|
||||
Log.v(TAG, "getEventTypes()");
|
||||
String urlStr = mUrlBase + "/static/eventTypes.json";
|
||||
Log.v(TAG, "urlStr=" + urlStr);
|
||||
final String authtoken = getStoredToken();
|
||||
public abstract boolean getEventTypes(JSONObjectCallback callback);
|
||||
|
||||
if (!isLoggedIn()) {
|
||||
Log.v(TAG, "not logged in - doing nothing");
|
||||
return (false);
|
||||
}
|
||||
|
||||
StringRequest req = new StringRequest(Request.Method.GET, urlStr,
|
||||
new Response.Listener<String>() {
|
||||
@Override
|
||||
public void onResponse(String response) {
|
||||
Log.v(TAG, "getEventTypes.onResponse(): Response is: " + response);
|
||||
mServerConnectionOk = true;
|
||||
try {
|
||||
JSONObject retObj = new JSONObject(response);
|
||||
callback.accept(retObj);
|
||||
} catch (JSONException e) {
|
||||
Log.e(TAG, "getEventTypes.onRespons(): Error: " + e.getMessage() + "," + e.toString());
|
||||
callback.accept(null);
|
||||
}
|
||||
}
|
||||
},
|
||||
new Response.ErrorListener() {
|
||||
@Override
|
||||
public void onErrorResponse(VolleyError error) {
|
||||
mServerConnectionOk = false;
|
||||
if (error != null) {
|
||||
Log.e(TAG, "getEventTypes.onErrorResponse(): " + error.toString() + ", message:" + error.getMessage());
|
||||
} else {
|
||||
Log.e(TAG, "getEventTypes.onErrorResponse() - returned null response");
|
||||
}
|
||||
callback.accept(null);
|
||||
}
|
||||
}) {
|
||||
// Note, this is overriding part of StringRequest, not one of the sub-classes above!
|
||||
@Override
|
||||
public Map<String, String> getHeaders() throws AuthFailureError {
|
||||
Map<String, String> params = new HashMap<String, String>();
|
||||
params.put("Content-Type", "application/json; charset=UTF-8");
|
||||
params.put("Authorization", "Token " + getStoredToken());
|
||||
return params;
|
||||
}
|
||||
};
|
||||
|
||||
mQueue.add(req);
|
||||
return (true);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a trivial file from the server to check we have a good server connection.
|
||||
* sets mServerConnectionOk.
|
||||
* sets mServerConnectionOk.
|
||||
*
|
||||
* @return true if request sent successfully or else false.
|
||||
*/
|
||||
public boolean checkServerConnection() {
|
||||
Log.v(TAG, "checkServerConnection()");
|
||||
String urlStr = mUrlBase + "/static/test.txt";
|
||||
Log.v(TAG, "urlStr=" + urlStr);
|
||||
public abstract boolean checkServerConnection();
|
||||
|
||||
StringRequest req = new StringRequest(Request.Method.GET, urlStr,
|
||||
new Response.Listener<String>() {
|
||||
@Override
|
||||
public void onResponse(String response) {
|
||||
Log.v(TAG, "checkServerConnection.onResponse(): Response is: " + response);
|
||||
mServerConnectionOk = true;
|
||||
}
|
||||
},
|
||||
new Response.ErrorListener() {
|
||||
@Override
|
||||
public void onErrorResponse(VolleyError error) {
|
||||
Log.v(TAG, "checkServerConnection.onErrorResponse");
|
||||
mServerConnectionOk = false;
|
||||
}
|
||||
});
|
||||
public abstract boolean getUserProfile(JSONObjectCallback callback);
|
||||
|
||||
mQueue.add(req);
|
||||
return (true);
|
||||
|
||||
public boolean authenticate(final String uname, final String passwd, StringCallback callback) {
|
||||
Log.e(TAG,"WebApiConnection.authenticate(username, password, callback) Not Implemented");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remove the stored token so future calls are not authenticated.
|
||||
public void logout() {
|
||||
Log.v(TAG, "logout()");
|
||||
setStoredToken(null);
|
||||
}
|
||||
|
||||
protected void setStoredToken(String authToken) {
|
||||
mAuthToken = authToken;
|
||||
}
|
||||
|
||||
protected String getStoredToken() {
|
||||
return (mAuthToken);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,423 @@
|
||||
package uk.org.openseizuredetector;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.android.volley.RequestQueue;
|
||||
import com.android.volley.toolbox.Volley;
|
||||
import com.google.android.gms.tasks.OnCompleteListener;
|
||||
import com.google.android.gms.tasks.OnFailureListener;
|
||||
import com.google.android.gms.tasks.OnSuccessListener;
|
||||
import com.google.android.gms.tasks.Task;
|
||||
import com.google.firebase.auth.FirebaseAuth;
|
||||
import com.google.firebase.firestore.DocumentReference;
|
||||
import com.google.firebase.firestore.DocumentSnapshot;
|
||||
import com.google.firebase.firestore.FirebaseFirestore;
|
||||
import com.google.firebase.firestore.Query;
|
||||
import com.google.firebase.firestore.QueryDocumentSnapshot;
|
||||
import com.google.firebase.firestore.QuerySnapshot;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
// This class is intended to handle all interactions with the OSD WebAPI
|
||||
public class WebApiConnection_firebase extends WebApiConnection {
|
||||
public String retVal;
|
||||
public int retCode;
|
||||
public boolean mServerConnectionOk = false;
|
||||
private String TAG = "WebApiConnection_firebase";
|
||||
private String mAuthToken;
|
||||
private Context mContext;
|
||||
private OsdUtil mUtil;
|
||||
FirebaseFirestore mDb;
|
||||
|
||||
RequestQueue mQueue;
|
||||
|
||||
|
||||
public WebApiConnection_firebase(Context context) {
|
||||
super(context);
|
||||
loginToFirebase();
|
||||
}
|
||||
|
||||
public void loginToFirebase() {
|
||||
// Check if we are already logged in
|
||||
FirebaseAuth auth = FirebaseAuth.getInstance();
|
||||
mDb = FirebaseFirestore.getInstance();
|
||||
if (auth != null) {
|
||||
if (auth.getCurrentUser() != null) {
|
||||
Log.i(TAG, "Firebase Logged in OK -" + auth.getCurrentUser().getDisplayName());
|
||||
} else {
|
||||
Log.e(TAG, "Firebase not logged in - no current user");
|
||||
}
|
||||
} else {
|
||||
Log.e(TAG, "Firebase not logged in");
|
||||
}
|
||||
}
|
||||
|
||||
public void close() {
|
||||
Log.i(TAG, "stop()");
|
||||
mQueue.stop();
|
||||
}
|
||||
|
||||
public boolean isLoggedIn() {
|
||||
FirebaseAuth auth = FirebaseAuth.getInstance();
|
||||
if (auth != null) {
|
||||
if (auth.getCurrentUser() != null) {
|
||||
//Log.v(TAG, "isLoggedIn(): Firebase Logged in OK");
|
||||
return (true);
|
||||
} else {
|
||||
//Log.v(TAG, "isLoggedIn(): Current user is null - Firebase not logged in");
|
||||
return (false);
|
||||
}
|
||||
} else {
|
||||
//Log.v(TAG, "isLoggedIn(): Firebase not logged in");
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean getUserProfile(JSONObjectCallback callback) {
|
||||
Log.v(TAG, "getUserProfile()");
|
||||
FirebaseAuth auth = FirebaseAuth.getInstance();
|
||||
if (!isLoggedIn()) {
|
||||
Log.v(TAG, "not logged in - doing nothing");
|
||||
return (false);
|
||||
} else {
|
||||
try {
|
||||
JSONObject retObj = new JSONObject();
|
||||
retObj.put("id",auth.getCurrentUser().getUid());
|
||||
retObj.put("username", auth.getCurrentUser().getDisplayName());
|
||||
retObj.put("email", auth.getCurrentUser().getEmail());
|
||||
callback.accept(retObj);
|
||||
} catch (JSONException e) {
|
||||
Log.e(TAG, "Error Creating retObjObj: " + e.getMessage());
|
||||
mUtil.showToast("Error Creating retObj - this should not happen!!!");
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
return (true);
|
||||
}
|
||||
|
||||
public String getStoredToken() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setStoredToken(String s) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Create a new event in the remote database, based on the provided parameters.
|
||||
// passes the newly created documentId to function callback on successful completion, or null on error.
|
||||
public boolean createEvent(final int osdAlarmState, final Date eventDate, final String eventDesc, StringCallback callback) {
|
||||
Log.v(TAG, "createEvent()");
|
||||
String userId = null;
|
||||
|
||||
if (mDb == null) {
|
||||
Log.w(TAG, "createEvent() - mDb is null - not doing anything");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (FirebaseAuth.getInstance().getCurrentUser() == null) {
|
||||
Log.e(TAG, "ERROR: createEvent() - not logged in");
|
||||
return false;
|
||||
} else {
|
||||
userId = FirebaseAuth.getInstance().getCurrentUser().getUid();
|
||||
}
|
||||
Map<String, Object> event = new HashMap<>();
|
||||
event.put("dataTime", eventDate.getTime());
|
||||
event.put("osdAlarmState", osdAlarmState);
|
||||
event.put("desc", eventDesc);
|
||||
event.put("type", null);
|
||||
event.put("subType", null);
|
||||
event.put("userId", userId);
|
||||
|
||||
mDb.collection("Events")
|
||||
.add(event)
|
||||
.addOnSuccessListener(new OnSuccessListener<DocumentReference>() {
|
||||
@Override
|
||||
public void onSuccess(DocumentReference documentReference) {
|
||||
Log.d(TAG, "createEvent.onSuccess() - DocumentSnapshot added with ID: " + documentReference.getId());
|
||||
mServerConnectionOk = true;
|
||||
callback.accept(documentReference.getId());
|
||||
}
|
||||
})
|
||||
.addOnFailureListener(new OnFailureListener() {
|
||||
@Override
|
||||
public void onFailure(@NonNull Exception e) {
|
||||
Log.w(TAG, "createEvent.onFailure() - Error adding document", e);
|
||||
callback.accept(null);
|
||||
}
|
||||
});
|
||||
return (true);
|
||||
}
|
||||
|
||||
// calls function callback with a JSONObject representation of the event with id 'eventId'
|
||||
public boolean getEvent(String eventId, JSONObjectCallback callback) {
|
||||
Log.v(TAG, "getEvent()");
|
||||
if (mDb == null) {
|
||||
Log.w(TAG, "getEvent() - mDb is null - not doing anything");
|
||||
return false;
|
||||
}
|
||||
|
||||
DocumentReference docRef = mDb
|
||||
.collection("Events").document(eventId);
|
||||
docRef.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
|
||||
@Override
|
||||
public void onComplete(@NonNull Task<DocumentSnapshot> task) {
|
||||
if (task.isSuccessful()) {
|
||||
DocumentSnapshot document = task.getResult();
|
||||
if (document.exists()) {
|
||||
Log.d(TAG, "getEvent.onComplete(): DocumentSnapshot data: " + document.getData());
|
||||
if (document.getData() == null) {
|
||||
callback.accept(null);
|
||||
} else
|
||||
callback.accept(new JSONObject(document.getData()));
|
||||
} else {
|
||||
Log.d(TAG, "No such document");
|
||||
callback.accept(null);
|
||||
}
|
||||
} else {
|
||||
Log.d(TAG, "get failed with ", task.getException());
|
||||
callback.accept(null);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve all events accessible to the logged in user, and pass them to the callback function as a JSONObject
|
||||
*
|
||||
* @param callback
|
||||
* @return true on success or false on failure to initiate the request.
|
||||
*/
|
||||
public boolean getEvents(JSONObjectCallback callback) {
|
||||
//Long eventId=Long.valueOf(285);
|
||||
Log.v(TAG, "getEvents()");
|
||||
if (mDb == null) {
|
||||
Log.w(TAG, "getEvents() - mDb is null - not doing anything");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isLoggedIn()) {
|
||||
Log.w(TAG, "getEvents() - not logged in - not doing anything");
|
||||
return false;
|
||||
}
|
||||
String userId = FirebaseAuth.getInstance().getCurrentUser().getUid();
|
||||
mDb.collection("Events") //.where("userId", "==", userId)
|
||||
.whereEqualTo("userId", userId)
|
||||
.orderBy("dataTime", Query.Direction.ASCENDING)
|
||||
.get()
|
||||
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
|
||||
@Override
|
||||
public void onComplete(@NonNull Task<QuerySnapshot> task) {
|
||||
if (task.isSuccessful()) {
|
||||
try {
|
||||
JSONObject retObj = new JSONObject();
|
||||
JSONArray eventArray = new JSONArray();
|
||||
Log.d(TAG, "getEvents() - returned " + task.getResult().size());
|
||||
for (QueryDocumentSnapshot document : task.getResult()) {
|
||||
Log.d(TAG, "getEvents() - " + document.getId() + " => " + document.getData());
|
||||
JSONObject eventObj = new JSONObject(document.getData());
|
||||
// Add the event id into the event data because firebase does not include it as part of the document.
|
||||
eventObj.put("id", document.getId());
|
||||
eventArray.put(eventObj);
|
||||
}
|
||||
retObj.put("events", eventArray);
|
||||
callback.accept(retObj);
|
||||
} catch (JSONException e) {
|
||||
Log.e(TAG, "getEvents.onResponse(): Error: " + e.getMessage() + "," + e.toString());
|
||||
callback.accept(null);
|
||||
}
|
||||
|
||||
} else {
|
||||
Log.d(TAG, "Error getting documents: ", task.getException());
|
||||
callback.accept(null);
|
||||
}
|
||||
}
|
||||
});
|
||||
return (true);
|
||||
}
|
||||
|
||||
public boolean updateEvent(final JSONObject eventObj, JSONObjectCallback callback) {
|
||||
String eventId;
|
||||
Log.v(TAG, "updateEvent()");
|
||||
if (mDb == null) {
|
||||
Log.w(TAG, "updateEvent() - mDb is null - not doing anything");
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
eventId = eventObj.getString("id");
|
||||
} catch (JSONException e) {
|
||||
Log.e(TAG, "updateEvent(): Error reading id from eventObj");
|
||||
eventId = null;
|
||||
return false;
|
||||
}
|
||||
final String dataStr = eventObj.toString();
|
||||
Log.v(TAG, "updateEvent - data=" + dataStr);
|
||||
Map<String, Object> eventMap = new HashMap<>();
|
||||
try {
|
||||
eventMap.put("dataTime", eventObj.getLong("dataTime"));
|
||||
eventMap.put("osdAlarmState", eventObj.getInt("osdAlarmState"));
|
||||
eventMap.put("desc", eventObj.getString("desc"));
|
||||
eventMap.put("type", eventObj.getString("type"));
|
||||
eventMap.put("subType", eventObj.getString("subType"));
|
||||
eventMap.put("userId", eventObj.getString("userId"));
|
||||
} catch (JSONException e) {
|
||||
Log.e(TAG, "updateEvent(): Error data from eventObj." + e.toString());
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
Log.v(TAG, "updateEvent - map=" + eventMap.toString());
|
||||
|
||||
try {
|
||||
DocumentReference docRef = mDb.collection("Events").document(eventId);
|
||||
docRef.set(eventMap)
|
||||
.addOnSuccessListener(new OnSuccessListener<Void>() {
|
||||
@Override
|
||||
public void onSuccess(Void aVoid) {
|
||||
JSONObject retObj;
|
||||
try {
|
||||
retObj = new JSONObject("{\"status\":\"OK\"}");
|
||||
} catch (Exception e) {
|
||||
retObj = null;
|
||||
}
|
||||
callback.accept(retObj);
|
||||
}
|
||||
})
|
||||
.addOnFailureListener(new OnFailureListener() {
|
||||
@Override
|
||||
public void onFailure(@NonNull Exception e) {
|
||||
Log.w(TAG, "Error updating document", e);
|
||||
callback.accept(null);
|
||||
}
|
||||
});
|
||||
return (true);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "updateEvent() - ERROR: " + e.toString());
|
||||
e.printStackTrace();
|
||||
}
|
||||
return (false);
|
||||
}
|
||||
|
||||
public boolean createDatapoint(JSONObject dataObj, String eventId, StringCallback callback) {
|
||||
Log.v(TAG, "createDatapoint()");
|
||||
// Create a new event in the remote database, based on the provided parameters.
|
||||
String userId = null;
|
||||
if (FirebaseAuth.getInstance().getCurrentUser() == null) {
|
||||
Log.e(TAG, "ERROR: createDatapoint() - not logged in");
|
||||
return false;
|
||||
} else {
|
||||
userId = FirebaseAuth.getInstance().getCurrentUser().getUid();
|
||||
}
|
||||
String dataTime;
|
||||
try {
|
||||
dataTime = dataObj.getString("dataTime");
|
||||
} catch (JSONException e) {
|
||||
dataTime = "";
|
||||
}
|
||||
Map<String, Object> datapoint = new HashMap<>();
|
||||
datapoint.put("dataTime", dataTime);
|
||||
datapoint.put("dataJSON", dataObj.toString());
|
||||
datapoint.put("userId", userId);
|
||||
datapoint.put("eventId", userId);
|
||||
|
||||
mDb.collection("Datapoints")
|
||||
.add(datapoint)
|
||||
.addOnSuccessListener(new OnSuccessListener<DocumentReference>() {
|
||||
@Override
|
||||
public void onSuccess(DocumentReference documentReference) {
|
||||
Log.d(TAG, "createDatapoint.onSuccess() - DocumentSnapshot added with ID: " + documentReference.getId());
|
||||
mServerConnectionOk = true;
|
||||
callback.accept(documentReference.getId());
|
||||
}
|
||||
})
|
||||
.addOnFailureListener(new OnFailureListener() {
|
||||
@Override
|
||||
public void onFailure(@NonNull Exception e) {
|
||||
Log.w(TAG, "createDatapoint.onFailure() - Error adding document", e);
|
||||
callback.accept(null);
|
||||
}
|
||||
});
|
||||
return (true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve the file containing the standard event types from the server.
|
||||
* Calls the specified callback function, passing a JSONObject as a parameter when the data has been received and parsed.
|
||||
*
|
||||
* @return true if request sent successfully or else false.
|
||||
*/
|
||||
public boolean getEventTypes(JSONObjectCallback callback) {
|
||||
Log.v(TAG, "getEventTypes()");
|
||||
if (mDb == null) {
|
||||
Log.w(TAG, "getEventTypes() - mDb is null - not doing anything");
|
||||
return false;
|
||||
}
|
||||
|
||||
mDb.collection("EventTypes")
|
||||
.get()
|
||||
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
|
||||
@Override
|
||||
public void onComplete(@NonNull Task<QuerySnapshot> task) {
|
||||
if (task.isSuccessful()) {
|
||||
try {
|
||||
JSONObject retObj = new JSONObject();
|
||||
for (QueryDocumentSnapshot document : task.getResult()) {
|
||||
Log.d(TAG, "getEventTypes.onComplete(): " + document.getId() + " => " + document.getData());
|
||||
Log.v(TAG, "getEventTypes.onComplete() - subtypes=" + document.getData().get("subTypes"));
|
||||
JSONArray subTypesArray = listToJSONArray((List) document.getData().get("subTypes"));
|
||||
retObj.put(document.getData().get("type").toString(), subTypesArray);
|
||||
}
|
||||
Log.d(TAG, "getEventTypes.onComplete() - retObj=" + retObj.toString());
|
||||
callback.accept(retObj);
|
||||
} catch (JSONException e) {
|
||||
Log.e(TAG, "getEventTypes.onResponse(): Error: " + e.getMessage() + "," + e.toString());
|
||||
callback.accept(null);
|
||||
}
|
||||
} else {
|
||||
Log.d(TAG, "Error getting documents: ", task.getException());
|
||||
callback.accept(null);
|
||||
}
|
||||
}
|
||||
});
|
||||
return (true);
|
||||
|
||||
}
|
||||
|
||||
private JSONArray listToJSONArray(List<Object> list) {
|
||||
JSONArray arr = new JSONArray();
|
||||
for (Object obj : list) {
|
||||
arr.put(obj);
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a trivial file from the server to check we have a good server connection.
|
||||
* sets mServerConnectionOk.
|
||||
*
|
||||
* @return true if request sent successfully or else false.
|
||||
*/
|
||||
public boolean checkServerConnection() {
|
||||
//FIXME There must be a Firebase function for this?
|
||||
mServerConnectionOk = true;
|
||||
return mServerConnectionOk;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,663 @@
|
||||
package uk.org.openseizuredetector;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.volley.AuthFailureError;
|
||||
import com.android.volley.Request;
|
||||
import com.android.volley.RequestQueue;
|
||||
import com.android.volley.Response;
|
||||
import com.android.volley.VolleyError;
|
||||
import com.android.volley.VolleyLog;
|
||||
import com.android.volley.toolbox.StringRequest;
|
||||
import com.android.volley.toolbox.Volley;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
// This class is intended to handle all interactions with the OSD WebAPI
|
||||
public class WebApiConnection_osdapi extends WebApiConnection {
|
||||
public String retVal;
|
||||
public int retCode;
|
||||
public boolean mServerConnectionOk = false;
|
||||
private String mUrlBase = "https://osdApi.ddns.net";
|
||||
private String TAG = "WebApiConnection_osdapi";
|
||||
RequestQueue mQueue;
|
||||
|
||||
public WebApiConnection_osdapi(Context context) {
|
||||
super(context);
|
||||
mQueue = Volley.newRequestQueue(context);
|
||||
}
|
||||
|
||||
public void close() {
|
||||
super.close();
|
||||
Log.i(TAG,"stop()");
|
||||
mQueue.stop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to authenticate with the web API using user name uname and password passwd. Calls function callback with either
|
||||
* the authentication token on success or null on failure.
|
||||
*
|
||||
* @param uname - user name
|
||||
* @param passwd - password
|
||||
* @param callback - call back function callback(String retVal)
|
||||
* @return true if request sent, or false if failed to send request.
|
||||
*/
|
||||
@Override
|
||||
public boolean authenticate(final String uname, final String passwd, StringCallback callback) {
|
||||
// NOTE: the 'final' keyword is necessary for uname and passwd to be accessible to getParams below - I don't know why!
|
||||
// We know that this command works, so we just need the Java equivalent:
|
||||
// curl -X POST -d 'login=graham4&password=testpwd1' https://osdapi.ddns.net/api/accounts/login/
|
||||
// sending the credentials as a JSONObject postData did not work, so try the method from:
|
||||
// https://protocoderspoint.com/login-and-registration-form-in-android-using-volley-keeping-user-logged-in/#Login_Registration_form_in_android_using_volley_library
|
||||
String urlStr = mUrlBase + "/api/accounts/login/";
|
||||
Log.v(TAG, "urlStr=" + urlStr);
|
||||
|
||||
StringRequest req = new StringRequest(Request.Method.POST, urlStr,
|
||||
new Response.Listener<String>() {
|
||||
@Override
|
||||
public void onResponse(String response) {
|
||||
String tokenStr = null;
|
||||
Log.v(TAG, "Response is: " + response);
|
||||
try {
|
||||
JSONObject jo = new JSONObject(response);
|
||||
tokenStr = jo.getString("token");
|
||||
mServerConnectionOk = true;
|
||||
} catch (JSONException e) {
|
||||
tokenStr = "Error Parsing Rsponse";
|
||||
}
|
||||
setStoredToken(tokenStr);
|
||||
callback.accept(tokenStr);
|
||||
}
|
||||
},
|
||||
new Response.ErrorListener() {
|
||||
@Override
|
||||
public void onErrorResponse(VolleyError error) {
|
||||
if (error != null) {
|
||||
Log.e(TAG, "Login Error: " + error.toString() + ", message:" + error.getMessage());
|
||||
} else {
|
||||
Log.e(TAG, "Login Error: Returned null response");
|
||||
}
|
||||
mServerConnectionOk = false;
|
||||
setStoredToken(null);
|
||||
callback.accept(null);
|
||||
}
|
||||
}) {
|
||||
// Note, this is overriding part of StringRequest, not one of the sub-classes above!
|
||||
@Override
|
||||
protected Map<String, String> getParams() {
|
||||
Map<String, String> params = new HashMap<>();
|
||||
// params.put("name",sname); // passing parameters to server
|
||||
params.put("login", uname);
|
||||
params.put("password", passwd);
|
||||
return params;
|
||||
}
|
||||
};
|
||||
|
||||
mQueue.add(req);
|
||||
return (true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public boolean isLoggedIn() {
|
||||
String authToken = getStoredToken();
|
||||
Log.v(TAG, "isLoggedIn(): token=" + authToken);
|
||||
if (authToken == null || authToken.length() == 0) {
|
||||
Log.v(TAG, "isLogged in - not logged in");
|
||||
return (false);
|
||||
} else {
|
||||
Log.v(TAG,"isLoggedIn - logged in ok");
|
||||
return (true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Create a new event in the remote database, based on the provided parameters.
|
||||
public boolean createEvent(final int osdAlarmState, final Date eventDate, final String eventDesc, StringCallback callback) {
|
||||
Log.v(TAG, "createEvent()");
|
||||
String urlStr = mUrlBase + "/api/events/";
|
||||
Log.v(TAG, "urlStr=" + urlStr);
|
||||
final String authtoken = getStoredToken();
|
||||
|
||||
if (!isLoggedIn()) {
|
||||
Log.v(TAG, "not logged in - doing nothing");
|
||||
return (false);
|
||||
}
|
||||
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
try {
|
||||
jsonObject.put("osdAlarmState", String.valueOf(osdAlarmState));
|
||||
jsonObject.put("dataTime", dateFormat.format(eventDate));
|
||||
jsonObject.put("desc", eventDesc);
|
||||
} catch (JSONException e) {
|
||||
Log.e(TAG, "Error generating event JSON string");
|
||||
}
|
||||
final String dataStr = jsonObject.toString();
|
||||
Log.v(TAG, "createEvent - data=" + dataStr);
|
||||
|
||||
StringRequest req = new StringRequest(Request.Method.POST, urlStr,
|
||||
new Response.Listener<String>() {
|
||||
@Override
|
||||
public void onResponse(String response) {
|
||||
Log.v(TAG, "createEvent.onResponse - Response is: " + response);
|
||||
mServerConnectionOk = true;
|
||||
// we return just the eventId to be consistent with the firebase version of WebApiConnection.
|
||||
String retVal = null;
|
||||
try {
|
||||
JSONObject retObj = new JSONObject(response);
|
||||
retVal = retObj.getString("id");
|
||||
} catch (JSONException e) {
|
||||
Log.e(TAG, "createEvent.onResponse(): Error: " + e.getMessage() + "," + e.toString());
|
||||
retVal = null;
|
||||
}
|
||||
callback.accept(retVal);
|
||||
}
|
||||
},
|
||||
new Response.ErrorListener() {
|
||||
@Override
|
||||
public void onErrorResponse(VolleyError error) {
|
||||
mServerConnectionOk = false;
|
||||
if (error != null) {
|
||||
Log.e(TAG, "createEvent Error: " + error.toString() + ", message:" + error.getMessage());
|
||||
callback.accept(null);
|
||||
} else {
|
||||
Log.e(TAG, "createEvent Error - null response");
|
||||
callback.accept(null);
|
||||
}
|
||||
}
|
||||
}) {
|
||||
// Note, this is overriding part of StringRequest, not one of the sub-classes above!
|
||||
@Override
|
||||
protected Map<String, String> getParams() {
|
||||
Map<String, String> params = new HashMap<>();
|
||||
// params.put("name",sname); // passing parameters to server
|
||||
String authToken = getStoredToken();
|
||||
params.put("Authorization: Token " + authToken, authToken);
|
||||
Log.v(TAG, "getParams: params=" + params.toString());
|
||||
return params;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getHeaders() throws AuthFailureError {
|
||||
Map<String, String> params = new HashMap<String, String>();
|
||||
params.put("Content-Type", "application/json; charset=UTF-8");
|
||||
params.put("Authorization", "Token " + getStoredToken());
|
||||
return params;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getBody() throws AuthFailureError {
|
||||
try {
|
||||
return dataStr == null ? null : dataStr.getBytes("utf-8");
|
||||
} catch (UnsupportedEncodingException uee) {
|
||||
VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s", dataStr, "utf-8");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
mQueue.add(req);
|
||||
return (true);
|
||||
}
|
||||
|
||||
public boolean getEvent(String eventId, JSONObjectCallback callback) {
|
||||
Log.v(TAG, "getEvent()");
|
||||
String urlStr = mUrlBase + "/api/events/" + eventId;
|
||||
Log.v(TAG, "getEvent(): urlStr=" + urlStr);
|
||||
final String authtoken = getStoredToken();
|
||||
|
||||
if (!isLoggedIn()) {
|
||||
Log.v(TAG, "not logged in - doing nothing");
|
||||
return (false);
|
||||
}
|
||||
|
||||
StringRequest req = new StringRequest(Request.Method.GET, urlStr,
|
||||
new Response.Listener<String>() {
|
||||
@Override
|
||||
public void onResponse(String response) {
|
||||
Log.v(TAG, "Response is: " + response);
|
||||
try {
|
||||
JSONObject retObj = new JSONObject(response);
|
||||
retObj.put("alarmStateStr", mUtil.alarmStatusToString(retObj.getInt("osdAlarmState")));
|
||||
callback.accept(retObj);
|
||||
} catch (JSONException e) {
|
||||
Log.e(TAG, "getEventTypes.onRespons(): Error: " + e.getMessage() + "," + e.toString());
|
||||
callback.accept(null);
|
||||
}
|
||||
mServerConnectionOk = true;
|
||||
}
|
||||
},
|
||||
new Response.ErrorListener() {
|
||||
@Override
|
||||
public void onErrorResponse(VolleyError error) {
|
||||
if (error != null) {
|
||||
Log.e(TAG, "Create Event Error: " + error.toString() + ", message:" + error.getMessage());
|
||||
} else {
|
||||
Log.e(TAG, "Create Event Error: returned null response");
|
||||
}
|
||||
mServerConnectionOk = false;
|
||||
callback.accept(null);
|
||||
}
|
||||
}) {
|
||||
|
||||
@Override
|
||||
public Map<String, String> getHeaders() throws AuthFailureError {
|
||||
Map<String, String> params = new HashMap<String, String>();
|
||||
params.put("Content-Type", "application/json; charset=UTF-8");
|
||||
params.put("Authorization", "Token " + getStoredToken());
|
||||
return params;
|
||||
}
|
||||
};
|
||||
mQueue.add(req);
|
||||
return (true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve all events accessible to the logged in user, and pass them to the callback function as a JSONObject
|
||||
*
|
||||
* @param callback
|
||||
* @return true on success or false on failure to initiate the request.
|
||||
*/
|
||||
public boolean getEvents(JSONObjectCallback callback) {
|
||||
Log.v(TAG, "getEvents()");
|
||||
String urlStr = mUrlBase + "/api/events/";
|
||||
Log.v(TAG, "getEvents(): urlStr=" + urlStr);
|
||||
final String authtoken = getStoredToken();
|
||||
|
||||
if (!isLoggedIn()) {
|
||||
Log.v(TAG, "not logged in - doing nothing");
|
||||
return (false);
|
||||
}
|
||||
|
||||
StringRequest req = new StringRequest(Request.Method.GET, urlStr,
|
||||
new Response.Listener<String>() {
|
||||
@Override
|
||||
public void onResponse(String response) {
|
||||
Log.v(TAG, "Response is: " + response);
|
||||
mServerConnectionOk = true;
|
||||
try {
|
||||
JSONObject retObj = new JSONObject();
|
||||
JSONArray eventArray = new JSONArray(response);
|
||||
retObj.put("events", eventArray);
|
||||
callback.accept(retObj);
|
||||
} catch (JSONException e) {
|
||||
Log.e(TAG, "getEventTypes.onRespons(): Error: " + e.getMessage() + "," + e.toString());
|
||||
callback.accept(null);
|
||||
}
|
||||
}
|
||||
},
|
||||
new Response.ErrorListener() {
|
||||
@Override
|
||||
public void onErrorResponse(VolleyError error) {
|
||||
//if ((error != null) && (error.networkResponse != null) && (error.networkResponse.data != null)) {#
|
||||
mServerConnectionOk = false;
|
||||
if (error != null) {
|
||||
if (error.networkResponse != null) {
|
||||
Log.e(TAG, "getEvents(): Error: " + error.toString() + ", message:" + error.getMessage());
|
||||
} else {
|
||||
Log.e(TAG, "getEvents(): Error: - request returned null networkResponse");
|
||||
}
|
||||
} else{
|
||||
Log.e(TAG, "getEvents(): Error: - request returned null response");
|
||||
}
|
||||
callback.accept(null);
|
||||
}
|
||||
}) {
|
||||
|
||||
@Override
|
||||
public Map<String, String> getHeaders() throws AuthFailureError {
|
||||
Map<String, String> params = new HashMap<String, String>();
|
||||
params.put("Content-Type", "application/json; charset=UTF-8");
|
||||
params.put("Authorization", "Token " + getStoredToken());
|
||||
return params;
|
||||
}
|
||||
};
|
||||
mQueue.add(req);
|
||||
return (true);
|
||||
}
|
||||
|
||||
|
||||
public boolean updateEvent(final JSONObject eventObj, JSONObjectCallback callback) {
|
||||
String eventId;
|
||||
Log.v(TAG, "updateEvent()");
|
||||
final String authtoken = getStoredToken();
|
||||
|
||||
if (!isLoggedIn()) {
|
||||
Log.v(TAG, "not logged in - doing nothing");
|
||||
return (false);
|
||||
}
|
||||
try {
|
||||
eventId = eventObj.getString("id");
|
||||
} catch (JSONException e) {
|
||||
Log.e(TAG, "updateEvent(): Error reading id from eventObj");
|
||||
eventId = null;
|
||||
}
|
||||
final String dataStr = eventObj.toString();
|
||||
Log.v(TAG, "updateEvent - data=" + dataStr);
|
||||
|
||||
int reqMethod;
|
||||
String urlStr;
|
||||
if (eventId != null) {
|
||||
Log.v(TAG, "updateEvent() - found eventId " + eventId + ", Updating event record");
|
||||
urlStr = mUrlBase + "/api/events/" + eventId + "/";
|
||||
Log.v(TAG, "urlStr=" + urlStr);
|
||||
reqMethod = Request.Method.PUT;
|
||||
} else {
|
||||
Log.v(TAG, "updateEvent() - eventId not found - creating new event record");
|
||||
urlStr = mUrlBase + "/api/events/";
|
||||
Log.v(TAG, "urlStr=" + urlStr);
|
||||
reqMethod = Request.Method.POST;
|
||||
}
|
||||
|
||||
StringRequest req = new StringRequest(reqMethod, urlStr,
|
||||
new Response.Listener<String>() {
|
||||
@Override
|
||||
public void onResponse(String response) {
|
||||
Log.v(TAG, "Response is: " + response);
|
||||
mServerConnectionOk = true;
|
||||
try {
|
||||
JSONObject retObj = new JSONObject(response);
|
||||
callback.accept(retObj);
|
||||
} catch (JSONException e) {
|
||||
Log.e(TAG, "getEventTypes.onRespons(): Error: " + e.getMessage() + "," + e.toString());
|
||||
callback.accept(null);
|
||||
}
|
||||
}
|
||||
},
|
||||
new Response.ErrorListener() {
|
||||
@Override
|
||||
public void onErrorResponse(VolleyError error) {
|
||||
mServerConnectionOk = false;
|
||||
if (error != null) {
|
||||
Log.e(TAG, "Create Event Error: " + error.toString() + ", message:" + error.getMessage());
|
||||
} else {
|
||||
Log.e(TAG, "Create Event Error - returned null response");
|
||||
}
|
||||
callback.accept(null);
|
||||
}
|
||||
}) {
|
||||
// Note, this is overriding part of StringRequest, not one of the sub-classes above!
|
||||
@Override
|
||||
protected Map<String, String> getParams() {
|
||||
Map<String, String> params = new HashMap<>();
|
||||
// params.put("name",sname); // passing parameters to server
|
||||
String authToken = getStoredToken();
|
||||
params.put("Authorization: Token " + authToken, authToken);
|
||||
Log.v(TAG, "getParams: params=" + params.toString());
|
||||
//params.put("eventType", String.valueOf(eventType));
|
||||
//params.put("dataTime", dateFormat.format(eventDate));
|
||||
//params.put("desc", eventDesc);
|
||||
return params;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getHeaders() throws AuthFailureError {
|
||||
Map<String, String> params = new HashMap<String, String>();
|
||||
params.put("Content-Type", "application/json; charset=UTF-8");
|
||||
params.put("Authorization", "Token " + getStoredToken());
|
||||
return params;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getBody() throws AuthFailureError {
|
||||
try {
|
||||
return dataStr == null ? null : dataStr.getBytes("utf-8");
|
||||
} catch (UnsupportedEncodingException uee) {
|
||||
VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s", dataStr, "utf-8");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
mQueue.add(req);
|
||||
return (true);
|
||||
}
|
||||
|
||||
|
||||
public boolean createDatapoint(JSONObject dataObj, String eventId, StringCallback callback) {
|
||||
Log.v(TAG, "createDatapoint()");
|
||||
// Create a new event in the remote database, based on the provided parameters.
|
||||
String urlStr = mUrlBase + "/api/datapoints/";
|
||||
Log.v(TAG, "urlStr=" + urlStr);
|
||||
final String authtoken = getStoredToken();
|
||||
|
||||
if (!isLoggedIn()) {
|
||||
Log.v(TAG, "not logged in - doing nothing");
|
||||
return (false);
|
||||
}
|
||||
|
||||
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
try {
|
||||
//jsonObject.put("userId", -1);
|
||||
jsonObject.put("eventId", String.valueOf(eventId));
|
||||
jsonObject.put("dataTime", dataObj.getString("dataTime"));
|
||||
jsonObject.put("dataJSON", dataObj.toString());
|
||||
} catch (JSONException e) {
|
||||
Log.e(TAG, "Error generating event JSON string");
|
||||
}
|
||||
final String dataStr = jsonObject.toString();
|
||||
Log.v(TAG, "createDatapoint - dataStr=" + dataStr);
|
||||
|
||||
|
||||
StringRequest req = new StringRequest(Request.Method.POST, urlStr,
|
||||
new Response.Listener<String>() {
|
||||
@Override
|
||||
public void onResponse(String response) {
|
||||
Log.v(TAG, "Response is: " + response);
|
||||
mServerConnectionOk = true;
|
||||
callback.accept(response);
|
||||
}
|
||||
},
|
||||
new Response.ErrorListener() {
|
||||
@Override
|
||||
public void onErrorResponse(VolleyError error) {
|
||||
mServerConnectionOk = false;
|
||||
if (error != null) {
|
||||
Log.e(TAG, "Create Datapoint Error: " + error.toString() + ", message:" + error.getMessage());
|
||||
callback.accept(null);
|
||||
} else {
|
||||
Log.e(TAG, "Create Datapoint Error - returned null respones");
|
||||
callback.accept(null);
|
||||
}
|
||||
}
|
||||
}) {
|
||||
// Note, this is overriding part of StringRequest, not one of the sub-classes above!
|
||||
@Override
|
||||
protected Map<String, String> getParams() {
|
||||
Map<String, String> params = new HashMap<>();
|
||||
// params.put("name",sname); // passing parameters to server
|
||||
String authToken = getStoredToken();
|
||||
params.put("Authorization: Token " + authToken, authToken);
|
||||
Log.v(TAG, "getParams: params=" + params.toString());
|
||||
return params;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getHeaders() throws AuthFailureError {
|
||||
Map<String, String> params = new HashMap<String, String>();
|
||||
params.put("Content-Type", "application/json; charset=UTF-8");
|
||||
params.put("Authorization", "Token " + getStoredToken());
|
||||
return params;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getBody() throws AuthFailureError {
|
||||
try {
|
||||
return dataStr == null ? null : dataStr.getBytes("utf-8");
|
||||
} catch (UnsupportedEncodingException uee) {
|
||||
VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s", dataStr, "utf-8");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
mQueue.add(req);
|
||||
return (true);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Retieve the user profile of the authenticated user from the server, and return it to the callback function.
|
||||
* @param callback - function to be called with a JSONObject as a parameter that contains the user profile data.
|
||||
* @return true if request sent successfully, or else false.
|
||||
*/
|
||||
public boolean getUserProfile(JSONObjectCallback callback) {
|
||||
Log.v(TAG, "getUserProfile()");
|
||||
String urlStr = mUrlBase + "/api/accounts/profile/";
|
||||
Log.v(TAG, "getUserProfile(): urlStr=" + urlStr);
|
||||
final String authtoken = getStoredToken();
|
||||
|
||||
if (!isLoggedIn()) {
|
||||
Log.v(TAG, "not logged in - doing nothing");
|
||||
return (false);
|
||||
}
|
||||
|
||||
StringRequest req = new StringRequest(Request.Method.GET, urlStr,
|
||||
new Response.Listener<String>() {
|
||||
@Override
|
||||
public void onResponse(String response) {
|
||||
Log.v(TAG, "Response is: " + response);
|
||||
try {
|
||||
JSONObject retObj = new JSONObject(response);
|
||||
callback.accept(retObj);
|
||||
} catch (JSONException e) {
|
||||
Log.e(TAG, "getUserProfile.onResponse(): Error: " + e.getMessage() + "," + e.toString());
|
||||
callback.accept(null);
|
||||
}
|
||||
mServerConnectionOk = true;
|
||||
}
|
||||
},
|
||||
new Response.ErrorListener() {
|
||||
@Override
|
||||
public void onErrorResponse(VolleyError error) {
|
||||
if (error != null) {
|
||||
Log.e(TAG, "Create Event Error: " + error.toString() + ", message:" + error.getMessage());
|
||||
} else {
|
||||
Log.e(TAG, "Create Event Error: returned null response");
|
||||
}
|
||||
mServerConnectionOk = false;
|
||||
callback.accept(null);
|
||||
}
|
||||
}) {
|
||||
|
||||
@Override
|
||||
public Map<String, String> getHeaders() throws AuthFailureError {
|
||||
Map<String, String> params = new HashMap<String, String>();
|
||||
params.put("Content-Type", "application/json; charset=UTF-8");
|
||||
params.put("Authorization", "Token " + getStoredToken());
|
||||
return params;
|
||||
}
|
||||
};
|
||||
mQueue.add(req);
|
||||
return (true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve the file containing the standard event types from the server.
|
||||
* Calls the specified callback function, passing a JSONObject as a parameter when the data has been received and parsed.
|
||||
*
|
||||
* @return true if request sent successfully or else false.
|
||||
*/
|
||||
public boolean getEventTypes(JSONObjectCallback callback) {
|
||||
Log.v(TAG, "getEventTypes()");
|
||||
String urlStr = mUrlBase + "/static/eventTypes.json";
|
||||
Log.v(TAG, "urlStr=" + urlStr);
|
||||
final String authtoken = getStoredToken();
|
||||
|
||||
if (!isLoggedIn()) {
|
||||
Log.v(TAG, "not logged in - doing nothing");
|
||||
return (false);
|
||||
}
|
||||
|
||||
StringRequest req = new StringRequest(Request.Method.GET, urlStr,
|
||||
new Response.Listener<String>() {
|
||||
@Override
|
||||
public void onResponse(String response) {
|
||||
Log.v(TAG, "getEventTypes.onResponse(): Response is: " + response);
|
||||
mServerConnectionOk = true;
|
||||
try {
|
||||
JSONObject retObj = new JSONObject(response);
|
||||
callback.accept(retObj);
|
||||
} catch (JSONException e) {
|
||||
Log.e(TAG, "getEventTypes.onRespons(): Error: " + e.getMessage() + "," + e.toString());
|
||||
callback.accept(null);
|
||||
}
|
||||
}
|
||||
},
|
||||
new Response.ErrorListener() {
|
||||
@Override
|
||||
public void onErrorResponse(VolleyError error) {
|
||||
mServerConnectionOk = false;
|
||||
if (error != null) {
|
||||
Log.e(TAG, "getEventTypes.onErrorResponse(): " + error.toString() + ", message:" + error.getMessage());
|
||||
} else {
|
||||
Log.e(TAG, "getEventTypes.onErrorResponse() - returned null response");
|
||||
}
|
||||
callback.accept(null);
|
||||
}
|
||||
}) {
|
||||
// Note, this is overriding part of StringRequest, not one of the sub-classes above!
|
||||
@Override
|
||||
public Map<String, String> getHeaders() throws AuthFailureError {
|
||||
Map<String, String> params = new HashMap<String, String>();
|
||||
params.put("Content-Type", "application/json; charset=UTF-8");
|
||||
params.put("Authorization", "Token " + getStoredToken());
|
||||
return params;
|
||||
}
|
||||
};
|
||||
|
||||
mQueue.add(req);
|
||||
return (true);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a trivial file from the server to check we have a good server connection.
|
||||
* sets mServerConnectionOk.
|
||||
* @return true if request sent successfully or else false.
|
||||
*/
|
||||
public boolean checkServerConnection() {
|
||||
Log.v(TAG, "checkServerConnection()");
|
||||
String urlStr = mUrlBase + "/static/test.txt";
|
||||
Log.v(TAG, "urlStr=" + urlStr);
|
||||
|
||||
StringRequest req = new StringRequest(Request.Method.GET, urlStr,
|
||||
new Response.Listener<String>() {
|
||||
@Override
|
||||
public void onResponse(String response) {
|
||||
Log.v(TAG, "checkServerConnection.onResponse(): Response is: " + response);
|
||||
mServerConnectionOk = true;
|
||||
}
|
||||
},
|
||||
new Response.ErrorListener() {
|
||||
@Override
|
||||
public void onErrorResponse(VolleyError error) {
|
||||
Log.v(TAG, "checkServerConnection.onErrorResponse");
|
||||
mServerConnectionOk = false;
|
||||
}
|
||||
});
|
||||
|
||||
mQueue.add(req);
|
||||
return (true);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -31,6 +31,36 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<Button
|
||||
android:id="@+id/cancelBtn"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/back" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/loginBtn"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/authenticate" />
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/login_osdapi_ui"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/username"
|
||||
android:layout_width="match_parent"
|
||||
@@ -53,30 +83,12 @@
|
||||
android:hint="password"
|
||||
android:inputType="textPassword" />
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<Button
|
||||
android:id="@+id/cancelBtn"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/back" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/OKBtn"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/authenticate" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
android:orientation="horizontal"
|
||||
>
|
||||
|
||||
<Button
|
||||
android:id="@+id/RegisterBtn"
|
||||
@@ -94,6 +106,8 @@
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/logout_ui"
|
||||
android:layout_width="fill_parent"
|
||||
@@ -117,8 +131,14 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:text="userId" />
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
@@ -139,12 +159,6 @@
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!--<TextView
|
||||
android:id="@+id/tokenTv"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/logged_in_with_token" />
|
||||
-->
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
@@ -164,40 +178,29 @@
|
||||
android:layout_weight="1"
|
||||
android:text="@string/logout" />
|
||||
</LinearLayout>
|
||||
<!--
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
</LinearLayout>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<Button
|
||||
android:id="@+id/aboutDataSharingBtn"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
android:layout_weight="1"
|
||||
android:text="@string/about_data_sharing" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/createEventBtn"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="Create Event" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/createDatapointBtn"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="Prune Database" />
|
||||
</LinearLayout>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
<Button
|
||||
android:id="@+id/privacyPolicyBtn"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<Button
|
||||
android:id="@+id/getLocalEventsBtn"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="getLocalEvents" />
|
||||
|
||||
</LinearLayout>
|
||||
-->
|
||||
android:layout_weight="1"
|
||||
android:text="@string/privacy_policy" />
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
@@ -17,7 +17,7 @@
|
||||
android:text="@string/cancel" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/OKBtn"
|
||||
android:id="@+id/loginBtn"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
|
||||
@@ -96,7 +96,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
<Button
|
||||
android:id="@+id/OKBtn"
|
||||
android:id="@+id/loginBtn"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/okBtnTxt" />
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
android:orientation="vertical" android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<LinearLayout
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
<TextView
|
||||
|
||||
@@ -5,71 +5,67 @@
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
<TextView
|
||||
android:id="@+id/event_id_remote_tv"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginRight="10dp"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge" />
|
||||
android:text="eventId" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/event_date_remote_tv"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textStyle="bold"
|
||||
android:text="date" />
|
||||
<TextView
|
||||
android:id="@+id/event_date_remote_tv"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="date"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
<LinearLayout
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/event_type_remote_tv"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textStyle="bold"
|
||||
android:text="---" />
|
||||
<TextView
|
||||
android:id="@+id/event_type_remote_tv"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="---"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text=" : " />
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text=" : " />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/event_subtype_remote_tv"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="---" />
|
||||
<TextView
|
||||
android:id="@+id/event_subtype_remote_tv"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="---" />
|
||||
|
||||
</LinearLayout>
|
||||
<TextView
|
||||
android:id="@+id/event_alarmState_remote_tv"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="alarm" />
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="notes"
|
||||
android:textStyle="italic"
|
||||
android:id="@+id/event_notes_remote_tv" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- <TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="dataJSON"
|
||||
android:id="@+id/event_dataJSON" />
|
||||
-->
|
||||
<TextView
|
||||
android:id="@+id/event_alarmState_remote_tv"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="alarm" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/event_notes_remote_tv"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="notes"
|
||||
android:textStyle="italic" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/event_id_remote_tv"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginRight="10dp"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall" />
|
||||
android:text="eventId" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
@@ -3,6 +3,8 @@
|
||||
<string name="app_name">OpenSeizureDetector</string>
|
||||
<string name="changelog">
|
||||
"\n
|
||||
\nV4.1.1 - Changed remote database to be compatible with either OSD webAPI or future Firebase database.<br/>
|
||||
- Performance improvement by having separate events and datapoints tables in local database
|
||||
\nV4.0.1 - fixed crash in Report Seizure function
|
||||
\nV4.0.0
|
||||
- Introduced the <b>Data Sharing</b> feature to allow users to share their seizure and false alarm data
|
||||
@@ -370,7 +372,7 @@
|
||||
<string name="check_seizures_message">Please select the events highlighted in pink to say if they are real seizures or false alarms</string>
|
||||
<string name="error_server_not_running">ERROR: OpenSeizureDetector Server is not running - please re-start it</string>
|
||||
<string name="system_logs">System Logs</string>
|
||||
<string name="logged_in_as_user_id">Logged in as User Id:</string>
|
||||
<string name="logged_in_as_user_id">Logged in as: </string>
|
||||
<string name="datasharing_notification_text">Select for more information</string>
|
||||
<string name="datasharing_notification_title">OpenSeizureDetector Data Sharing Problem</string>
|
||||
<string name="datasharing_about_title">OpenSeizureDetector Data Sharing</string>
|
||||
@@ -430,4 +432,6 @@
|
||||
and selecting <b>Apps->OpenSeizureDetector->Permissions</b>.
|
||||
</string>
|
||||
<string name="permissions_required">Permissions Disclosure</string>
|
||||
<string name="about_data_sharing">About Data Sharing</string>
|
||||
<string name="privacy_policy">Privacy Policy</string>
|
||||
</resources>
|
||||
|
||||
@@ -15,20 +15,14 @@ import java.util.TimeZone;
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(sdk = {Build.VERSION_CODES.O_MR1}, packageName = "uk.org.openseizuredetector")
|
||||
public class LogManagerTest extends TestCase {
|
||||
LogManager mLm;
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles"));
|
||||
mLm = new LogManager(RuntimeEnvironment.systemContext);
|
||||
}
|
||||
|
||||
|
||||
public void tearDown() throws Exception {
|
||||
mLm.close();
|
||||
|
||||
}
|
||||
|
||||
SdData getFakeSdData() {
|
||||
SdData sdData = new SdData();
|
||||
return sdData;
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
package uk.org.openseizuredetector;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
|
||||
import com.google.firebase.FirebaseApp;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class WebApiConnectionTest {
|
||||
WebApiConnection mWac;
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
Context context = ApplicationProvider.getApplicationContext();
|
||||
FirebaseApp.initializeApp(context);
|
||||
mWac = new WebApiConnection(context);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isLoggedIn() {
|
||||
assertTrue(mWac.isLoggedIn());
|
||||
assertFalse(mWac.isLoggedIn());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createEvent() {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getEvent() {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getEvents() {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateEvent() {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createDatapoint() {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getUserProfile() {
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user