From 511539f9bd8c1fd808e4d08f7e1c1aa54efa6289 Mon Sep 17 00:00:00 2001 From: Gurtok Date: Mon, 16 Jan 2017 17:01:09 -0700 Subject: [PATCH 01/42] maybe not broken --- .../ca/dungeons/sensordump/MainActivity.java | 239 ++++++++++-------- .../src/main/res/layout/activity_main.xml | 229 +++++++++++++---- .../src/main/res/values/strings.xml | 5 + .../src/main/res/xml/preferences.xml | 17 +- 4 files changed, 325 insertions(+), 165 deletions(-) diff --git a/ElasticSensorDump/src/main/java/ca/dungeons/sensordump/MainActivity.java b/ElasticSensorDump/src/main/java/ca/dungeons/sensordump/MainActivity.java index 4514dd7..b170c5a 100644 --- a/ElasticSensorDump/src/main/java/ca/dungeons/sensordump/MainActivity.java +++ b/ElasticSensorDump/src/main/java/ca/dungeons/sensordump/MainActivity.java @@ -28,8 +28,10 @@ import android.widget.ImageButton; import android.widget.SeekBar; import android.widget.TextView; +import android.widget.ToggleButton; import org.json.JSONObject; +import org.w3c.dom.Text; import java.text.SimpleDateFormat; import java.util.Date; @@ -79,56 +81,9 @@ protected void onCreate(final Bundle savedInstanceState) { setContentView(R.layout.activity_main); // Prevent screen from going into landscape setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED); - - // Callback for settings screen - final Intent settingsIntent = new Intent(this, SettingsActivity.class); sharedPrefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext()); - - // check for gps access, also set up some button controls - CheckGPS(); - // Click a button, get some sensor data - final Button btnStart = (Button) findViewById(R.id.btnStart); - btnStart.setOnClickListener(new View.OnClickListener() { - public void onClick(View v) { - if (!logging) { - btnStart.setText(getString(R.string.buttonStop)); - startLogging(); - logging = true; - } else { - btnStart.setText(getString(R.string.buttonStart)); - stopLogging(); - logging = false; - } - } - }); - - // Click a button, get the settings screen - final ImageButton ibSetup = (ImageButton) findViewById(R.id.ibSetup); - ibSetup.setOnClickListener(new View.OnClickListener() { - public void onClick(View v) { - startActivity(settingsIntent); - } - }); - - // Slide a bar to adjust the refresh times - final SeekBar seekBar = (SeekBar) findViewById(R.id.seekBar); - final TextView tvSeekBarText = (TextView) findViewById(R.id.TickText); - tvSeekBarText.setText(getString(R.string.Collection_Interval) + " " + seekBar.getProgress() + getString(R.string.milliseconds)); - seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { - @Override - public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - if (fromUser) { - if(progress < MIN_SENSOR_REFRESH) progress = MIN_SENSOR_REFRESH; - tvSeekBarText.setText(getString(R.string.Collection_Interval) + " " + progress + getString(R.string.milliseconds)); - sensorRefreshTime = progress; - } - } - @Override - public void onStartTrackingTouch(SeekBar seekBar){ } //intentionally blank - @Override - public void onStopTrackingTouch(SeekBar seekBar) { } //intentionally blank - }); - + // main activity buttons + buildButtonLogic(); // Get a list of all available sensors on the device and store in array mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); List deviceSensors = mSensorManager.getSensorList(Sensor.TYPE_ALL); @@ -136,10 +91,8 @@ public void onStopTrackingTouch(SeekBar seekBar) { } //intentionally blank for (int i = 0; i < deviceSensors.size(); i++) { usableSensors[i] = deviceSensors.get(i).getType(); } - IntentFilter batteryFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); registerReceiver(batteryReceiver, batteryFilter); - } @Override @@ -208,14 +161,12 @@ public final void onSensorChanged(SensorEvent event) { joSensorData.put(sensorName, sensorValue); } } - // Make sure we only generate docs at an adjustable rate // We'll use 250ms for now if (System.currentTimeMillis() > lastUpdate + sensorRefreshTime) { updateScreen(); lastUpdate = System.currentTimeMillis(); esIndexer.index(joSensorData); - } } catch (Exception e) { Log.v("JSON Logging error", e.toString()); @@ -245,50 +196,140 @@ private void stopLogging() { // Disable wakelock if logging has stopped getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); - logging = false; unregisterReceiver(batteryReceiver); - tvProgress = (TextView) findViewById(R.id.tvProgress); - tvProgress.setText( getString(R.string.loggingStopped) ); mSensorManager.unregisterListener(this); - - // Disable GPS if we allowed it. - if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { - try { - locationManager.removeUpdates(gpsLogger); - gpsOFF(); - } catch (Exception e) { - Log.v("GPS Error", "GPS could not unbind"); - } - } + gpsOFF(); + logging = false; } // Update the display with readings/written/errors private void updateScreen() { - - String updateText = getString(R.string.Sensor_Readings) + esIndexer.indexRequests + "\n" + - getString(R.string.Documents_Written) + esIndexer.indexSuccess + "\n" + - getString(R.string.GPS_Updates) + gpsLogger.gpsUpdates + "\n" + - getString(R.string.Errors) + esIndexer.failedIndex + "\n" + - "Batter sensor" + batteryLevel; - tvProgress = (TextView) findViewById(R.id.tvProgress); - tvProgress.setText(updateText); + // need to update UI based on the passed data intent + // + TextView mainBanner = (TextView) findViewById(R.id.main_Banner); + TextView sensorTV = (TextView) findViewById(R.id.sensor_tv); + TextView documentsTV = (TextView) findViewById(R.id.documents_tv); + TextView gpsTV = (TextView) findViewById(R.id.gps_TV); + TextView errorsTV = (TextView) findViewById(R.id.errors_TV); + // update each metric + sensorTV.setText( (""+ esIndexer.indexRequests) ); + documentsTV.setText( (""+ esIndexer.indexSuccess) ); + gpsTV.setText( (""+ gpsLogger.gpsUpdates) ); + errorsTV.setText( (""+ esIndexer.failedIndex) ); + if(logging) + mainBanner.setText(getString(R.string.logging)); + else + mainBanner.setText(getString(R.string.loggingStopped)); } - // Catch the permissions request for GPS being successful, and light up the GPS for this session - @Override - public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) { - switch (requestCode) { - case 1: { - if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { - if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { - locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); - locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, gpsLogger); + void buildButtonLogic() { + // Click a button, get some sensor data + final Button btnStart = (Button) findViewById(R.id.btnStart); + btnStart.setOnClickListener(new View.OnClickListener() { + public void onClick(View v) { + if (!logging) { + btnStart.setText(getString(R.string.buttonStop)); + startLogging(); + logging = true; + } else { + btnStart.setText(getString(R.string.buttonStart)); + stopLogging(); + logging = false; + } + } + }); + + // Click a button, get the settings screen + final ImageButton ibSetup = (ImageButton) findViewById(R.id.ibSetup); + ibSetup.setOnClickListener(new View.OnClickListener() { + public void onClick(View v) { + // Callback for settings screen + final Intent settingsIntent = new Intent(getBaseContext(), SettingsActivity.class); + startActivity(settingsIntent); + } + }); + + // Slide a bar to adjust the refresh times + final SeekBar seekBar = (SeekBar) findViewById(R.id.seekBar); + final TextView tvSeekBarText = (TextView) findViewById(R.id.TickText); + tvSeekBarText.setText(getString(R.string.Collection_Interval) + " " + seekBar.getProgress() * 10 + getString(R.string.milliseconds)); + seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + if (fromUser) { + if (progress < MIN_SENSOR_REFRESH) progress = MIN_SENSOR_REFRESH; + tvSeekBarText.setText(getString(R.string.Collection_Interval) + " " + progress * 10 + getString(R.string.milliseconds)); + sensorRefreshTime = progress * 10; + } + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + } //intentionally blank + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + } //intentionally blank + }); + + // GPS Toggle + // + final ToggleButton toggleButton = (ToggleButton) findViewById(R.id.GPS_Toggle); + toggleButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + // if the toggle button changed to ON do... + if (isChecked) { + gpsOn(); + // if the toggle button is changed to OFF do... + } else { + // if we have gps access turn off receivers + if( gpsPermission() ) { + try { + gpsOFF(); + // update sharedPrefs : gpsBool to FALSE + GpsToPrefs("GPS_Permission", false); + // update sharedPrefs : gpsChoosen to TRUE + GpsToPrefs("GPS_ASKEDforPermission", true); + } catch (Exception e) { + Log.v("GPS_TOGGLE_PROBLEM", "GPS_TOGGLE_PROBLEM"); + } } } + } + + }); + // end build button logic + } + // write the result of asking for GPS access + void GpsToPrefs(String asked, boolean permission) { + SharedPreferences.Editor sharedPref_Editor = sharedPrefs.edit(); + sharedPref_Editor.putBoolean(asked, permission); + sharedPref_Editor.apply(); + } + // true = we have asked for permission, and it was granted + boolean gpsPermission() { + gpsChoosen = sharedPrefs.getBoolean("GPS_ASKEDforPermission", false); + if( !gpsChoosen ) { + requestGpsPermission(); + return sharedPrefs.getBoolean("GPS_Permission", false); } + return sharedPrefs.getBoolean("GPS_Permission", false); } + // ask user to grant gps access & write result to sharedPrefs + void requestGpsPermission(){ + try{ + Log.v("CHECK DPS", "Check GPS FAIL"); + ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1); + gpsBool = ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED; + GpsToPrefs("GPS_Permission", gpsBool); + GpsToPrefs("GPS_ASKEDforPermission", true); + }catch( SecurityException e) { + Log.v("CHECK DPS", "Check GPS FAIL"); + } + } // unbind GPS listener, should stop GPS thread in 2.0 public void gpsOFF(){ //unbind GPS listener if permission was granted @@ -297,35 +338,23 @@ public void gpsOFF(){ locationManager.removeUpdates(gpsLogger); else if(ContextCompat.checkSelfPermission(this, android.Manifest.permission. ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_DENIED) - { Log.v("GPS Denied", "GPS Denied"); - }//intentionally blank, if permission is denied initially, gps was not on + //intentionally blank, if permission is denied initially, gps was not on else //anything else Log.v("GPS Error", "GPS could not unbind"); } - // GPS on/off persistent on app restart - public void CheckGPS() + public void gpsOn() { - CompoundButton GpsButton = (CompoundButton) findViewById(R.id.GPS_Toggle); - // if the user has already been asked about GPS access, do not ask again - // else ask and verify access before listening - if(!gpsChoosen) { - if(sharedPrefs.getBoolean("GPS_bool", true) ) { - gpsChoosen = true; - gpsBool = true; - GpsButton.setChecked(true); - } else { - gpsChoosen = true; - ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1); - gpsBool = ( ContextCompat.checkSelfPermission(this, android.Manifest.permission. - ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED ); - } - } // Light up the GPS if we're allowed - if ( gpsBool ) { - locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); - locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, gpsLogger); + if ( gpsPermission() ) { + Log.v("CHECK DPS", "Check GPS FAIL"); + try{ + locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); + locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, gpsLogger); + }catch(SecurityException e){ + Log.v("CHECK DPS", "Check GPS FAIL"); + } } } diff --git a/ElasticSensorDump/src/main/res/layout/activity_main.xml b/ElasticSensorDump/src/main/res/layout/activity_main.xml index 8145b52..68f4b16 100644 --- a/ElasticSensorDump/src/main/res/layout/activity_main.xml +++ b/ElasticSensorDump/src/main/res/layout/activity_main.xml @@ -10,44 +10,6 @@ tools:context="ca.dungeons.sensordump.MainActivity" android:background="@color/backGroundGreyTint"> - - - - - - - - - + android:max="100" + android:progress="25" + android:id="@+id/seekBar" + android:layout_width="200dp" /> - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + tools:ignore="RelativeOverlap" + android:layout_alignParentTop="true" + android:layout_alignParentEnd="true"> + + + + + - + \ No newline at end of file diff --git a/ElasticSensorDump/src/main/res/values/strings.xml b/ElasticSensorDump/src/main/res/values/strings.xml index edf3b53..7a4a62a 100644 --- a/ElasticSensorDump/src/main/res/values/strings.xml +++ b/ElasticSensorDump/src/main/res/values/strings.xml @@ -15,6 +15,11 @@ Settings ToggleButton Start Button + sensor_tv + documents_tv + gps_tv + errors_tv + Logging \ No newline at end of file diff --git a/ElasticSensorDump/src/main/res/xml/preferences.xml b/ElasticSensorDump/src/main/res/xml/preferences.xml index 60e0389..aebaaa9 100644 --- a/ElasticSensorDump/src/main/res/xml/preferences.xml +++ b/ElasticSensorDump/src/main/res/xml/preferences.xml @@ -1,10 +1,5 @@ - + - Date: Mon, 23 Jan 2017 08:57:48 -0700 Subject: [PATCH 02/42] maybe not broken --- .../ca/dungeons/sensordump/MainActivity.java | 104 +++++++++--------- 1 file changed, 50 insertions(+), 54 deletions(-) diff --git a/ElasticSensorDump/src/main/java/ca/dungeons/sensordump/MainActivity.java b/ElasticSensorDump/src/main/java/ca/dungeons/sensordump/MainActivity.java index b170c5a..c3796cf 100644 --- a/ElasticSensorDump/src/main/java/ca/dungeons/sensordump/MainActivity.java +++ b/ElasticSensorDump/src/main/java/ca/dungeons/sensordump/MainActivity.java @@ -16,8 +16,6 @@ import android.location.LocationManager; import android.os.BatteryManager; import android.os.Bundle; -import android.preference.PreferenceManager; -import android.support.annotation.NonNull; import android.support.v4.app.ActivityCompat; import android.support.v4.content.ContextCompat; import android.util.Log; @@ -31,11 +29,11 @@ import android.widget.ToggleButton; import org.json.JSONObject; -import org.w3c.dom.Text; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; +import java.util.ServiceConfigurationError; public class MainActivity extends Activity implements SensorEventListener { @@ -73,7 +71,7 @@ public void onReceive(Context context, Intent intent) { }; boolean gpsChoosen = false; - boolean gpsBool = false; + boolean gpsAccess = false; @Override protected void onCreate(final Bundle savedInstanceState) { @@ -81,7 +79,7 @@ protected void onCreate(final Bundle savedInstanceState) { setContentView(R.layout.activity_main); // Prevent screen from going into landscape setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED); - sharedPrefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext()); + sharedPrefs = this.getPreferences(Activity.MODE_PRIVATE); // main activity buttons buildButtonLogic(); // Get a list of all available sensors on the device and store in array @@ -179,16 +177,21 @@ private void startLogging() { // Prevent screen from sleeping if logging has started getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); //check for gps access, store in preferences - logging = true; startTime = System.currentTimeMillis(); lastUpdate = startTime; gpsLogger.resetGPS(); esIndexer = new ElasticSearchIndexer(); esIndexer.updateURL(sharedPrefs); - // Bind all sensors to activity - for (int usableSensor : usableSensors) { - mSensorManager.registerListener(this, mSensorManager.getDefaultSensor(usableSensor), SensorManager.SENSOR_DELAY_NORMAL); + try { + gpsPower(); + // Bind all sensors to activity + for (int usableSensor : usableSensors) { + mSensorManager.registerListener(this, mSensorManager.getDefaultSensor(usableSensor), SensorManager.SENSOR_DELAY_NORMAL); + } + }catch(Exception e){ + Log.v("Error starting a sensor", "Error starting a sensor!!"); } + } // Shut down the sensors by stopping listening to them @@ -196,10 +199,13 @@ private void stopLogging() { // Disable wakelock if logging has stopped getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); - unregisterReceiver(batteryReceiver); - mSensorManager.unregisterListener(this); - gpsOFF(); - logging = false; + try { + unregisterReceiver(batteryReceiver); + mSensorManager.unregisterListener(this); + gpsPower(); + }catch( Exception e){ + Log.v("Stop Logging", " Error stopLogging() "); + } } // Update the display with readings/written/errors @@ -262,7 +268,6 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { sensorRefreshTime = progress * 10; } } - @Override public void onStartTrackingTouch(SeekBar seekBar) { } //intentionally blank @@ -280,81 +285,72 @@ public void onStopTrackingTouch(SeekBar seekBar) { public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { // if the toggle button changed to ON do... if (isChecked) { - gpsOn(); + // asks for permission if sharedPrefs does not contain a value for gpsChosen. + gpsAccess = gpsPermission(); + gpsPower(); // if the toggle button is changed to OFF do... } else { // if we have gps access turn off receivers - if( gpsPermission() ) { + if( logging ) { try { - gpsOFF(); - // update sharedPrefs : gpsBool to FALSE - GpsToPrefs("GPS_Permission", false); - // update sharedPrefs : gpsChoosen to TRUE - GpsToPrefs("GPS_ASKEDforPermission", true); + gpsPower(); } catch (Exception e) { Log.v("GPS_TOGGLE_PROBLEM", "GPS_TOGGLE_PROBLEM"); } } } - } }); // end build button logic } - // write the result of asking for GPS access + // write the result of asking for GPS access void GpsToPrefs(String asked, boolean permission) { SharedPreferences.Editor sharedPref_Editor = sharedPrefs.edit(); sharedPref_Editor.putBoolean(asked, permission); sharedPref_Editor.apply(); } - // true = we have asked for permission, and it was granted - boolean gpsPermission() { - gpsChoosen = sharedPrefs.getBoolean("GPS_ASKEDforPermission", false); - if( !gpsChoosen ) { - requestGpsPermission(); - return sharedPrefs.getBoolean("GPS_Permission", false); - } - return sharedPrefs.getBoolean("GPS_Permission", false); - } // ask user to grant gps access & write result to sharedPrefs void requestGpsPermission(){ try{ - Log.v("CHECK DPS", "Check GPS FAIL"); ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1); - gpsBool = ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED; - GpsToPrefs("GPS_Permission", gpsBool); + gpsAccess = ( ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED ); + GpsToPrefs("GPS_Permission", gpsAccess); GpsToPrefs("GPS_ASKEDforPermission", true); }catch( SecurityException e) { Log.v("CHECK DPS", "Check GPS FAIL"); } - } - // unbind GPS listener, should stop GPS thread in 2.0 - public void gpsOFF(){ - //unbind GPS listener if permission was granted - if(ContextCompat.checkSelfPermission(this, android.Manifest.permission. - ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED ) - locationManager.removeUpdates(gpsLogger); - else if(ContextCompat.checkSelfPermission(this, android.Manifest.permission. - ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_DENIED) - Log.v("GPS Denied", "GPS Denied"); - //intentionally blank, if permission is denied initially, gps was not on - else //anything else - Log.v("GPS Error", "GPS could not unbind"); + // true = we have asked for permission, and it was granted + boolean gpsPermission() { + // if sharedPrefs does NOT contain a string for ASK for permission + String TempGosChosen = sharedPrefs.getString("GPS_ASKEDforPermission",null); + if( TempGosChosen == null ) { + requestGpsPermission(); + sharedPrefs.getBoolean("GPS_ASKEDforPermission", true); + return sharedPrefs.getBoolean("GPS_Permission", false); + } + return sharedPrefs.getBoolean("GPS_Permission", false); } - // GPS on/off persistent on app restart - public void gpsOn() + // GPS on/off + public void gpsPower() { - // Light up the GPS if we're allowed - if ( gpsPermission() ) { - Log.v("CHECK DPS", "Check GPS FAIL"); + if ( logging && gpsAccess ) { + //unbind GPS listener if permission was granted && we are logging + try { + locationManager.removeUpdates(gpsLogger); + }catch(SecurityException e){ + Log.e("ERROR: GPS receivers" ,"ERROR: GPS receivers are not running" ); + } + }else if( !logging && gpsAccess ){ // Light up the GPS if we're allowed try{ locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, gpsLogger); }catch(SecurityException e){ - Log.v("CHECK DPS", "Check GPS FAIL"); + Log.v("GPS ON", "GPS ON FAILED:: CHECK gpsPower()"); } + }else{ + Log.v("gpsPower()", "Either not logging or we don't have permission"); } } From 281be0cbc31d7fb5eef0cc47331ebe760010fbc8 Mon Sep 17 00:00:00 2001 From: Gurtok Date: Mon, 23 Jan 2017 21:33:35 -0700 Subject: [PATCH 03/42] maybe not broken --- .../ca/dungeons/sensordump/MainActivity.java | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/ElasticSensorDump/src/main/java/ca/dungeons/sensordump/MainActivity.java b/ElasticSensorDump/src/main/java/ca/dungeons/sensordump/MainActivity.java index c3796cf..a9ed297 100644 --- a/ElasticSensorDump/src/main/java/ca/dungeons/sensordump/MainActivity.java +++ b/ElasticSensorDump/src/main/java/ca/dungeons/sensordump/MainActivity.java @@ -33,7 +33,6 @@ import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; -import java.util.ServiceConfigurationError; public class MainActivity extends Activity implements SensorEventListener { @@ -43,7 +42,6 @@ public class MainActivity extends Activity implements SensorEventListener { private LocationManager locationManager; // Config data private SharedPreferences sharedPrefs; - private TextView tvProgress = null; private GPSLogger gpsLogger = new GPSLogger(); // JSON structure for sensor and gps data @@ -70,7 +68,6 @@ public void onReceive(Context context, Intent intent) { } }; - boolean gpsChoosen = false; boolean gpsAccess = false; @Override @@ -183,7 +180,7 @@ private void startLogging() { esIndexer = new ElasticSearchIndexer(); esIndexer.updateURL(sharedPrefs); try { - gpsPower(); + gpsPower("ON"); // Bind all sensors to activity for (int usableSensor : usableSensors) { mSensorManager.registerListener(this, mSensorManager.getDefaultSensor(usableSensor), SensorManager.SENSOR_DELAY_NORMAL); @@ -202,7 +199,7 @@ private void stopLogging() { try { unregisterReceiver(batteryReceiver); mSensorManager.unregisterListener(this); - gpsPower(); + gpsPower("OFF"); }catch( Exception e){ Log.v("Stop Logging", " Error stopLogging() "); } @@ -287,20 +284,19 @@ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if (isChecked) { // asks for permission if sharedPrefs does not contain a value for gpsChosen. gpsAccess = gpsPermission(); - gpsPower(); + gpsPower("ON"); // if the toggle button is changed to OFF do... } else { // if we have gps access turn off receivers if( logging ) { try { - gpsPower(); + gpsPower("OFF"); } catch (Exception e) { Log.v("GPS_TOGGLE_PROBLEM", "GPS_TOGGLE_PROBLEM"); } } } } - }); // end build button logic } @@ -333,16 +329,16 @@ boolean gpsPermission() { return sharedPrefs.getBoolean("GPS_Permission", false); } // GPS on/off - public void gpsPower() + public void gpsPower(String power) { - if ( logging && gpsAccess ) { + if ( power.equals("OFF") && gpsAccess ) { //unbind GPS listener if permission was granted && we are logging try { locationManager.removeUpdates(gpsLogger); }catch(SecurityException e){ Log.e("ERROR: GPS receivers" ,"ERROR: GPS receivers are not running" ); } - }else if( !logging && gpsAccess ){ // Light up the GPS if we're allowed + }else if( power.equals("ON") && gpsAccess ){ // Light up the GPS if we're allowed try{ locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, gpsLogger); From dd891231e041d6b99dafb6bedc9badc096c815eb Mon Sep 17 00:00:00 2001 From: Gurtok Date: Sun, 29 Jan 2017 17:34:18 -0700 Subject: [PATCH 04/42] maybe not broken --- .../sensordump/ElasticSearchIndexer.java | 24 +- .../ca/dungeons/sensordump/MainActivity.java | 240 +++++++++--------- .../src/main/res/layout/activity_main.xml | 8 +- 3 files changed, 129 insertions(+), 143 deletions(-) diff --git a/ElasticSensorDump/src/main/java/ca/dungeons/sensordump/ElasticSearchIndexer.java b/ElasticSensorDump/src/main/java/ca/dungeons/sensordump/ElasticSearchIndexer.java index dc333e4..192835f 100644 --- a/ElasticSensorDump/src/main/java/ca/dungeons/sensordump/ElasticSearchIndexer.java +++ b/ElasticSensorDump/src/main/java/ca/dungeons/sensordump/ElasticSearchIndexer.java @@ -138,9 +138,9 @@ public void run() { } // Only show errors for index requests, not the mapping request - if (isCreatingMapping) { + if (isCreatingMapping) isCreatingMapping = false; - } else { + else { Log.v("Index Request", "" + indexRequests); Log.v("Fail Reason", e.toString()); Log.v("Fail URL", url); @@ -149,9 +149,9 @@ public void run() { } } // We are no longer creating the mapping. Time for sensor readings! - if (isCreatingMapping) { + if (isCreatingMapping) isCreatingMapping = false; - } + // Bulk success! if (isBulk) { @@ -179,11 +179,10 @@ public void run() { // Build the URL based on the config data private String buildURL() { - if (esSSL) { + if (esSSL) return "https://" + esHost + ":" + esPort + "/" + esIndex + "/"; - } else { + else return "http://" + esHost + ":" + esPort + "/" + esIndex + "/"; - } } // Send mapping to elastic for sensor index using PUT @@ -213,11 +212,10 @@ private void indexFailedDocuments() { StringBuilder bulkDataList = new StringBuilder(); // Bulk index url - if (esSSL) { + if (esSSL) url = "https://" + esHost + ":" + esPort + "/_bulk"; - } else { + else url = "http://" + esHost + ":" + esPort + "/_bulk"; - } for (String failedJsonDoc : failedJSONDocs) { bulkDataList.append("{\"index\":{\"_index\":\"").append(esIndex) @@ -235,17 +233,15 @@ private void indexFailedDocuments() { void index(JSONObject joIndex) { // Create the mapping on first request - if (isCreatingMapping && indexRequests == 0) { + if (isCreatingMapping && indexRequests == 0) createMapping(); - } String jsonData = joIndex.toString(); String url = buildURL() + esType + "/"; // If we have some data, it's good to post - if (jsonData != null) { + if (jsonData != null) callElasticAPI("POST", url, jsonData, false); - } // Try it again! if (isLastIndexSuccessful && failedJSONDocs.size() > 0 && !isRetryingFailedIndexes) { diff --git a/ElasticSensorDump/src/main/java/ca/dungeons/sensordump/MainActivity.java b/ElasticSensorDump/src/main/java/ca/dungeons/sensordump/MainActivity.java index a9ed297..1b66c76 100644 --- a/ElasticSensorDump/src/main/java/ca/dungeons/sensordump/MainActivity.java +++ b/ElasticSensorDump/src/main/java/ca/dungeons/sensordump/MainActivity.java @@ -35,41 +35,41 @@ import java.util.List; public class MainActivity extends Activity implements SensorEventListener { - + // if we are logging, "main power button" + private boolean logging = false; + // do not record more than once every 50 milliseconds. Default value is 250ms. private static int MIN_SENSOR_REFRESH = 50; + private int sensorRefreshTime = 250; + // objects required private ElasticSearchIndexer esIndexer; private SensorManager mSensorManager; private LocationManager locationManager; + private GPSLogger gpsLogger = new GPSLogger(); // Config data private SharedPreferences sharedPrefs; - private GPSLogger gpsLogger = new GPSLogger(); - // JSON structure for sensor and gps data private JSONObject joSensorData = new JSONObject(); - + // the sensors we have permission to record private int[] usableSensors; - private boolean logging = false; - + boolean gpsPermission = false; + boolean gpsAccess = false; + // timers, the schema is defined else where private long lastUpdate; private long startTime; - - private int sensorRefreshTime = 250; + // battery level in percentages double batteryLevel = 0; final BroadcastReceiver batteryReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - //context.unregisterReceiver(this); int tempLevel = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1); int tempScale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1); - if(tempLevel > 0 && tempScale > 0) { + if (tempLevel > 0 && tempScale > 0) { batteryLevel = tempLevel; } } }; - boolean gpsAccess = false; - @Override protected void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -136,9 +136,9 @@ public final void onSensorChanged(SensorEvent event) { joSensorData.put("total_distance_miles", gpsLogger.gpsTotalDistanceMiles); } // put battery status percentage into the Json. - if (batteryLevel > 0) { + if (batteryLevel > 0) joSensorData.put("battery_percentage", batteryLevel); - } + // Store sensor update into sensor data structure for (int i = 0; i < event.values.length; i++) { // We don't need the android.sensor. and motorola.sensor. stuff @@ -163,48 +163,12 @@ public final void onSensorChanged(SensorEvent event) { lastUpdate = System.currentTimeMillis(); esIndexer.index(joSensorData); } + } catch (Exception e) { Log.v("JSON Logging error", e.toString()); } } - // Go through the sensor array and light them all up - private void startLogging() { - - // Prevent screen from sleeping if logging has started - getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); - //check for gps access, store in preferences - startTime = System.currentTimeMillis(); - lastUpdate = startTime; - gpsLogger.resetGPS(); - esIndexer = new ElasticSearchIndexer(); - esIndexer.updateURL(sharedPrefs); - try { - gpsPower("ON"); - // Bind all sensors to activity - for (int usableSensor : usableSensors) { - mSensorManager.registerListener(this, mSensorManager.getDefaultSensor(usableSensor), SensorManager.SENSOR_DELAY_NORMAL); - } - }catch(Exception e){ - Log.v("Error starting a sensor", "Error starting a sensor!!"); - } - - } - - // Shut down the sensors by stopping listening to them - private void stopLogging() { - - // Disable wakelock if logging has stopped - getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); - try { - unregisterReceiver(batteryReceiver); - mSensorManager.unregisterListener(this); - gpsPower("OFF"); - }catch( Exception e){ - Log.v("Stop Logging", " Error stopLogging() "); - } - } - // Update the display with readings/written/errors private void updateScreen() { // need to update UI based on the passed data intent @@ -215,11 +179,11 @@ private void updateScreen() { TextView gpsTV = (TextView) findViewById(R.id.gps_TV); TextView errorsTV = (TextView) findViewById(R.id.errors_TV); // update each metric - sensorTV.setText( (""+ esIndexer.indexRequests) ); - documentsTV.setText( (""+ esIndexer.indexSuccess) ); - gpsTV.setText( (""+ gpsLogger.gpsUpdates) ); - errorsTV.setText( (""+ esIndexer.failedIndex) ); - if(logging) + sensorTV.setText(("" + esIndexer.indexRequests)); + documentsTV.setText(("" + esIndexer.indexSuccess)); + gpsTV.setText(("" + gpsLogger.gpsUpdates)); + errorsTV.setText(("" + esIndexer.failedIndex)); + if (logging) mainBanner.setText(getString(R.string.logging)); else mainBanner.setText(getString(R.string.loggingStopped)); @@ -233,11 +197,9 @@ public void onClick(View v) { if (!logging) { btnStart.setText(getString(R.string.buttonStop)); startLogging(); - logging = true; } else { btnStart.setText(getString(R.string.buttonStart)); stopLogging(); - logging = false; } } }); @@ -274,99 +236,127 @@ public void onStopTrackingTouch(SeekBar seekBar) { } //intentionally blank }); - // GPS Toggle - // + /* GPS Toggle + gps recording on/off + gpsPermission() will only return TRUE IF we have both access and permission + */ final ToggleButton toggleButton = (ToggleButton) findViewById(R.id.GPS_Toggle); toggleButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - // if the toggle button changed to ON do... - if (isChecked) { - // asks for permission if sharedPrefs does not contain a value for gpsChosen. - gpsAccess = gpsPermission(); - gpsPower("ON"); - // if the toggle button is changed to OFF do... - } else { - // if we have gps access turn off receivers - if( logging ) { - try { - gpsPower("OFF"); - } catch (Exception e) { - Log.v("GPS_TOGGLE_PROBLEM", "GPS_TOGGLE_PROBLEM"); - } - } - } + gpsAccess = isChecked; } }); - // end build button logic } - // write the result of asking for GPS access - void GpsToPrefs(String asked, boolean permission) { + + /* INTENT: + write additional preferences + form of String Boolean + */ + void stringBooleanToPrefs(String asked, boolean permission) { SharedPreferences.Editor sharedPref_Editor = sharedPrefs.edit(); sharedPref_Editor.putBoolean(asked, permission); sharedPref_Editor.apply(); } - // ask user to grant gps access & write result to sharedPrefs - void requestGpsPermission(){ - try{ - ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1); - gpsAccess = ( ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED ); - GpsToPrefs("GPS_Permission", gpsAccess); - GpsToPrefs("GPS_ASKEDforPermission", true); - }catch( SecurityException e) { - Log.v("CHECK DPS", "Check GPS FAIL"); - } - } - // true = we have asked for permission, and it was granted - boolean gpsPermission() { + + /* INTENT: + ask user to grant gps access + write result to sharedPrefs + true = we have asked for permission, and it was granted + */ + public boolean gpsPermission() { // if sharedPrefs does NOT contain a string for ASK for permission - String TempGosChosen = sharedPrefs.getString("GPS_ASKEDforPermission",null); - if( TempGosChosen == null ) { - requestGpsPermission(); - sharedPrefs.getBoolean("GPS_ASKEDforPermission", true); - return sharedPrefs.getBoolean("GPS_Permission", false); + String tempGpsChosen = sharedPrefs.getString("GPS_ASKEDforPermission", null); + + if ( tempGpsChosen == null || tempGpsChosen.equals("false") ) { + try { + ActivityCompat.requestPermissions(this, new String[]{Manifest.permission. + ACCESS_FINE_LOCATION}, 1); + gpsPermission = (ContextCompat.checkSelfPermission(this, android.Manifest. + permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED); + + stringBooleanToPrefs("GPS_ASKEDforPermission", true); + stringBooleanToPrefs("GPS_Permission", gpsPermission ); + + return sharedPrefs.getBoolean("GPS_Permission", gpsPermission); + + } catch (SecurityException e) { + Log.v("CHECK DPS", "Check GPS FAIL"); + } } return sharedPrefs.getBoolean("GPS_Permission", false); } - // GPS on/off - public void gpsPower(String power) - { - if ( power.equals("OFF") && gpsAccess ) { - //unbind GPS listener if permission was granted && we are logging + + /* INTENT: + turn gps recording ON or OFF + */ + public void gpsPower(boolean power) { + if ( power && gpsPermission() ) {// Light up the GPS if we're allowed try { - locationManager.removeUpdates(gpsLogger); - }catch(SecurityException e){ - Log.e("ERROR: GPS receivers" ,"ERROR: GPS receivers are not running" ); - } - }else if( power.equals("ON") && gpsAccess ){ // Light up the GPS if we're allowed - try{ locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, gpsLogger); - }catch(SecurityException e){ + } catch (SecurityException e) { Log.v("GPS ON", "GPS ON FAILED:: CHECK gpsPower()"); } - }else{ - Log.v("gpsPower()", "Either not logging or we don't have permission"); - } + } else if(!power && logging ){ //unbind GPS listener if permission was granted && we are logging + try { + locationManager.removeUpdates(gpsLogger); + } catch (SecurityException e) { + Log.e("ERROR: GPS receivers", "ERROR: GPS receivers are not running"); + } + }else + Log.e("ERROR: GPS POWER", "ERROR: GPS power function"); } + // Go through the sensor array and light them all up + private void startLogging() { - @Override - protected void onPause() { - super.onPause(); - } + // Prevent screen from sleeping if logging has started + getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + //check for gps access, store in preferences + lastUpdate = startTime = System.currentTimeMillis(); + gpsLogger.resetGPS(); + esIndexer = new ElasticSearchIndexer(); + esIndexer.updateURL(sharedPrefs); + try { + resetSensorCounts(); + // bind and record sensors to activity + for (int usableSensor : usableSensors) + mSensorManager.registerListener(this, mSensorManager.getDefaultSensor(usableSensor), SensorManager.SENSOR_DELAY_NORMAL); - @Override - protected void onResume() { - super.onResume(); + // start gps sensor recording + gpsPower(true); + + // make sure we start to listen to the battery receiver + IntentFilter batteryFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); + registerReceiver(batteryReceiver, batteryFilter); + logging = true; + + } catch (Exception e) { + Log.v("Error starting a sensor", "Error starting a sensor!!"); + } } - @Override - protected void onStop() { - super.onStop(); + // Shut down the sensors by stopping listening to them + private void stopLogging() { + // Disable wakelock if logging has stopped + getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + try { + + mSensorManager.unregisterListener(this); + + if(gpsAccess) + gpsPower(false); + + unregisterReceiver(batteryReceiver); + logging = false; + } catch (Exception e) { + Log.v("Stop Logging", " Error stopLogging() "); + } } - @Override - protected void onDestroy() { - super.onDestroy(); + private void resetSensorCounts(){ + gpsLogger.resetGPS(); + esIndexer.resetCounters(); } + } diff --git a/ElasticSensorDump/src/main/res/layout/activity_main.xml b/ElasticSensorDump/src/main/res/layout/activity_main.xml index 68f4b16..02a08a6 100644 --- a/ElasticSensorDump/src/main/res/layout/activity_main.xml +++ b/ElasticSensorDump/src/main/res/layout/activity_main.xml @@ -95,7 +95,7 @@ android:textAlignment="textEnd" /> Date: Wed, 1 Feb 2017 22:54:07 -0700 Subject: [PATCH 05/42] starting on database storage for upload buffer --- .../ca/dungeons/sensordump/MainActivity.java | 51 +++++---- .../java/ca/dungeons/sensordump/dataBase.java | 106 ++++++++++++++++++ 2 files changed, 138 insertions(+), 19 deletions(-) create mode 100644 ElasticSensorDump/src/main/java/ca/dungeons/sensordump/dataBase.java diff --git a/ElasticSensorDump/src/main/java/ca/dungeons/sensordump/MainActivity.java b/ElasticSensorDump/src/main/java/ca/dungeons/sensordump/MainActivity.java index 1b66c76..0162226 100644 --- a/ElasticSensorDump/src/main/java/ca/dungeons/sensordump/MainActivity.java +++ b/ElasticSensorDump/src/main/java/ca/dungeons/sensordump/MainActivity.java @@ -33,6 +33,7 @@ import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; +import java.util.Locale; public class MainActivity extends Activity implements SensorEventListener { // if we are logging, "main power button" @@ -101,7 +102,7 @@ public final void onSensorChanged(SensorEvent event) { try { // Update timestamp in sensor data structure Date logDate = new Date(System.currentTimeMillis()); - SimpleDateFormat logDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZZ"); + SimpleDateFormat logDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZZ", Locale.US); String dateString = logDateFormat.format(logDate); joSensorData.put("@timestamp", dateString); @@ -164,6 +165,14 @@ public final void onSensorChanged(SensorEvent event) { esIndexer.index(joSensorData); } + // update gps access once per 5 seconds + // turn the gps Power true/false + if(System.currentTimeMillis() > lastUpdate + 5000){ + if(gpsAccess) + gpsPower(true); + + } + } catch (Exception e) { Log.v("JSON Logging error", e.toString()); } @@ -236,10 +245,10 @@ public void onStopTrackingTouch(SeekBar seekBar) { } //intentionally blank }); - /* GPS Toggle - gps recording on/off - gpsPermission() will only return TRUE IF we have both access and permission - */ + /* + * GPS Toggle + * gps recording on/off + */ final ToggleButton toggleButton = (ToggleButton) findViewById(R.id.GPS_Toggle); toggleButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override @@ -249,21 +258,21 @@ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { }); } - /* INTENT: - write additional preferences - form of String Boolean - */ + /* + * String asked = preferences key + * boolean permission = if the gps button is on && we have gps access + */ void stringBooleanToPrefs(String asked, boolean permission) { SharedPreferences.Editor sharedPref_Editor = sharedPrefs.edit(); sharedPref_Editor.putBoolean(asked, permission); sharedPref_Editor.apply(); } - /* INTENT: - ask user to grant gps access - write result to sharedPrefs - true = we have asked for permission, and it was granted - */ + /* + * ask user to grant gps access + * write result to sharedPrefs + * true = we have asked for permission, and it was granted + */ public boolean gpsPermission() { // if sharedPrefs does NOT contain a string for ASK for permission String tempGpsChosen = sharedPrefs.getString("GPS_ASKEDforPermission", null); @@ -287,8 +296,8 @@ public boolean gpsPermission() { return sharedPrefs.getBoolean("GPS_Permission", false); } - /* INTENT: - turn gps recording ON or OFF + /* + * turn gps recording ON or OFF */ public void gpsPower(boolean power) { if ( power && gpsPermission() ) {// Light up the GPS if we're allowed @@ -307,9 +316,11 @@ public void gpsPower(boolean power) { }else Log.e("ERROR: GPS POWER", "ERROR: GPS power function"); } - // Go through the sensor array and light them all up - private void startLogging() { + /* + * Go through the sensor array and light them all up + */ + private void startLogging() { // Prevent screen from sleeping if logging has started getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); //check for gps access, store in preferences @@ -336,7 +347,9 @@ private void startLogging() { } } - // Shut down the sensors by stopping listening to them + /* + * Shut down the sensors by stopping listening to them + */ private void stopLogging() { // Disable wakelock if logging has stopped getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); diff --git a/ElasticSensorDump/src/main/java/ca/dungeons/sensordump/dataBase.java b/ElasticSensorDump/src/main/java/ca/dungeons/sensordump/dataBase.java new file mode 100644 index 0000000..7d0a3ad --- /dev/null +++ b/ElasticSensorDump/src/main/java/ca/dungeons/sensordump/dataBase.java @@ -0,0 +1,106 @@ +package ca.dungeons.sensordump; + +// This class handles all the database activities +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; +import android.database.Cursor; +import android.content.Context; +import android.content.ContentValues; +import android.util.Log; +import org.json.JSONException; +import org.json.JSONObject; + +public class dataBase { + + public class dbInterface extends SQLiteOpenHelper{ + + /** + Created by Gurtok + EDIT: 02-01-2017 + Version 1.0 + final NAME String: "dbStorage". Database should be persistent, even when empty. + TABLE_NAME: passed in date string, already formatted. + */ + + private static final String DATABASE_NAME = "dbStorage"; // Main database name + private static final int DATABASE_VERSION = 1; // database version + private static final String TABLE_NAME = "StorageTable";// table name for database + private String COLUMN_JSON = "json OBJ BLOB"; + + + public dbInterface(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) { + super(context, DATABASE_NAME, factory, DATABASE_VERSION); + } + // This should never run, will delete the database. Required method. + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME); + onCreate(db); + } + /* + * Create a DATABASE named as a static variable up top + * two columns, one for KEY storage, one for the json blob + * execute the query + */ + @Override + public void onCreate(SQLiteDatabase dataBase) { + String query = "CREATE TABLE " + TABLE_NAME + "(" + + COLUMN_JSON + " BLOB " + " " + + "):"; + dataBase.execSQL(query); + } + /* + * add a new json object to the table + * the column ID will be auto-incremented + */ + public void JsonToDatabase(JSONObject jsonObject){ + ContentValues values = new ContentValues(); + values.put(COLUMN_JSON, jsonObject.toString() ); + SQLiteDatabase db = getWritableDatabase(); + db.insert(TABLE_NAME, null, values); + db.close(); + } + /* + * Delete a product from the database + */ + public void deleteJson(String productName){ + SQLiteDatabase db = getWritableDatabase(); + db.execSQL("DELETE FROM " + TABLE_NAME + " WHERE " + COLUMN_JSON + "=\"" + productName + "\";"); + } + /* + * retrieve a string from the database + * convert to json object + * send to elastic via index function + */ + public void SendJson() { + JSONObject retrievedJson = new JSONObject(); + ElasticSearchIndexer esIndexer = new ElasticSearchIndexer(); + SQLiteDatabase mainDB = getReadableDatabase(); + + Cursor recordCursor = mainDB.query("select top 1 * from" + + TABLE_NAME + + "order by RowID acs" + ,null,null,null,null,null,null, + "1");// LIMIT 1 json record at a time + // get the string from DB + String cursorString = recordCursor.getString(recordCursor.getColumnIndex(COLUMN_JSON)); + // try to convert string to a new json object + try { + retrievedJson = new JSONObject(cursorString); + }catch(JSONException e){ + Log.v("error creating JSON", "Error creating JSON"); + } + // if the json is not empty, send to kibana + if( retrievedJson.length() != 0) { + esIndexer.index(retrievedJson); + mainDB.close(); + recordCursor.close(); + }else { + mainDB.close(); + recordCursor.close(); + } + + } + + } +} \ No newline at end of file From cb164c77bf52add04a06c4fb8fe851528430c5f0 Mon Sep 17 00:00:00 2001 From: Gurtok Date: Wed, 29 Mar 2017 10:03:06 -0600 Subject: [PATCH 06/42] starting on database storage for upload buffer --- .../dungeons/sensordump/DatabaseHelper.java | 104 ++++++++++++++++++ .../dungeons/sensordump/UploadAsyncTask.java | 95 ++++++++++++++++ 2 files changed, 199 insertions(+) create mode 100644 ElasticSensorDump/src/main/java/ca/dungeons/sensordump/DatabaseHelper.java create mode 100644 ElasticSensorDump/src/main/java/ca/dungeons/sensordump/UploadAsyncTask.java diff --git a/ElasticSensorDump/src/main/java/ca/dungeons/sensordump/DatabaseHelper.java b/ElasticSensorDump/src/main/java/ca/dungeons/sensordump/DatabaseHelper.java new file mode 100644 index 0000000..a0fea47 --- /dev/null +++ b/ElasticSensorDump/src/main/java/ca/dungeons/sensordump/DatabaseHelper.java @@ -0,0 +1,104 @@ +package ca.dungeons.sensordump; + +// This class handles all the database activities +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; +import android.content.Context; +import android.content.ContentValues; +import android.os.AsyncTask; +import android.util.Log; +import org.json.JSONObject; + +/** + * A class to buffer generated data to a dataBase for later upload. + * @author Gurtok. + * @version First version of ESD dataBase helper. + */ +class DatabaseHelper extends SQLiteOpenHelper{ + + /** Main database name */ + private static final String DATABASE_NAME = "dbStorage"; + + /** Database version. */ + private static final int DATABASE_VERSION = 1; + + /** Table name for database. */ + static final String TABLE_NAME = "StorageTable"; + + /** json text. */ + static final String dataColumn = "JSON"; + + /** Get a new instance of the background Async task. */ + private UploadAsyncTask backgroundThread; + + /** + * Default constructor. Creates a new dataBase if required. + * @param context Calling method context. + */ + DatabaseHelper(Context context) { + super(context, DATABASE_NAME, null, DATABASE_VERSION); + backgroundThread = new UploadAsyncTask( context.getApplicationContext() ); + } + + /** + * @param db Existing dataBase. + * @param oldVersion Old version number ID. + * @param newVersion New version number ID. + */ + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME); + onCreate(db); + } + + /** + * Create the table for dataBase. + * Two columns. + * One for KEY storage. + * One for the json text string. + * Execute dataBase creation. + * @param dataBase Passed dataBase. Needs to be writable. + */ + @Override + public void onCreate(SQLiteDatabase dataBase) { + + String query = "CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " (ID INTEGER PRIMARY KEY, JSON TEXT);"; + dataBase.execSQL( query ); + } + + /** + * Pack the json object into a content values object for shipping. + * Insert completed json object into dataBase. + * Key will autoIncrement. + * Will also start a background thread to upload the database to Kibana. + * @param jsonObject Passed object to be inserted. + */ + void JsonToDatabase(JSONObject jsonObject){ + SQLiteDatabase storageWriteDatabase = getWritableDatabase(); + ContentValues values = new ContentValues(); + values.put(dataColumn, jsonObject.toString() ); + long checkDB = storageWriteDatabase.insert( TABLE_NAME, null, values); + + // Start the background upload task. + if( backgroundThread.getStatus() != AsyncTask.Status.RUNNING ){ + backgroundThread.execute(); + } + //For testing purposes. REMOVE ! + if(checkDB == -1) + Log.v("Failed insert","Failed insert database."); + else + Log.v("Inserted","inserted " + values); + + } + + /** + * Delete top row from the database. + */ + void deleteTopJson(){ + SQLiteDatabase db = getWritableDatabase(); + db.execSQL("DELETE FROM " + TABLE_NAME + " WHERE " + dataColumn + "IN (SELECT _id FROM " + + TABLE_NAME + " ORDER BY _id LIMIT 1)"); + Log.v("TOP deleted", String.format("%S%S%S","The top index of ", TABLE_NAME, " was delete.")); + } + +} diff --git a/ElasticSensorDump/src/main/java/ca/dungeons/sensordump/UploadAsyncTask.java b/ElasticSensorDump/src/main/java/ca/dungeons/sensordump/UploadAsyncTask.java new file mode 100644 index 0000000..320b02b --- /dev/null +++ b/ElasticSensorDump/src/main/java/ca/dungeons/sensordump/UploadAsyncTask.java @@ -0,0 +1,95 @@ +package ca.dungeons.sensordump; + +import android.content.Context; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.net.ConnectivityManager; +import android.os.AsyncTask; +import android.util.Log; +import org.json.JSONException; +import org.json.JSONObject; + +/** + * A class to start a thread upload the database to Kibana. + * @author Gurtok. + * @version First version of upload Async thread. + */ +class UploadAsyncTask extends AsyncTask{ + + private DatabaseHelper dbHelper; + private static ElasticSearchIndexer esIndexer = new ElasticSearchIndexer(); + private static Cursor cursor; + private static JSONObject jsonObject; + private Context callingContext; + + UploadAsyncTask( Context context ) { + dbHelper = new DatabaseHelper( context.getApplicationContext() ); + callingContext = context.getApplicationContext(); + } + + @Override + protected void onPreExecute() { + SQLiteDatabase readableDatabase = dbHelper.getReadableDatabase(); + cursor = readableDatabase.query("SELECT TOP 1 * FROM " + DatabaseHelper.TABLE_NAME + + " ORDER BY RowID ACS",null,null,null,null,null,null, " 1"); + } + + /** + * Check for internet connectivity. + * If connected, start up the async thread to send. + * @return Super requires a return value. In this case it will always be null. + */ + @Override + protected Void doInBackground(Void... params) { + + ConnectivityManager connectionManager = (ConnectivityManager) + callingContext.getSystemService(Context.CONNECTIVITY_SERVICE); + Boolean wifiCheck = connectionManager.getActiveNetworkInfo().isConnected(); + + if( wifiCheck ) { + do{ + String cursorString = cursor.getString( cursor.getColumnIndex(DatabaseHelper.dataColumn) ); + publishProgress( cursorString ); + dbHelper.deleteTopJson(); + }while( cursor.moveToNext() ); + + }else{ + Log.e("No network connection", "No connection, saving to database"); + } + + return null; + } + + /** + * This is the work loop for uploading. + * Called each loop of doInBackground method. + * String array parameter contains only ONE value, stored at index[0]. + * @param values A string value to be converted to JSON. + */ + @Override + protected void onProgressUpdate(String... values) { + + try { + jsonObject = new JSONObject( values[0] ); + } catch (JSONException e) { + Log.v("error creating JSON", "Error creating JSON"); + } + + // if the json is not empty, send to kibana + if (jsonObject.length() != 0) { + esIndexer.index( jsonObject ); + } + + } + + /** + * This runs after the dataBase is emptied or upload is interrupted. + * @param Void Not used. Required parameter from super. + */ + @Override + protected void onPostExecute(Void Void) { + dbHelper.close(); + } + + +} From 94a28718f700f3ee174760fa07e17f9232341786 Mon Sep 17 00:00:00 2001 From: Gurtok Date: Sat, 15 Apr 2017 08:48:29 -0600 Subject: [PATCH 07/42] starting on database storage for upload buffer --- ElasticSensorDump/build.gradle | 1 + .../src/main/AndroidManifest.xml | 2 +- .../dungeons/sensordump/DatabaseHelper.java | 62 ++-- .../sensordump/ElasticSearchIndexer.java | 292 +++++---------- .../ca/dungeons/sensordump/GPSLogger.java | 56 +-- .../ca/dungeons/sensordump/MainActivity.java | 343 +++++++++++------- .../dungeons/sensordump/UploadAsyncTask.java | 108 ++++-- .../java/ca/dungeons/sensordump/dataBase.java | 106 ------ .../ic_action_navigation_more_vert.png | Bin 0 -> 248 bytes .../ic_action_navigation_more_vert.png | Bin 0 -> 156 bytes .../ic_action_navigation_more_vert.png | Bin 0 -> 323 bytes .../ic_action_navigation_more_vert.png | Bin 0 -> 482 bytes .../src/main/res/layout/activity_main.xml | 283 ++++++++------- .../src/main/res/values/colors.xml | 3 +- .../src/main/res/values/strings.xml | 11 +- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 4 +- 17 files changed, 589 insertions(+), 684 deletions(-) delete mode 100644 ElasticSensorDump/src/main/java/ca/dungeons/sensordump/dataBase.java create mode 100644 ElasticSensorDump/src/main/res/drawable-hdpi/ic_action_navigation_more_vert.png create mode 100644 ElasticSensorDump/src/main/res/drawable-mdpi/ic_action_navigation_more_vert.png create mode 100644 ElasticSensorDump/src/main/res/drawable-xhdpi/ic_action_navigation_more_vert.png create mode 100644 ElasticSensorDump/src/main/res/drawable-xxhdpi/ic_action_navigation_more_vert.png diff --git a/ElasticSensorDump/build.gradle b/ElasticSensorDump/build.gradle index a984d63..6432e3a 100644 --- a/ElasticSensorDump/build.gradle +++ b/ElasticSensorDump/build.gradle @@ -24,4 +24,5 @@ dependencies { testCompile 'junit:junit:4.12' compile 'com.android.support:appcompat-v7:25.1.0' compile 'com.android.support:support-v4:25.1.0' + compile 'com.android.support.constraint:constraint-layout:1.0.2' } diff --git a/ElasticSensorDump/src/main/AndroidManifest.xml b/ElasticSensorDump/src/main/AndroidManifest.xml index b81a73c..22b295e 100644 --- a/ElasticSensorDump/src/main/AndroidManifest.xml +++ b/ElasticSensorDump/src/main/AndroidManifest.xml @@ -4,7 +4,7 @@ - + failedJSONDocs = new ArrayList<>(); - private boolean isLastIndexSuccessful = false; - - // Control variable to prevent sensors from being written before mapping created - // Multi-threading is fun :( - private boolean isCreatingMapping = true; - - // Another control variable, because threading is hate. - private boolean isRetryingFailedIndexes = false; - - - ElasticSearchIndexer() { - } - - void updateURL(SharedPreferences sharedPrefs) { - // Extract config information to build connection strings - esHost = sharedPrefs.getString("host", "localhost"); - esPort = sharedPrefs.getString("port", "9200"); - esIndex = sharedPrefs.getString("index", "sensor_dump"); - esType = sharedPrefs.getString("type", "phone_data"); - esSSL = sharedPrefs.getBoolean("ssl", false); - esUsername = sharedPrefs.getString("user", ""); - esPassword = sharedPrefs.getString("pass", ""); - - // Tag the current date stamp on the index name if set in preferences - // Thanks GlenRSmith for this idea - if (sharedPrefs.getBoolean("index_date", false)) { +import java.util.Locale; + +final class ElasticSearchIndexer{ + + /** Number of successful uploads. */ + private static long indexSuccess = 0; + /** Elastic search web address. */ + private static String esHost, esPort, esIndex, esType; + static String esUsername = ""; + static String esPassword = ""; + /** Represents if the server utilizes SSL security. */ + private static boolean esSSL; + private static SharedPreferences sharedPreferences = MainActivity.sharedPrefs; + private static boolean mappingCreated = false; + + /** + * On create, update the url from shared preferences. + * Then create and open a HTTP connection to url. + */ + private ElasticSearchIndexer(){} + + /** + * Extract config information to build connection strings. + * Tag the current date stamp on the index name if set in preferences. Credit: GlenRSmith. + */ + private static void updateURL() { + esHost = sharedPreferences.getString("host", "localhost"); + esPort = sharedPreferences.getString("port", "9200"); + esIndex = sharedPreferences.getString("index", "customer"); + esType = sharedPreferences.getString("type", "phone_data"); + esSSL = sharedPreferences.getBoolean("ssl", false); + esUsername = sharedPreferences.getString("user", ""); + esPassword = sharedPreferences.getString("pass", ""); + + if ( sharedPreferences.getBoolean("index_date", false)) { Date logDate = new Date(System.currentTimeMillis()); - SimpleDateFormat logDateFormat = new SimpleDateFormat("yyyyMMdd"); + SimpleDateFormat logDateFormat = new SimpleDateFormat("yyyyMMdd", Locale.US); String dateString = logDateFormat.format(logDate); esIndex = esIndex + "-" + dateString; } } - // Stop/start should reset counters - public void resetCounters() { - failedIndex = 0; - indexRequests = 0; - indexSuccess = 0; - } - - private void callElasticAPI(final String verb, final String url, - final String jsonData, final boolean isBulk) { - indexRequests++; - - // Send authentication if required - if (esUsername.length() > 0 && esPassword.length() > 0) { - Authenticator.setDefault(new Authenticator() { - protected PasswordAuthentication getPasswordAuthentication() { - return new PasswordAuthentication(esUsername, esPassword.toCharArray()); - } - }); - } + /** Build the URL based on the config data */ + static URL buildURL() { + updateURL(); + URL tempOutput = null; - // Spin up a thread for http connection - Runnable r = new Runnable() { - public void run() { - - HttpURLConnection httpCon; - OutputStreamWriter osw; - URL u; - - try { - u = new URL(url); - httpCon = (HttpURLConnection) u.openConnection(); - httpCon.setConnectTimeout(2000); - httpCon.setReadTimeout(2000); - httpCon.setDoOutput(true); - httpCon.setRequestMethod(verb); - osw = new OutputStreamWriter(httpCon.getOutputStream()); - osw.write(jsonData); - osw.close(); - httpCon.getInputStream(); - - // Something bad happened. I expect only the finest of 200's - int responseCode = httpCon.getResponseCode(); - if (responseCode > LAST_RESPONSE_CODE) { - if (!isCreatingMapping) { - failedIndex++; - isLastIndexSuccessful = false; - } - } else { - isLastIndexSuccessful = true; - indexSuccess++; - } - - httpCon.disconnect(); - - } catch (Exception e) { - - // Probably a connection error. Maybe. Lets just buffer up the json - // docs so we can try them again later - if (e instanceof IOException) { - if (!isCreatingMapping && !isBulk) { - isLastIndexSuccessful = false; - // Store up to MAX_FAILED_DOCS worth of data before dumping it - if(failedJSONDocs.size() < MAX_FAILED_DOCS) { - failedJSONDocs.add(jsonData); - } - } - } - - // Only show errors for index requests, not the mapping request - if (isCreatingMapping) - isCreatingMapping = false; - else { - Log.v("Index Request", "" + indexRequests); - Log.v("Fail Reason", e.toString()); - Log.v("Fail URL", url); - Log.v("Fail Data", jsonData); - failedIndex++; - } - } - // We are no longer creating the mapping. Time for sensor readings! - if (isCreatingMapping) - isCreatingMapping = false; - - - // Bulk success! - if (isBulk) { - // Clear failed log and update our stats - failedIndex -= failedJSONDocs.size(); - indexSuccess += failedJSONDocs.size(); - failedJSONDocs.clear(); - isRetryingFailedIndexes = false; - } - } - }; + String httpString = "http://"; + if (esSSL) + httpString = "https://"; - // Only allow posts if we're not creating mapping - if (isCreatingMapping) { - if (verb.equals("PUT")) { - Thread t = new Thread(r); - t.start(); - } - } else { - // We're not creating a mapping, just go nuts - Thread t = new Thread(r); - t.start(); + try{ + tempOutput = new URL( String.format("%s%s:%s/%s/",httpString ,esHost ,esPort ,esIndex )); + }catch(MalformedURLException urlEx){ + Log.e("buildURL", "Error building URL."); } + return tempOutput; } - // Build the URL based on the config data - private String buildURL() { - if (esSSL) - return "https://" + esHost + ":" + esPort + "/" + esIndex + "/"; - else - return "http://" + esHost + ":" + esPort + "/" + esIndex + "/"; - } - - // Send mapping to elastic for sensor index using PUT - private void createMapping() { + /** Send mapping to elastic for sensor index. */ + private static void createMapping() { JSONObject mappings = new JSONObject(); try { @@ -197,57 +81,53 @@ private void createMapping() { JSONObject indexType = new JSONObject().put(esType, properties); mappings = new JSONObject().put("mappings", indexType); } catch (JSONException j) { - Log.v("Json Exception", j.toString()); - } - - Log.v("Mapping", mappings.toString()); - - callElasticAPI("PUT", buildURL(), mappings.toString() , false); - } - - // Spam those failed docs! - // Maybe this should be a bulk operation... one day - private void indexFailedDocuments() { - String url; - StringBuilder bulkDataList = new StringBuilder(); - - // Bulk index url - if (esSSL) - url = "https://" + esHost + ":" + esPort + "/_bulk"; - else - url = "http://" + esHost + ":" + esPort + "/_bulk"; - - for (String failedJsonDoc : failedJSONDocs) { - bulkDataList.append("{\"index\":{\"_index\":\"").append(esIndex) - .append("\",\"_type\":\"").append(esType).append("\"}}\n"); - bulkDataList.append(failedJsonDoc).append("\n"); + Log.e("Mapping Error", "Error mapping " + j.toString()); + mappingCreated = false; } - String bulkData = bulkDataList.toString(); - - Log.v("Bulk Data", bulkData); - callElasticAPI("POST", url, bulkData, true); + index( mappings ); + mappingCreated = true; } - // Send JSON data to elastic using POST - void index(JSONObject joIndex) { + /** + * Send JSON data to elastic using POST + * @param jsonObject The supplied json object to be uploaded. + */ + static boolean index(JSONObject jsonObject) { // Create the mapping on first request - if (isCreatingMapping && indexRequests == 0) + if ( ! mappingCreated ){ createMapping(); + } - String jsonData = joIndex.toString(); - String url = buildURL() + esType + "/"; // If we have some data, it's good to post - if (jsonData != null) - callElasticAPI("POST", url, jsonData, false); + if ( jsonObject != null ) { + try { + UploadAsyncTask.outputStreamWriter.write( jsonObject.toString() ); + checkResponseCode(); + }catch(IOException IOex) { + // Error writing to httpConnection. + MainActivity.uploadErrors++; + return false; + } + } + return true; + } - // Try it again! - if (isLastIndexSuccessful && failedJSONDocs.size() > 0 && !isRetryingFailedIndexes) { - isRetryingFailedIndexes = true; - indexFailedDocuments(); + private static void checkResponseCode() { + try { + UploadAsyncTask.httpCon.getInputStream(); + // Something bad happened. I expect only the finest of 200's + int responseCode = UploadAsyncTask.httpCon.getResponseCode(); + if (200 <= responseCode && responseCode <= 299) { + indexSuccess++; + MainActivity.documentsIndexed = indexSuccess; + } + }catch(IOException IOex) { + Log.e("Bad response code", " Response code returned upload failure."); } } + } diff --git a/ElasticSensorDump/src/main/java/ca/dungeons/sensordump/GPSLogger.java b/ElasticSensorDump/src/main/java/ca/dungeons/sensordump/GPSLogger.java index 08010a2..64e7f5d 100644 --- a/ElasticSensorDump/src/main/java/ca/dungeons/sensordump/GPSLogger.java +++ b/ElasticSensorDump/src/main/java/ca/dungeons/sensordump/GPSLogger.java @@ -5,33 +5,23 @@ import android.os.Bundle; class GPSLogger implements LocationListener { - - boolean gpsHasData = false; - double gpsLat; - double gpsLong; - double gpsAlt; - float gpsAccuracy; - float gpsBearing; String gpsProvider; - float gpsSpeed; - float gpsSpeedKMH; - float gpsSpeedMPH; int gpsUpdates = 0; - double gpsLatStart; - double gpsLongStart; - float gpsAcceleration; - float gpsAccelerationKMH; - float gpsAccelerationMPH; - double gpsDistanceMetres; - double gpsDistanceFeet; - double gpsTotalDistance; - double gpsTotalDistanceKM; - double gpsTotalDistanceMiles; - + double gpsLat, gpsLong, gpsAlt; + double gpsLatStart, gpsLongStart; + double gpsDistanceMetres, gpsDistanceFeet, gpsTotalDistance; + double gpsTotalDistanceKM, gpsTotalDistanceMiles; + float gpsAccuracy, gpsBearing; + float gpsSpeed, gpsSpeedKMH, gpsSpeedMPH; + float gpsAcceleration, gpsAccelerationKMH, gpsAccelerationMPH; private float lastSpeed; - private double lastLat; - private double lastLong; + private double lastLat, lastLong; + boolean gpsHasData = false; + /** + * Lister for when the GPS reports a location change. + * @param location Current location. + */ @Override public void onLocationChanged(Location location) { @@ -52,7 +42,8 @@ public void onLocationChanged(Location location) { lastLong = gpsLong; } - this.gpsUpdates += 1; + gpsUpdates++; + MainActivity.gpsReadings = gpsUpdates; // Metre per second is not ideal. Adding km/hr and mph as well gpsSpeedKMH = gpsSpeed * (float) 3.6; @@ -87,22 +78,15 @@ public void onLocationChanged(Location location) { gpsHasData = true; } - void resetGPS() { - gpsUpdates = 0; - } + /** Reset the gps event counter. */ + void resetGPS(){ gpsUpdates = 0; } @Override - public void onStatusChanged(String provider, int status, Bundle extras) { - - } + public void onStatusChanged(String provider, int status, Bundle extras){} @Override - public void onProviderEnabled(String provider) { - - } + public void onProviderEnabled(String provider){} @Override - public void onProviderDisabled(String provider) { - - } + public void onProviderDisabled(String provider){} } diff --git a/ElasticSensorDump/src/main/java/ca/dungeons/sensordump/MainActivity.java b/ElasticSensorDump/src/main/java/ca/dungeons/sensordump/MainActivity.java index 0162226..1770b8b 100644 --- a/ElasticSensorDump/src/main/java/ca/dungeons/sensordump/MainActivity.java +++ b/ElasticSensorDump/src/main/java/ca/dungeons/sensordump/MainActivity.java @@ -25,9 +25,11 @@ import android.widget.CompoundButton; import android.widget.ImageButton; import android.widget.SeekBar; +import android.widget.Switch; import android.widget.TextView; -import android.widget.ToggleButton; +import android.widget.Toast; +import org.json.JSONException; import org.json.JSONObject; import java.text.SimpleDateFormat; @@ -35,31 +37,52 @@ import java.util.List; import java.util.Locale; +/** + * + */ public class MainActivity extends Activity implements SensorEventListener { - // if we are logging, "main power button" + + /** True if we are currently reading sensor data. */ private boolean logging = false; - // do not record more than once every 50 milliseconds. Default value is 250ms. + /** True if we are currently reading from gps sensors */ + boolean gpsLogging = false; + /** Variable to track if we have permission to upload via metered connection.*/ + boolean mobileUpload = false; + /** do not record more than once every 50 milliseconds. Default value is 250ms. */ private static int MIN_SENSOR_REFRESH = 50; + /** Refresh time in milliseconds. Default = 250ms.*/ private int sensorRefreshTime = 250; - // objects required - private ElasticSearchIndexer esIndexer; + + /** Instance of sensor Manager. */ private SensorManager mSensorManager; + /** Instance of gps Manager. */ private LocationManager locationManager; + /** A new instance of the GPSLogger.java file. + * Helper class to organize gps data. */ private GPSLogger gpsLogger = new GPSLogger(); - // Config data - private SharedPreferences sharedPrefs; - // JSON structure for sensor and gps data + /** A new instance of the DatabaseHelper class. + * Database IO runs through this object. */ + public final DatabaseHelper dbHelper = new DatabaseHelper( this ); + /** Global SharedPreferences object. */ + static SharedPreferences sharedPrefs; + /** Each loop, data wrapper to upload to Elastic. */ private JSONObject joSensorData = new JSONObject(); - // the sensors we have permission to record + /** Array to hold sensor references. */ private int[] usableSensors; + /** True if we have permission to record gps data. */ boolean gpsPermission = false; - boolean gpsAccess = false; - // timers, the schema is defined else where - private long lastUpdate; - private long startTime; - // battery level in percentages + + /** Timers, the schema is defined else where. */ + private long startTime, lastUpdate; + + /** Battery level in percentages. */ double batteryLevel = 0; + /** Number of sensor readings this session */ + public static long sensorReadings, documentsIndexed, gpsReadings, + uploadErrors, databaseEntries = 0; + + /** Listener for battery updates. */ final BroadcastReceiver batteryReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -71,52 +94,76 @@ public void onReceive(Context context, Intent intent) { } }; + /** + * Set contentView to portrait, and lock it that way. + * Build main activity buttons. + * Get a list of all available sensors on the device and store in array. + * + * @param savedInstanceState A generic object. + */ @Override protected void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); - // Prevent screen from going into landscape + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED); sharedPrefs = this.getPreferences(Activity.MODE_PRIVATE); - // main activity buttons + buildButtonLogic(); - // Get a list of all available sensors on the device and store in array + mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); List deviceSensors = mSensorManager.getSensorList(Sensor.TYPE_ALL); + usableSensors = new int[deviceSensors.size()]; + + for (int i = 0; i < deviceSensors.size(); i++) { usableSensors[i] = deviceSensors.get(i).getType(); + Log.e("device ID", usableSensors[i] + ": Device ID. "); } + IntentFilter batteryFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); registerReceiver(batteryReceiver, batteryFilter); - } - @Override - public final void onAccuracyChanged(Sensor sensor, int accuracy) { - // I don't really care about this yet. } + /** + * Required stub. Not used. + * @param sensor Empty. + * @param accuracy Empty. + */ + @Override + public final void onAccuracyChanged(Sensor sensor, int accuracy){ } + + /** + * This is the main recording loop. One reading per sensor per loop. + * Update timestamp in sensor data structure. + * Store the logging start time with each document. + * Store the duration of the sensor log with each document. + * Dump gps data into document if it's ready. + * Put battery status percentage into the Json. + * + * @param event A reference to the event object. + */ @Override public final void onSensorChanged(SensorEvent event) { try { - // Update timestamp in sensor data structure + Date logDate = new Date(System.currentTimeMillis()); SimpleDateFormat logDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZZ", Locale.US); String dateString = logDateFormat.format(logDate); joSensorData.put("@timestamp", dateString); - // Store the logging start time with each document Date startDate = new Date(startTime); String startDateString = logDateFormat.format(startDate); joSensorData.put("start_time", startDateString); - // Store the duration of the sensor log with each document long logDuration = (System.currentTimeMillis() - startTime) / 1000; joSensorData.put("log_duration_seconds", logDuration); - // Dump gps data into document if it's ready if (gpsLogger.gpsHasData) { + // Function to update the joSensorData list. joSensorData.put("location", "" + gpsLogger.gpsLat + "," + gpsLogger.gpsLong); joSensorData.put("start_location", "" + gpsLogger.gpsLatStart + "," + gpsLogger.gpsLongStart); joSensorData.put("altitude", gpsLogger.gpsAlt); @@ -136,7 +183,7 @@ public final void onSensorChanged(SensorEvent event) { joSensorData.put("total_distance_km", gpsLogger.gpsTotalDistanceKM); joSensorData.put("total_distance_miles", gpsLogger.gpsTotalDistanceMiles); } - // put battery status percentage into the Json. + if (batteryLevel > 0) joSensorData.put("battery_percentage", batteryLevel); @@ -157,219 +204,233 @@ public final void onSensorChanged(SensorEvent event) { joSensorData.put(sensorName, sensorValue); } } - // Make sure we only generate docs at an adjustable rate - // We'll use 250ms for now + // Make sure we only generate docs at an adjustable rate. + // 250ms is the default setting. if (System.currentTimeMillis() > lastUpdate + sensorRefreshTime) { updateScreen(); + // turn the gps Power true/false + if(gpsLogging) + gpsPower(true); + dbHelper.JsonToDatabase(joSensorData); + sensorReadings++; lastUpdate = System.currentTimeMillis(); - esIndexer.index(joSensorData); } - - // update gps access once per 5 seconds - // turn the gps Power true/false - if(System.currentTimeMillis() > lastUpdate + 5000){ - if(gpsAccess) - gpsPower(true); - - } - - } catch (Exception e) { - Log.v("JSON Logging error", e.toString()); + } catch (JSONException e) { + Log.e("JSON Logging error", e.getMessage() + " space " + e.getCause() ); } } - // Update the display with readings/written/errors + /** + * Update the display with readings/written/errors. + * Need to update UI based on the passed data intent. + * + */ private void updateScreen() { - // need to update UI based on the passed data intent - // + TextView mainBanner = (TextView) findViewById(R.id.main_Banner); TextView sensorTV = (TextView) findViewById(R.id.sensor_tv); TextView documentsTV = (TextView) findViewById(R.id.documents_tv); TextView gpsTV = (TextView) findViewById(R.id.gps_TV); TextView errorsTV = (TextView) findViewById(R.id.errors_TV); - // update each metric - sensorTV.setText(("" + esIndexer.indexRequests)); - documentsTV.setText(("" + esIndexer.indexSuccess)); - gpsTV.setText(("" + gpsLogger.gpsUpdates)); - errorsTV.setText(("" + esIndexer.failedIndex)); + TextView dbEntries = (TextView) findViewById(R.id.databaseCount); + + sensorTV.setText( String.valueOf(sensorReadings) ); + documentsTV.setText( String.valueOf( documentsIndexed ) ); + gpsTV.setText( String.valueOf( gpsReadings ) ); + errorsTV.setText( String.valueOf( uploadErrors ) ); + dbEntries.setText(String.valueOf( databaseEntries )); + if (logging) mainBanner.setText(getString(R.string.logging)); else mainBanner.setText(getString(R.string.loggingStopped)); } + /** + * Go through the sensor array and light them all up + * btnStart: Click a button, get some sensor data. + * ibSetup: Settings screen. + * seekBar: Adjust the collection rate of data. + * gpsToggle: Turn gps collection or/off. + */ void buildButtonLogic() { - // Click a button, get some sensor data + final Button btnStart = (Button) findViewById(R.id.btnStart); btnStart.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { - if (!logging) { - btnStart.setText(getString(R.string.buttonStop)); - startLogging(); - } else { - btnStart.setText(getString(R.string.buttonStart)); - stopLogging(); - } + if(!logging) { + btnStart.setText(getString(R.string.buttonStop)); + startLogging(); + }else { + btnStart.setText(getString(R.string.buttonStart)); + stopLogging(); + + } } }); - // Click a button, get the settings screen final ImageButton ibSetup = (ImageButton) findViewById(R.id.ibSetup); ibSetup.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { - // Callback for settings screen final Intent settingsIntent = new Intent(getBaseContext(), SettingsActivity.class); startActivity(settingsIntent); } }); - // Slide a bar to adjust the refresh times final SeekBar seekBar = (SeekBar) findViewById(R.id.seekBar); final TextView tvSeekBarText = (TextView) findViewById(R.id.TickText); tvSeekBarText.setText(getString(R.string.Collection_Interval) + " " + seekBar.getProgress() * 10 + getString(R.string.milliseconds)); seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - if (fromUser) { - if (progress < MIN_SENSOR_REFRESH) progress = MIN_SENSOR_REFRESH; - tvSeekBarText.setText(getString(R.string.Collection_Interval) + " " + progress * 10 + getString(R.string.milliseconds)); + + if ( progress * 10 < MIN_SENSOR_REFRESH ) { + seekBar.setProgress( MIN_SENSOR_REFRESH / 10 ); + Toast.makeText(getApplicationContext(),"Minimum sensor refresh is 50 ms",Toast.LENGTH_SHORT).show(); + }else sensorRefreshTime = progress * 10; - } + tvSeekBarText.setText(getString(R.string.Collection_Interval) + " " + sensorRefreshTime + getString(R.string.milliseconds)); } @Override - public void onStartTrackingTouch(SeekBar seekBar) { - } //intentionally blank + public void onStartTrackingTouch(SeekBar seekBar) {} //intentionally blank @Override - public void onStopTrackingTouch(SeekBar seekBar) { - } //intentionally blank + public void onStopTrackingTouch(SeekBar seekBar) {} //intentionally blank }); - /* - * GPS Toggle - * gps recording on/off - */ - final ToggleButton toggleButton = (ToggleButton) findViewById(R.id.GPS_Toggle); - toggleButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + final Switch mobileDataSwitch = (Switch) findViewById(R.id.mobileDataSwitch); + mobileDataSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - gpsAccess = isChecked; + mobileUpload = isChecked; } }); + + final Switch gpsDataSwitch = (Switch) findViewById(R.id.gpsDataSwitch); + gpsDataSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + gpsPermission = isChecked; + gpsPower(isChecked); + } + }); + } - /* - * String asked = preferences key - * boolean permission = if the gps button is on && we have gps access + /** + * Update preferences with new permissions. + * @param asked Preferences key. + * @param permission True if we have access. */ - void stringBooleanToPrefs(String asked, boolean permission) { + void BooleanToPrefs(String asked, boolean permission) { SharedPreferences.Editor sharedPref_Editor = sharedPrefs.edit(); sharedPref_Editor.putBoolean(asked, permission); sharedPref_Editor.apply(); } - /* - * ask user to grant gps access - * write result to sharedPrefs - * true = we have asked for permission, and it was granted + /** + * Prompt user for gps access. + * Write this result to shared preferences. + * @return True if we asked for permission and it was granted. */ public boolean gpsPermission() { // if sharedPrefs does NOT contain a string for ASK for permission - String tempGpsChosen = sharedPrefs.getString("GPS_ASKEDforPermission", null); + if ( ! sharedPrefs.contains("GPS_Asked") ) { + ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1); + gpsPermission = (ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED); - if ( tempGpsChosen == null || tempGpsChosen.equals("false") ) { - try { - ActivityCompat.requestPermissions(this, new String[]{Manifest.permission. - ACCESS_FINE_LOCATION}, 1); - gpsPermission = (ContextCompat.checkSelfPermission(this, android.Manifest. - permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED); - - stringBooleanToPrefs("GPS_ASKEDforPermission", true); - stringBooleanToPrefs("GPS_Permission", gpsPermission ); - - return sharedPrefs.getBoolean("GPS_Permission", gpsPermission); - - } catch (SecurityException e) { - Log.v("CHECK DPS", "Check GPS FAIL"); - } + BooleanToPrefs("GPS_Asked", true); + BooleanToPrefs("GPS_Permission", gpsPermission ); } - return sharedPrefs.getBoolean("GPS_Permission", false); + return sharedPrefs.getBoolean("GPS_Permission", false); } - /* - * turn gps recording ON or OFF + /** + * Power button for gps recording. + * @param power True if we can light the gps listeners up. */ public void gpsPower(boolean power) { - if ( power && gpsPermission() ) {// Light up the GPS if we're allowed + boolean gpsAccess = gpsPermission(); + + if ( power && gpsAccess && !gpsLogging ) {// Light up the GPS if we're allowed + locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); try { - locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, gpsLogger); + gpsLogging = true; + return; } catch (SecurityException e) { - Log.v("GPS ON", "GPS ON FAILED:: CHECK gpsPower()"); + Log.e("GPS ON", "GPS ON FAILED:: CHECK gpsPower()"); } - } else if(!power && logging ){ //unbind GPS listener if permission was granted && we are logging + } + + if( !power && gpsAccess && gpsLogging ){ //unbind GPS listener if permission was granted && we are logging try { locationManager.removeUpdates(gpsLogger); + gpsLogging = false; + return; } catch (SecurityException e) { Log.e("ERROR: GPS receivers", "ERROR: GPS receivers are not running"); } - }else - Log.e("ERROR: GPS POWER", "ERROR: GPS power function"); + } + Log.e("ERROR: GPS POWER", "ERROR: GPS power function"); } - /* - * Go through the sensor array and light them all up + /** + * Iterate through the sensor list and power them up. */ private void startLogging() { - // Prevent screen from sleeping if logging has started + // Prevent screen from sleeping if logging has started getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); - //check for gps access, store in preferences + clearCounts(); + //check for gps access, store in preferences lastUpdate = startTime = System.currentTimeMillis(); gpsLogger.resetGPS(); - esIndexer = new ElasticSearchIndexer(); - esIndexer.updateURL(sharedPrefs); - try { - resetSensorCounts(); - // bind and record sensors to activity - for (int usableSensor : usableSensors) - mSensorManager.registerListener(this, mSensorManager.getDefaultSensor(usableSensor), SensorManager.SENSOR_DELAY_NORMAL); - - // start gps sensor recording - gpsPower(true); - // make sure we start to listen to the battery receiver - IntentFilter batteryFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); - registerReceiver(batteryReceiver, batteryFilter); - logging = true; - - } catch (Exception e) { - Log.v("Error starting a sensor", "Error starting a sensor!!"); - } + // bind and record sensors to activity + for (int usableSensor : usableSensors) + mSensorManager.registerListener( this, mSensorManager.getDefaultSensor(usableSensor), SensorManager.SENSOR_DELAY_NORMAL); + // make sure we start to listen to the battery receiver + IntentFilter batteryFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); + registerReceiver(batteryReceiver, batteryFilter); + logging = true; } - /* - * Shut down the sensors by stopping listening to them + /** + * Stop the recording of sensor data. */ private void stopLogging() { // Disable wakelock if logging has stopped getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + gpsPower(false); + updateScreen(); try { - - mSensorManager.unregisterListener(this); - - if(gpsAccess) - gpsPower(false); - unregisterReceiver(batteryReceiver); + mSensorManager.unregisterListener(this); logging = false; } catch (Exception e) { - Log.v("Stop Logging", " Error stopLogging() "); + Log.e("Stop Logging", " Error stopLogging() " + e.getCause() + e.getMessage()); } } - private void resetSensorCounts(){ - gpsLogger.resetGPS(); - esIndexer.resetCounters(); + @Override + protected void onPause() { + super.onPause(); + try{ + unregisterReceiver(batteryReceiver); + mSensorManager.unregisterListener(this); + dbHelper.close(); + }catch(Exception e){ + Log.e("OnPause", "Error pausing app."); + } + } + + @Override + protected void onResume() { + super.onResume(); + } + + private void clearCounts(){ + sensorReadings = documentsIndexed = gpsReadings = uploadErrors = databaseEntries = 0; } } diff --git a/ElasticSensorDump/src/main/java/ca/dungeons/sensordump/UploadAsyncTask.java b/ElasticSensorDump/src/main/java/ca/dungeons/sensordump/UploadAsyncTask.java index 320b02b..f5e7015 100644 --- a/ElasticSensorDump/src/main/java/ca/dungeons/sensordump/UploadAsyncTask.java +++ b/ElasticSensorDump/src/main/java/ca/dungeons/sensordump/UploadAsyncTask.java @@ -2,36 +2,41 @@ import android.content.Context; import android.database.Cursor; +import android.database.DatabaseUtils; import android.database.sqlite.SQLiteDatabase; -import android.net.ConnectivityManager; import android.os.AsyncTask; import android.util.Log; import org.json.JSONException; import org.json.JSONObject; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.net.Authenticator; +import java.net.HttpURLConnection; +import java.net.PasswordAuthentication; +import java.net.URL; + /** * A class to start a thread upload the database to Kibana. * @author Gurtok. * @version First version of upload Async thread. */ -class UploadAsyncTask extends AsyncTask{ +class UploadAsyncTask extends AsyncTask{ private DatabaseHelper dbHelper; - private static ElasticSearchIndexer esIndexer = new ElasticSearchIndexer(); - private static Cursor cursor; - private static JSONObject jsonObject; - private Context callingContext; + static HttpURLConnection httpCon; + static OutputStreamWriter outputStreamWriter; + + /** Default Constructor using the application context. */ UploadAsyncTask( Context context ) { - dbHelper = new DatabaseHelper( context.getApplicationContext() ); - callingContext = context.getApplicationContext(); + dbHelper = new DatabaseHelper( context ); } + /** Required override method. Use to do initial housekeeping. */ @Override protected void onPreExecute() { - SQLiteDatabase readableDatabase = dbHelper.getReadableDatabase(); - cursor = readableDatabase.query("SELECT TOP 1 * FROM " + DatabaseHelper.TABLE_NAME + - " ORDER BY RowID ACS",null,null,null,null,null,null, " 1"); + super.onPreExecute(); } /** @@ -41,22 +46,54 @@ protected void onPreExecute() { */ @Override protected Void doInBackground(Void... params) { + URL url; + url = ElasticSearchIndexer.buildURL(); + SQLiteDatabase readableDatabase = dbHelper.getReadableDatabase(); + final String elasticUserName = ElasticSearchIndexer.esUsername; + final String elasticPassword = ElasticSearchIndexer.esPassword; + + // Send authentication if required + if ( elasticUserName.length() > 0 && elasticPassword.length() > 0) { + Authenticator.setDefault(new Authenticator() { + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(elasticUserName, elasticPassword.toCharArray()); + } + }); + } - ConnectivityManager connectionManager = (ConnectivityManager) - callingContext.getSystemService(Context.CONNECTIVITY_SERVICE); - Boolean wifiCheck = connectionManager.getActiveNetworkInfo().isConnected(); + try { + httpCon = (HttpURLConnection) url.openConnection(); + httpCon.setConnectTimeout(2000); + httpCon.setReadTimeout(2000); + httpCon.setDoOutput(true); + httpCon.setRequestMethod("PUT"); + outputStreamWriter = new OutputStreamWriter( httpCon.getOutputStream() ); + }catch (IOException IOex) { + Log.e("Network Connection", "Failed to connect to elastic. " + IOex.getMessage() + " " + IOex.getCause()); + } + + if( readableDatabase.getMaximumSize() >= 1 && outputStreamWriter != null ) { - if( wifiCheck ) { + String sqLiteQuery = "SELECT * FROM " + DatabaseHelper.TABLE_NAME + " ORDER BY ID ASC LIMIT 1"; + Cursor cursor = readableDatabase.rawQuery(sqLiteQuery, new String[]{} ); + cursor.moveToFirst(); do{ - String cursorString = cursor.getString( cursor.getColumnIndex(DatabaseHelper.dataColumn) ); - publishProgress( cursorString ); - dbHelper.deleteTopJson(); - }while( cursor.moveToNext() ); + try { + JSONObject jsonObject = new JSONObject( cursor.getString(1) ); + // if the json is not empty, send to kibana + if ( jsonObject.length() != 0 && outputStreamWriter != null) { + if( ElasticSearchIndexer.index( jsonObject ) ) + dbHelper.deleteTopJson(); + } + } catch (JSONException e) { + Log.e("error creating JSON", e.getMessage() + e.getCause() ); + } - }else{ - Log.e("No network connection", "No connection, saving to database"); + }while( cursor.moveToNext() ); + cursor.close(); } - + long count = DatabaseUtils.queryNumEntries(readableDatabase, DatabaseHelper.TABLE_NAME, null ); + publishProgress( count ); return null; } @@ -64,22 +101,12 @@ protected Void doInBackground(Void... params) { * This is the work loop for uploading. * Called each loop of doInBackground method. * String array parameter contains only ONE value, stored at index[0]. - * @param values A string value to be converted to JSON. + * @param progress A string value to be converted to JSON. */ @Override - protected void onProgressUpdate(String... values) { - - try { - jsonObject = new JSONObject( values[0] ); - } catch (JSONException e) { - Log.v("error creating JSON", "Error creating JSON"); - } - - // if the json is not empty, send to kibana - if (jsonObject.length() != 0) { - esIndexer.index( jsonObject ); - } - + protected void onProgressUpdate(Long... progress) { + super.onProgressUpdate(progress); + MainActivity.databaseEntries = progress[0]; } /** @@ -89,7 +116,16 @@ protected void onProgressUpdate(String... values) { @Override protected void onPostExecute(Void Void) { dbHelper.close(); + closeHttpConnection(); } + /** to be called by uploadAsyncTask to close the connection when thread closes. */ + private void closeHttpConnection(){ + httpCon.disconnect(); + } + + + + } diff --git a/ElasticSensorDump/src/main/java/ca/dungeons/sensordump/dataBase.java b/ElasticSensorDump/src/main/java/ca/dungeons/sensordump/dataBase.java deleted file mode 100644 index 7d0a3ad..0000000 --- a/ElasticSensorDump/src/main/java/ca/dungeons/sensordump/dataBase.java +++ /dev/null @@ -1,106 +0,0 @@ -package ca.dungeons.sensordump; - -// This class handles all the database activities -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteOpenHelper; -import android.database.Cursor; -import android.content.Context; -import android.content.ContentValues; -import android.util.Log; -import org.json.JSONException; -import org.json.JSONObject; - -public class dataBase { - - public class dbInterface extends SQLiteOpenHelper{ - - /** - Created by Gurtok - EDIT: 02-01-2017 - Version 1.0 - final NAME String: "dbStorage". Database should be persistent, even when empty. - TABLE_NAME: passed in date string, already formatted. - */ - - private static final String DATABASE_NAME = "dbStorage"; // Main database name - private static final int DATABASE_VERSION = 1; // database version - private static final String TABLE_NAME = "StorageTable";// table name for database - private String COLUMN_JSON = "json OBJ BLOB"; - - - public dbInterface(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) { - super(context, DATABASE_NAME, factory, DATABASE_VERSION); - } - // This should never run, will delete the database. Required method. - @Override - public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { - db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME); - onCreate(db); - } - /* - * Create a DATABASE named as a static variable up top - * two columns, one for KEY storage, one for the json blob - * execute the query - */ - @Override - public void onCreate(SQLiteDatabase dataBase) { - String query = "CREATE TABLE " + TABLE_NAME + "(" + - COLUMN_JSON + " BLOB " + " " + - "):"; - dataBase.execSQL(query); - } - /* - * add a new json object to the table - * the column ID will be auto-incremented - */ - public void JsonToDatabase(JSONObject jsonObject){ - ContentValues values = new ContentValues(); - values.put(COLUMN_JSON, jsonObject.toString() ); - SQLiteDatabase db = getWritableDatabase(); - db.insert(TABLE_NAME, null, values); - db.close(); - } - /* - * Delete a product from the database - */ - public void deleteJson(String productName){ - SQLiteDatabase db = getWritableDatabase(); - db.execSQL("DELETE FROM " + TABLE_NAME + " WHERE " + COLUMN_JSON + "=\"" + productName + "\";"); - } - /* - * retrieve a string from the database - * convert to json object - * send to elastic via index function - */ - public void SendJson() { - JSONObject retrievedJson = new JSONObject(); - ElasticSearchIndexer esIndexer = new ElasticSearchIndexer(); - SQLiteDatabase mainDB = getReadableDatabase(); - - Cursor recordCursor = mainDB.query("select top 1 * from" + - TABLE_NAME + - "order by RowID acs" - ,null,null,null,null,null,null, - "1");// LIMIT 1 json record at a time - // get the string from DB - String cursorString = recordCursor.getString(recordCursor.getColumnIndex(COLUMN_JSON)); - // try to convert string to a new json object - try { - retrievedJson = new JSONObject(cursorString); - }catch(JSONException e){ - Log.v("error creating JSON", "Error creating JSON"); - } - // if the json is not empty, send to kibana - if( retrievedJson.length() != 0) { - esIndexer.index(retrievedJson); - mainDB.close(); - recordCursor.close(); - }else { - mainDB.close(); - recordCursor.close(); - } - - } - - } -} \ No newline at end of file diff --git a/ElasticSensorDump/src/main/res/drawable-hdpi/ic_action_navigation_more_vert.png b/ElasticSensorDump/src/main/res/drawable-hdpi/ic_action_navigation_more_vert.png new file mode 100644 index 0000000000000000000000000000000000000000..eda3b50a111070f2b3180d53633a0345c4171d6a GIT binary patch literal 248 zcmVd4;` z8Xoqw2w3Z0LRX*yZn@AKcmbVNcy8S*=nm9CnG1Y?7HG~8lpga0E|cOt@BntT&qGK~ zPy!>>vLr~()PsFw#(wWG&7Sj^dVHx2Avq68O_^K{$q9;J+>$XeW4}f8s=X167A7yD y2*xGC5sa4q;*W6+p~Lrh$36rdPQbcQu4O+v%RD8ZD=2IL00004rbP0l+XkK DZCNjI literal 0 HcmV?d00001 diff --git a/ElasticSensorDump/src/main/res/drawable-xhdpi/ic_action_navigation_more_vert.png b/ElasticSensorDump/src/main/res/drawable-xhdpi/ic_action_navigation_more_vert.png new file mode 100644 index 0000000000000000000000000000000000000000..8ead3f1228c409505f2620e9e60b3d343e41b508 GIT binary patch literal 323 zcmV-J0lfZ+P)4&%jk@gyWS5?|Y=6O?ojpcm{ z{jBgVQ8a+G5|S4htHlTjrCwz6LSv;9c?+eMki5_oBqT3X!$QO!sL5~sHX4Au&=5rt z45a_1OufkDg@!cWe;+XesU;*YGzAIC3)Qd?F~l|b&EE=uxrN36V!+ry^YQcyJOQa; VNHO5&S3Up$002ovPDHLkV1lWcgp&XO literal 0 HcmV?d00001 diff --git a/ElasticSensorDump/src/main/res/drawable-xxhdpi/ic_action_navigation_more_vert.png b/ElasticSensorDump/src/main/res/drawable-xxhdpi/ic_action_navigation_more_vert.png new file mode 100644 index 0000000000000000000000000000000000000000..363ef22064bbe779da05d6ecb2925525ecc9e1ae GIT binary patch literal 482 zcmV<80UiE{P)=q(K_gM?i!6__+sZ(El=Mf3uvAzGW@x(A*{C^Qn#6>t<>^eb>1tX;Hh6rgfi-2i*R)qDciz@MLP0!ln6 z+F~;=$4z<$kjH#r19nghK=P^)fHakOS#5xoqIA?8lw$FbhY(QWK{4_Ihu35?$W3~O z5+3uFK5r{7iDKY&XpoU>K$A*|25FE6^%2mZK7Q^&8q{ad Y8pH;ENm=S - + + + + + + + + + android:gravity="top|center" + android:orientation="vertical" + android:layout_below="@+id/ibSetup" + android:layout_alignParentEnd="true" + android:layout_marginTop="30dp">