From 9f14087770085748b759015164f12be22ddf9e81 Mon Sep 17 00:00:00 2001 From: Neel Trivedi Date: Fri, 10 May 2019 07:56:54 +0530 Subject: [PATCH 01/22] save graph function implemeted (#1696) --- .../pslab/fragment/BaroMeterDataFragment.java | 53 +++++++++++++++++-- .../pslab/fragment/LuxMeterDataFragment.java | 51 ++++++++++++++++-- .../res/layout/fragment_barometer_data.xml | 1 + .../res/layout/fragment_lux_meter_data.xml | 1 + 4 files changed, 97 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/io/pslab/fragment/BaroMeterDataFragment.java b/app/src/main/java/io/pslab/fragment/BaroMeterDataFragment.java index 3073ee852..5a618f19f 100644 --- a/app/src/main/java/io/pslab/fragment/BaroMeterDataFragment.java +++ b/app/src/main/java/io/pslab/fragment/BaroMeterDataFragment.java @@ -1,5 +1,6 @@ package io.pslab.fragment; +import android.graphics.Bitmap; import android.graphics.Color; import android.hardware.Sensor; import android.hardware.SensorEvent; @@ -7,6 +8,7 @@ import android.hardware.SensorManager; import android.location.Location; import android.os.Bundle; +import android.os.Environment; import android.os.Handler; import android.support.annotation.NonNull; import android.support.v4.app.Fragment; @@ -16,7 +18,9 @@ import android.view.ViewGroup; import android.widget.TextView; import android.widget.Toast; + import io.pslab.DataFormatter; + import com.github.anastr.speedviewlib.PointerSpeedometer; import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.components.Legend; @@ -26,7 +30,14 @@ import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.FileWriter; import java.io.IOException; +import java.io.PrintWriter; +import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.Locale; @@ -48,6 +59,7 @@ import io.pslab.others.ScienceLabCommon; import static android.content.Context.SENSOR_SERVICE; +import static io.pslab.others.CSVLogger.CSV_DIRECTORY; /** * Created by Padmal on 12/13/18. @@ -93,6 +105,7 @@ private enum BARO_SENSOR {INBUILT_SENSOR, BMP180_SENSOR} private Unbinder unbinder; private long previousTimeElapsed = (System.currentTimeMillis() - startTime) / updatePeriod; private BarometerActivity baroSensor; + private View rootView; public static BaroMeterDataFragment newInstance() { return new BaroMeterDataFragment(); @@ -115,10 +128,10 @@ public void onCreate(Bundle savedInstanceState) { @Override public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.fragment_barometer_data, container, false); - unbinder = ButterKnife.bind(this, view); + rootView = inflater.inflate(R.layout.fragment_barometer_data, container, false); + unbinder = ButterKnife.bind(this, rootView); setupInstruments(); - return view; + return rootView; } @Override @@ -309,9 +322,39 @@ public void stopData() { } public void saveGraph() { - // Todo: Save graph view to gallery + String fileName = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.getDefault()).format(baroSensor.recordedBaroData.get(0).getTime()); + File csvFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + + File.separator + CSV_DIRECTORY + File.separator + baroSensor.getSensorName() + + File.separator + fileName + ".csv"); + if (!csvFile.exists()) { + try { + csvFile.createNewFile(); + PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(csvFile, true))); + out.write( "Timestamp,DateTime,Readings,Latitude,Longitude" + "\n"); + for (BaroData baroData : baroSensor.recordedBaroData) { + out.write( baroData.getTime() + "," + + CSVLogger.FILE_NAME_FORMAT.format(new Date(baroData.getTime())) + "," + + baroData.getBaro() + "," + + baroData.getLat() + "," + + baroData.getLon() + "," + "\n"); + } + out.flush(); + out.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + View view = rootView.findViewById(R.id.barometer_linearlayout); + view.setDrawingCacheEnabled(true); + Bitmap b = view.getDrawingCache(); + try { + b.compress(Bitmap.CompressFormat.JPEG, 100, new FileOutputStream(Environment.getExternalStorageDirectory().getAbsolutePath() + + File.separator + CSV_DIRECTORY + File.separator + baroSensor.getSensorName() + + File.separator + CSVLogger.FILE_NAME_FORMAT.format(new Date()) + "_graph.jpg" )); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } } - private void setupInstruments() { baroMeter.setMaxSpeed(PreferenceManager.getDefaultSharedPreferences(getActivity()).getFloat(baroSensor.BAROMETER_LIMIT, 2)); XAxis x = mChart.getXAxis(); diff --git a/app/src/main/java/io/pslab/fragment/LuxMeterDataFragment.java b/app/src/main/java/io/pslab/fragment/LuxMeterDataFragment.java index 23df52cca..c63ab7cbf 100644 --- a/app/src/main/java/io/pslab/fragment/LuxMeterDataFragment.java +++ b/app/src/main/java/io/pslab/fragment/LuxMeterDataFragment.java @@ -1,5 +1,6 @@ package io.pslab.fragment; +import android.graphics.Bitmap; import android.graphics.Color; import android.hardware.Sensor; import android.hardware.SensorEvent; @@ -7,6 +8,7 @@ import android.hardware.SensorManager; import android.location.Location; import android.os.Bundle; +import android.os.Environment; import android.os.Handler; import android.support.annotation.NonNull; import android.support.v4.app.Fragment; @@ -26,7 +28,14 @@ import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.FileWriter; import java.io.IOException; +import java.io.PrintWriter; +import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.Locale; @@ -50,6 +59,7 @@ import io.pslab.others.ScienceLabCommon; import static android.content.Context.SENSOR_SERVICE; +import static io.pslab.others.CSVLogger.CSV_DIRECTORY; /** * Created by Padmal on 11/2/18. @@ -96,6 +106,7 @@ private enum LUX_SENSOR {INBUILT_SENSOR, BH1750_SENSOR, TSL2561_SENSOR} private Unbinder unbinder; private long previousTimeElapsed = (System.currentTimeMillis() - startTime) / updatePeriod; private LuxMeterActivity luxSensor; + private View rootView; public static LuxMeterDataFragment newInstance() { return new LuxMeterDataFragment(); @@ -119,10 +130,10 @@ public void onCreate(Bundle savedInstanceState) { @Override public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.fragment_lux_meter_data, container, false); - unbinder = ButterKnife.bind(this, view); + rootView = inflater.inflate(R.layout.fragment_lux_meter_data, container, false); + unbinder = ButterKnife.bind(this, rootView); setupInstruments(); - return view; + return rootView; } @Override @@ -313,9 +324,41 @@ public void playData() { } public void saveGraph() { - // Todo: Save graph view to gallery + String fileName = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.getDefault()).format(luxSensor.recordedLuxData.get(0).getTime()); + File csvFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + + File.separator + CSV_DIRECTORY + File.separator + luxSensor.getSensorName() + + File.separator + fileName + ".csv"); + if (!csvFile.exists()) { + try { + csvFile.createNewFile(); + PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(csvFile, true))); + out.write( "Timestamp,DateTime,Readings,Latitude,Longitude" + "\n"); + for (LuxData luxData : luxSensor.recordedLuxData) { + out.write( luxData.getTime() + "," + + CSVLogger.FILE_NAME_FORMAT.format(new Date(luxData.getTime())) + "," + + luxData.getLux() + "," + + luxData.getLat() + "," + + luxData.getLon() + "," + "\n"); + } + out.flush(); + out.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + View view = rootView.findViewById(R.id.luxmeter_linearlayout); + view.setDrawingCacheEnabled(true); + Bitmap b = view.getDrawingCache(); + try { + b.compress(Bitmap.CompressFormat.JPEG, 100, new FileOutputStream(Environment.getExternalStorageDirectory().getAbsolutePath() + + File.separator + CSV_DIRECTORY + File.separator + luxSensor.getSensorName() + + File.separator + CSVLogger.FILE_NAME_FORMAT.format(new Date()) + "_graph.jpg" )); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } } + private void setupInstruments() { lightMeter.setMaxSpeed(PreferenceManager.getDefaultSharedPreferences(getActivity()).getFloat(luxSensor.LUXMETER_LIMIT, 10000)); diff --git a/app/src/main/res/layout/fragment_barometer_data.xml b/app/src/main/res/layout/fragment_barometer_data.xml index a73b69214..0c72f6b3d 100644 --- a/app/src/main/res/layout/fragment_barometer_data.xml +++ b/app/src/main/res/layout/fragment_barometer_data.xml @@ -2,6 +2,7 @@ diff --git a/app/src/main/res/layout/fragment_lux_meter_data.xml b/app/src/main/res/layout/fragment_lux_meter_data.xml index b65264ccc..d02da250f 100644 --- a/app/src/main/res/layout/fragment_lux_meter_data.xml +++ b/app/src/main/res/layout/fragment_lux_meter_data.xml @@ -2,6 +2,7 @@ From eca97b929bb06fb268aaffe026219a65ac0eac6c Mon Sep 17 00:00:00 2001 From: Smit Jasani Date: Fri, 10 May 2019 16:56:10 +0530 Subject: [PATCH 02/22] Appropriate message added in LuxMeter and BaroMeter configurations (#1701) --- .../io/pslab/activity/BarometerActivity.java | 12 ++++++------ .../fragment/BaroMeterSettingsFragment.java | 18 ++++++++++-------- .../fragment/LuxMeterSettingFragment.java | 15 +++++++++++++-- app/src/main/res/values/strings.xml | 9 ++++++--- app/src/main/res/xml/baro_meter_settings.xml | 2 +- app/src/main/res/xml/lux_meter_settings.xml | 2 +- 6 files changed, 37 insertions(+), 21 deletions(-) diff --git a/app/src/main/java/io/pslab/activity/BarometerActivity.java b/app/src/main/java/io/pslab/activity/BarometerActivity.java index dc4e5d02a..739312111 100644 --- a/app/src/main/java/io/pslab/activity/BarometerActivity.java +++ b/app/src/main/java/io/pslab/activity/BarometerActivity.java @@ -111,12 +111,12 @@ protected void onResume() { } private void reinstateConfigurations() { - SharedPreferences luxMeterConfigurations; - luxMeterConfigurations = PreferenceManager.getDefaultSharedPreferences(getBaseContext()); - locationEnabled = luxMeterConfigurations.getBoolean(BaroMeterSettingsFragment.KEY_INCLUDE_LOCATION, true); + SharedPreferences BaroMeterConfigurations; + BaroMeterConfigurations = PreferenceManager.getDefaultSharedPreferences(getBaseContext()); + locationEnabled = BaroMeterConfigurations.getBoolean(BaroMeterSettingsFragment.KEY_INCLUDE_LOCATION, true); BaroMeterDataFragment.setParameters( - Float.valueOf(luxMeterConfigurations.getString(BaroMeterSettingsFragment.KEY_HIGH_LIMIT, "1.1")), - Integer.valueOf(luxMeterConfigurations.getString(BaroMeterSettingsFragment.KEY_UPDATE_PERIOD, "1000")), - luxMeterConfigurations.getString(BaroMeterSettingsFragment.KEY_BARO_SENSOR_TYPE, "0")); + Float.valueOf(BaroMeterConfigurations.getString(BaroMeterSettingsFragment.KEY_HIGH_LIMIT, "1.1")), + Integer.valueOf(BaroMeterConfigurations.getString(BaroMeterSettingsFragment.KEY_UPDATE_PERIOD, "1000")), + BaroMeterConfigurations.getString(BaroMeterSettingsFragment.KEY_BARO_SENSOR_TYPE, "0")); } } diff --git a/app/src/main/java/io/pslab/fragment/BaroMeterSettingsFragment.java b/app/src/main/java/io/pslab/fragment/BaroMeterSettingsFragment.java index 5cfae7daf..d287657e1 100644 --- a/app/src/main/java/io/pslab/fragment/BaroMeterSettingsFragment.java +++ b/app/src/main/java/io/pslab/fragment/BaroMeterSettingsFragment.java @@ -8,6 +8,7 @@ import android.support.v7.preference.ListPreference; import android.support.v7.preference.PreferenceFragmentCompat; import android.support.v7.preference.PreferenceManager; +import android.widget.Toast; import io.pslab.DataFormatter; import io.pslab.R; @@ -81,10 +82,10 @@ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, Strin if (updatePeriod > 2000 || updatePeriod < 100) { throw new NumberFormatException(); } else { - updatePeriodPref.setSummary(String.valueOf(updatePeriod)); + updatePeriodPref.setSummary(String.valueOf(updatePeriod) + " ms"); } - updatePeriodPref.setSummary(updatePeriod + " ms"); } catch (NumberFormatException e) { + Toast.makeText(getActivity(), getActivity().getResources().getString(R.string.update_period_msg), Toast.LENGTH_SHORT).show(); updatePeriodPref.setSummary("1000 ms"); updatePeriodPref.setText("1000"); SharedPreferences.Editor editor = sharedPref.edit(); @@ -94,17 +95,18 @@ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, Strin break; case KEY_HIGH_LIMIT: try { - Float highLimit = Float.parseFloat(highLimitPref.getText()); - if (highLimit > 1.1 || highLimit < 0.0) { + double highLimit = Double.parseDouble(highLimitPref.getText()); + if (highLimit > 1.10 || highLimit < 0.00) { throw new NumberFormatException(); } else { - highLimitPref.setSummary(DataFormatter.formatDouble(highLimit, DataFormatter.LOW_PRECISION_FORMAT)); + highLimitPref.setSummary(DataFormatter.formatDouble(highLimit, DataFormatter.LOW_PRECISION_FORMAT) + " atm"); } } catch (NumberFormatException e) { - highLimitPref.setSummary("1.1 atm"); - highLimitPref.setText("1.1"); + Toast.makeText(getActivity(), getActivity().getResources().getString(R.string.high_limit_msg), Toast.LENGTH_SHORT).show(); + highLimitPref.setSummary("1.10 atm"); + highLimitPref.setText("1.10"); SharedPreferences.Editor editor = sharedPref.edit(); - editor.putString(KEY_HIGH_LIMIT, "1.1"); + editor.putString(KEY_HIGH_LIMIT, "1.10"); editor.commit(); } break; diff --git a/app/src/main/java/io/pslab/fragment/LuxMeterSettingFragment.java b/app/src/main/java/io/pslab/fragment/LuxMeterSettingFragment.java index 86efa44e6..168cc1726 100644 --- a/app/src/main/java/io/pslab/fragment/LuxMeterSettingFragment.java +++ b/app/src/main/java/io/pslab/fragment/LuxMeterSettingFragment.java @@ -8,6 +8,7 @@ import android.support.v7.preference.ListPreference; import android.support.v7.preference.PreferenceFragmentCompat; import android.support.v7.preference.PreferenceManager; +import android.widget.Toast; import io.pslab.R; import io.pslab.others.PSLabPermission; @@ -80,8 +81,13 @@ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, Strin case KEY_UPDATE_PERIOD: try { Integer updatePeriod = Integer.parseInt(updatePeriodPref.getText()); - updatePeriodPref.setSummary(updatePeriod + " ms"); + if (updatePeriod > 1000 || updatePeriod < 100) { + throw new NumberFormatException(); + } else { + updatePeriodPref.setSummary(updatePeriod + " ms"); + } } catch (NumberFormatException e) { + Toast.makeText(getActivity(), getActivity().getResources().getString(R.string.update_period_msg), Toast.LENGTH_SHORT).show(); updatePeriodPref.setSummary("1000 ms"); updatePeriodPref.setText("1000"); SharedPreferences.Editor editor = sharedPref.edit(); @@ -104,8 +110,13 @@ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, Strin case KEY_HIGH_LIMIT: try { Integer highLimit = Integer.parseInt(higLimitPref.getText()); - higLimitPref.setSummary(String.valueOf(highLimit)); + if (highLimit > 10000 || highLimit < 10) { + throw new NumberFormatException(); + } else { + higLimitPref.setSummary(String.valueOf(highLimit) + " Lx"); + } } catch (NumberFormatException e) { + Toast.makeText(getActivity(), getActivity().getResources().getString(R.string.high_limit_msg), Toast.LENGTH_SHORT).show(); higLimitPref.setSummary("2000 Lx"); higLimitPref.setText("2000"); SharedPreferences.Editor editor = sharedPref.edit(); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c3e7876c9..fc741add6 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -926,13 +926,16 @@ Include the location data in the logged file include_location_sensor_data Include Location Data - Please provide time interval(in ms) at which data will be updated + Please provide time interval at which data will be updated (100 ms to 1000 ms) + Please provide time interval at which data will be updated (100 ms to 2000 ms) setting_baro_update_period setting_lux_update_period - 1.1 + 1.10 1 Please provide maximum limit of atm value to be recorded - Please provide maximum limit of Lux value to be recorded + Please provide maximum limit of Lux value to be recorded (10 Lx to 10000 Lx) + Entered Update Period is not within the limits! + Entered High Limit is not within the limits! setting_baro_high_limit setting_lux_high_limit setting_lux_sensor_type diff --git a/app/src/main/res/xml/baro_meter_settings.xml b/app/src/main/res/xml/baro_meter_settings.xml index c49e74960..e0ce611ef 100644 --- a/app/src/main/res/xml/baro_meter_settings.xml +++ b/app/src/main/res/xml/baro_meter_settings.xml @@ -3,7 +3,7 @@ xmlns:app="http://schemas.android.com/apk/res-auto"> Date: Sat, 11 May 2019 19:36:48 +0530 Subject: [PATCH 03/22] WIP: Playback data from SD card feature added (#1691) * Playback data from SD card feature added * code refrmated * minor changes --- .../io/pslab/activity/DataLoggerActivity.java | 146 +++++++++++++++++- .../import_log_device_type_alert_layout.xml | 33 ++++ .../res/menu/activity_data_logger_menu.xml | 8 + app/src/main/res/values/strings.xml | 6 +- 4 files changed, 191 insertions(+), 2 deletions(-) create mode 100644 app/src/main/res/layout/import_log_device_type_alert_layout.xml create mode 100644 app/src/main/res/menu/activity_data_logger_menu.xml diff --git a/app/src/main/java/io/pslab/activity/DataLoggerActivity.java b/app/src/main/java/io/pslab/activity/DataLoggerActivity.java index 1ba7ffa42..7c3144d17 100644 --- a/app/src/main/java/io/pslab/activity/DataLoggerActivity.java +++ b/app/src/main/java/io/pslab/activity/DataLoggerActivity.java @@ -1,21 +1,40 @@ package io.pslab.activity; +import android.content.DialogInterface; +import android.content.Intent; +import android.net.Uri; import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.DividerItemDecoration; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.Toolbar; +import android.view.LayoutInflater; +import android.view.Menu; import android.view.MenuItem; import android.view.View; +import android.widget.RadioButton; +import android.widget.RadioGroup; import android.widget.TextView; +import android.widget.Toast; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; import butterknife.BindView; import butterknife.ButterKnife; import io.pslab.R; import io.pslab.adapters.SensorLoggerListAdapter; +import io.pslab.models.BaroData; +import io.pslab.models.LuxData; import io.pslab.models.SensorDataBlock; import io.pslab.others.LocalDataLog; +import io.realm.Realm; import io.realm.RealmResults; /** @@ -34,12 +53,17 @@ public class DataLoggerActivity extends AppCompatActivity { @BindView(R.id.toolbar) Toolbar toolbar; + private String selectedDevice = null; + private Realm realm; + private RealmResults categoryData; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_data_logger); ButterKnife.bind(this); setSupportActionBar(toolbar); + realm = LocalDataLog.with().getRealm(); String caller = getIntent().getStringExtra(CALLER_ACTIVITY); if (getSupportActionBar() != null) { getSupportActionBar().setDisplayHomeAsUpEnabled(true); @@ -47,7 +71,6 @@ protected void onCreate(Bundle savedInstanceState) { } if (caller == null) caller = ""; - RealmResults categoryData; switch (caller) { case "Lux Meter": @@ -66,7 +89,10 @@ protected void onCreate(Bundle savedInstanceState) { categoryData = LocalDataLog.with().getAllSensorBlocks(); getSupportActionBar().setTitle(getString(R.string.logged_data)); } + fillData(); + } + private void fillData() { if (categoryData.size() > 0) { blankView.setVisibility(View.GONE); SensorLoggerListAdapter adapter = new SensorLoggerListAdapter(categoryData, this); @@ -94,7 +120,125 @@ public boolean onOptionsItemSelected(MenuItem item) { case android.R.id.home: finish(); return true; + case R.id.action_import_log: + importLog(); } return super.onOptionsItemSelected(item); } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.activity_data_logger_menu, menu); + return true; + } + + private void importLog() { + AlertDialog alertDialog; + AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this); + LayoutInflater inflater = this.getLayoutInflater(); + final View dialogView = inflater.inflate(R.layout.import_log_device_type_alert_layout, null); + dialogBuilder.setView(dialogView); + dialogBuilder.setPositiveButton(getResources().getString(R.string.import_log_positive_button), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + RadioGroup importLogRadioGroup = dialogView.findViewById(R.id.import_log_device_radio_group); + try { + RadioButton selectedRadioButton = dialogView.findViewById(importLogRadioGroup.getCheckedRadioButtonId()); + selectedDevice = selectedRadioButton.getText().toString(); + selectFile(); + } catch (Exception e) { + Toast.makeText(DataLoggerActivity.this, getResources().getString(R.string.import_data_log_no_selection_error), Toast.LENGTH_SHORT).show(); + } + } + }); + alertDialog = dialogBuilder.create(); + alertDialog.show(); + } + + private void selectFile() { + Intent intent = new Intent(Intent.ACTION_GET_CONTENT); + intent.setType("*/*"); + startActivityForResult(intent, 100); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + if (requestCode == 100) { + Uri uri = data.getData(); + String path = uri.getPath(); + path = path.replace("/root_path/", "/"); + File file = new File(path); + getFileData(file); + } + } + + private void getFileData(File file) { + if (selectedDevice != null && selectedDevice.equals(getResources().getString(R.string.baro_meter))) { + try { + FileInputStream is = new FileInputStream(file); + BufferedReader reader = new BufferedReader(new InputStreamReader(is)); + String line = reader.readLine(); + int i = 0; + long block = 0, time = 0; + while (line != null) { + if (i != 0) { + String[] data = line.split(","); + try { + time += 1000; + BaroData baroData = new BaroData(time, block, Float.valueOf(data[2]), Double.valueOf(data[3]), Double.valueOf(data[4])); + realm.beginTransaction(); + realm.copyToRealm(baroData); + realm.commitTransaction(); + } catch (Exception e) { + Toast.makeText(this, getResources().getString(R.string.incorrect_import_format), Toast.LENGTH_SHORT).show(); + } + } else { + block = System.currentTimeMillis(); + time = block; + realm.beginTransaction(); + realm.copyToRealm(new SensorDataBlock(block, getResources().getString(R.string.baro_meter))); + realm.commitTransaction(); + } + i++; + line = reader.readLine(); + } + fillData(); + } catch (IOException e) { + e.printStackTrace(); + } + } else if (selectedDevice != null && selectedDevice.equals(getResources().getString(R.string.lux_meter))) { + try { + FileInputStream is = new FileInputStream(file); + BufferedReader reader = new BufferedReader(new InputStreamReader(is)); + String line = reader.readLine(); + int i = 0; + long block = 0, time = 0; + while (line != null) { + if (i != 0) { + String[] data = line.split(","); + try { + time += 1000; + LuxData luxData = new LuxData(time, block, Float.valueOf(data[2]), Double.valueOf(data[3]), Double.valueOf(data[4])); + realm.beginTransaction(); + realm.copyToRealm(luxData); + realm.commitTransaction(); + } catch (Exception e) { + Toast.makeText(this, getResources().getString(R.string.incorrect_import_format), Toast.LENGTH_SHORT).show(); + } + } else { + block = System.currentTimeMillis(); + time = block; + realm.beginTransaction(); + realm.copyToRealm(new SensorDataBlock(block, getResources().getString(R.string.lux_meter))); + realm.commitTransaction(); + } + i++; + line = reader.readLine(); + } + fillData(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } } diff --git a/app/src/main/res/layout/import_log_device_type_alert_layout.xml b/app/src/main/res/layout/import_log_device_type_alert_layout.xml new file mode 100644 index 000000000..9eb0a2028 --- /dev/null +++ b/app/src/main/res/layout/import_log_device_type_alert_layout.xml @@ -0,0 +1,33 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/activity_data_logger_menu.xml b/app/src/main/res/menu/activity_data_logger_menu.xml new file mode 100644 index 000000000..d7a256af5 --- /dev/null +++ b/app/src/main/res/menu/activity_data_logger_menu.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index fc741add6..4309a42a7 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -968,6 +968,11 @@ Pause Recording View Map + File format does not match device log format + Import Log + Kindly select one of the devices + Select + Data recording started with location Data recording started but GPS is off Recorded data will not contain location @@ -1109,5 +1114,4 @@ No Data Fetched Recorder Save Graph - From f5689472e3b6752c79138e9e4e3e0122f1796a69 Mon Sep 17 00:00:00 2001 From: Neel Trivedi Date: Sat, 11 May 2019 19:38:34 +0530 Subject: [PATCH 04/22] show logged data in barometer activty shows only barometer data (#1700) --- app/src/main/java/io/pslab/activity/DataLoggerActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/io/pslab/activity/DataLoggerActivity.java b/app/src/main/java/io/pslab/activity/DataLoggerActivity.java index 7c3144d17..7394c5017 100644 --- a/app/src/main/java/io/pslab/activity/DataLoggerActivity.java +++ b/app/src/main/java/io/pslab/activity/DataLoggerActivity.java @@ -77,7 +77,7 @@ protected void onCreate(Bundle savedInstanceState) { getSupportActionBar().setTitle(caller); categoryData = LocalDataLog.with().getTypeOfSensorBlocks(getString(R.string.lux_meter)); break; - case "Baro Meter": + case "Barometer": getSupportActionBar().setTitle(caller); categoryData = LocalDataLog.with().getTypeOfSensorBlocks(getString(R.string.baro_meter)); break; From 7477f3fe3ca7bc4c412b87612e401fb8f513111f Mon Sep 17 00:00:00 2001 From: Kunal Rai Date: Sat, 11 May 2019 19:44:19 +0530 Subject: [PATCH 05/22] Stopped repeated calling of Sensor manager (#1637) --- .../io/pslab/activity/CompassActivity.java | 20 +++++++++++++++---- app/src/main/res/values/strings.xml | 1 + 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/io/pslab/activity/CompassActivity.java b/app/src/main/java/io/pslab/activity/CompassActivity.java index 3359b2a96..a15cc092c 100644 --- a/app/src/main/java/io/pslab/activity/CompassActivity.java +++ b/app/src/main/java/io/pslab/activity/CompassActivity.java @@ -28,6 +28,7 @@ import android.widget.LinearLayout; import android.widget.RadioButton; import android.widget.TextView; +import android.widget.Toast; import java.util.Date; @@ -110,11 +111,15 @@ protected void onCreate(Bundle savedInstanceState) { setSupportActionBar(mToolbar); ActionBar actionBar = getSupportActionBar(); actionBar.setDisplayHomeAsUpEnabled(true); + mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE); + if((mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD))==null){ + Toast.makeText(this, R.string.Toast_magnetic_not_present, Toast.LENGTH_SHORT).show(); + } compassPreference = getSharedPreferences(PREFS_NAME, MODE_PRIVATE); setUpBottomSheet(); - mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE); + xAxisRadioButton.setChecked(true); direction = 0; @@ -162,14 +167,21 @@ public void onClick(View v) { protected void onResume() { super.onResume(); - mSensorManager.registerListener(this, mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION), SensorManager.SENSOR_DELAY_GAME); + if((mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD))==null){ + Toast.makeText(this, R.string.Toast_magnetic_not_present, Toast.LENGTH_SHORT).show(); + }else { + mSensorManager.registerListener(this, mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION), SensorManager.SENSOR_DELAY_GAME); + } } @Override protected void onPause() { super.onPause(); - - mSensorManager.unregisterListener(this); + if((mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD))==null){ + Toast.makeText(this, R.string.Toast_magnetic_not_present, Toast.LENGTH_SHORT).show(); + }else { + mSensorManager.unregisterListener(this); + } } @Override diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 4309a42a7..bff6cb503 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -6,6 +6,7 @@ close_drawer Press again to close PSLab + "The sensor required for this instrument is not present in your device" Device Instruments From ace8d8d3183acf19910b0658aeb45b7a0a324433 Mon Sep 17 00:00:00 2001 From: Kunal Rai Date: Sat, 11 May 2019 19:49:15 +0530 Subject: [PATCH 06/22] Recording added to power source (#1666) --- .../pslab/activity/PowerSourceActivity.java | 53 ++++++++++++++++++- .../java/io/pslab/models/PowerSourceData.java | 46 ++++++++++++++++ .../main/res/layout/activity_power_source.xml | 1 + app/src/main/res/menu/power_source_menu.xml | 6 +++ app/src/main/res/values/strings.xml | 1 + 5 files changed, 105 insertions(+), 2 deletions(-) create mode 100644 app/src/main/java/io/pslab/models/PowerSourceData.java diff --git a/app/src/main/java/io/pslab/activity/PowerSourceActivity.java b/app/src/main/java/io/pslab/activity/PowerSourceActivity.java index 779987d7b..f181a2f23 100644 --- a/app/src/main/java/io/pslab/activity/PowerSourceActivity.java +++ b/app/src/main/java/io/pslab/activity/PowerSourceActivity.java @@ -1,11 +1,15 @@ package io.pslab.activity; import android.annotation.SuppressLint; +import android.app.AlertDialog; +import android.content.DialogInterface; import android.content.SharedPreferences; import android.os.Bundle; import android.os.Handler; import android.support.annotation.NonNull; import android.support.design.widget.BottomSheetBehavior; +import android.support.design.widget.CoordinatorLayout; +import android.support.design.widget.Snackbar; import android.support.v4.widget.TextViewCompat; import android.support.v7.app.ActionBar; import android.support.v7.app.AppCompatActivity; @@ -23,6 +27,7 @@ import com.sdsmdg.harjot.crollerTest.Croller; import com.sdsmdg.harjot.crollerTest.OnCrollerChangeListener; +import java.util.Date; import java.util.Locale; import java.util.Timer; import java.util.TimerTask; @@ -32,6 +37,9 @@ import io.pslab.R; import io.pslab.communication.ScienceLab; import io.pslab.items.SquareImageButton; +import io.pslab.models.PowerSourceData; +import io.pslab.others.CSVLogger; +import io.pslab.others.CustomSnackBar; import io.pslab.others.MathUtils; import io.pslab.others.ScienceLabCommon; import io.pslab.others.SwipeGestureDetector; @@ -47,6 +55,8 @@ public class PowerSourceActivity extends AppCompatActivity { private final int PCS_CONTROLLER_MAX = 331; private final long LONG_CLICK_DELAY = 100; + private CSVLogger compassLogger = null; + private Boolean writeHeaderToFile = true; @BindView(R.id.toolbar) Toolbar toolbar; @@ -60,6 +70,9 @@ public class PowerSourceActivity extends AppCompatActivity { @BindView(R.id.power_card_pv1_down) SquareImageButton downPV1; + @BindView(R.id.power_source_coordinatorLayout) + CoordinatorLayout coordinatorLayout; + @BindView(R.id.power_card_pv2_controller) Croller controllerPV2; @BindView(R.id.power_card_pv2_display) @@ -103,7 +116,7 @@ public class PowerSourceActivity extends AppCompatActivity { ImageView bottomSheetSchematic; @BindView(R.id.custom_dialog_desc) TextView bottomSheetDesc; - + private PowerSourceData powerSourceData; BottomSheetBehavior bottomSheetBehavior; GestureDetector gestureDetector; private SharedPreferences powerPreferences; @@ -127,7 +140,7 @@ protected void onCreate(Bundle savedInstanceState) { setSupportActionBar(toolbar); ActionBar actionBar = getSupportActionBar(); actionBar.setDisplayHomeAsUpEnabled(true); - + powerSourceData = new PowerSourceData(); powerPreferences = getSharedPreferences(POWER_PREFERENCES, MODE_PRIVATE); setUpBottomSheet(); @@ -265,6 +278,17 @@ public boolean onOptionsItemSelected(MenuItem item) { bottomSheetBehavior.setState(bottomSheetBehavior.getState() == BottomSheetBehavior.STATE_HIDDEN ? BottomSheetBehavior.STATE_EXPANDED : BottomSheetBehavior.STATE_HIDDEN); break; + case R.id.power_source_record_data: + if (writeHeaderToFile) { + compassLogger = new CSVLogger(getString(R.string.compass)); + compassLogger.prepareLogFile(); + compassLogger.writeCSVFile("Timestamp,DateTime,Bx,By,Bz"); + recordData(); + writeHeaderToFile = !writeHeaderToFile; + } else { + recordData(); + } + break; case android.R.id.home: this.finish(); break; @@ -680,6 +704,31 @@ public void run() { powerCounter.schedule(task, 1, LONG_CLICK_DELAY); } + private void recordData() { + String dateTime = CSVLogger.FILE_NAME_FORMAT.format(new Date(System.currentTimeMillis())); + compassLogger.writeCSVFile(System.currentTimeMillis() + "," + dateTime + "," + powerSourceData.getPv1() + + "," + powerSourceData.getPv2() + "," + powerSourceData.getPv3() + "," + powerSourceData.getPcs()); + CustomSnackBar.showSnackBar(coordinatorLayout, + getString(R.string.csv_store_text) + " " + compassLogger.getCurrentFilePath() + , getString(R.string.delete_capital), new View.OnClickListener() { + @Override + public void onClick(View view) { + new AlertDialog.Builder(PowerSourceActivity.this, R.style.AlertDialogStyle) + .setTitle(R.string.delete_file) + .setMessage(R.string.delete_warning) + .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + compassLogger.deleteFile(); + } + }) + .setNegativeButton(R.string.cancel, null) + .create() + .show(); + } + }, Snackbar.LENGTH_LONG); + } + private enum Pin { PV1, PV2, PV3, PCS } diff --git a/app/src/main/java/io/pslab/models/PowerSourceData.java b/app/src/main/java/io/pslab/models/PowerSourceData.java new file mode 100644 index 000000000..1e322977d --- /dev/null +++ b/app/src/main/java/io/pslab/models/PowerSourceData.java @@ -0,0 +1,46 @@ +package io.pslab.models; + +public class PowerSourceData { + + private String pv1; + private String pv2; + private String pv3; + private String pcs; + + public PowerSourceData() {/**/} + + public PowerSourceData(String pv1, String pv2, String pv3,String pcs) { + this.pv1 = pv1; + this.pv2 = pv2; + this.pv3 = pv3; + this.pcs = pcs; + } + + public String getPv1() { + return pv1; + } + public void setPv1(String pv1) { + this.pv1 = pv1; + } + public String getPv2() { + return pv2; + } + public void setPv2(String pv2) { + this.pv2 = pv2; + } + public String getPv3() { + return pv3; + } + public void setPv3(String pv3) { + this.pv3 = pv3; + } + public String getPcs() { + return pcs; + } + public void setPcs(String pcs) { + this.pcs = pcs; + } + + + +} diff --git a/app/src/main/res/layout/activity_power_source.xml b/app/src/main/res/layout/activity_power_source.xml index 7e1e9c2f9..1ee06689d 100644 --- a/app/src/main/res/layout/activity_power_source.xml +++ b/app/src/main/res/layout/activity_power_source.xml @@ -3,6 +3,7 @@ xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" + android:id="@+id/power_source_coordinatorLayout" android:fitsSystemWindows="true"> + + Sensors Power Source Coming Soon! + Record current data setting_auto_start Auto start app when PSLab device is connected From 4ba5ee9391e601ec00c23e7ce5359e73ff574e5f Mon Sep 17 00:00:00 2001 From: Kunal Rai Date: Sat, 11 May 2019 19:53:30 +0530 Subject: [PATCH 07/22] Accelerometer crash on record fixed (#1541) --- app/src/main/AndroidManifest.xml | 3 +- .../pslab/activity/AccelerometerActivity.java | 393 ++------ .../io/pslab/activity/DataLoggerActivity.java | 6 +- .../activity/SensorDataLoggerActivity.java | 8 - .../io/pslab/activity/SettingsActivity.java | 3 + .../pslab/adapters/AccelerometerAdapter.java | 232 ----- .../adapters/SensorLoggerListAdapter.java | 32 +- .../fragment/AccelerometerDataFragment.java | 897 ++++++++++++++++++ .../AccelerometerSettingsFragment.java | 123 +++ .../AccelerometerRecordables.java | 17 + .../io/pslab/models/AccelerometerData.java | 92 ++ .../java/io/pslab/models/PSLabSensor.java | 24 +- .../java/io/pslab/others/LocalDataLog.java | 39 +- .../layout/fragment_accelerometer_data.xml | 445 +++++++++ .../fragment_accelerometer_settings.xml | 13 + app/src/main/res/layout/sensor_main.xml | 6 +- .../res/menu/accelerometer_data_log_menu.xml | 22 + .../main/res/menu/sensor_data_log_menu.xml | 9 +- 18 files changed, 1803 insertions(+), 561 deletions(-) delete mode 100644 app/src/main/java/io/pslab/adapters/AccelerometerAdapter.java create mode 100644 app/src/main/java/io/pslab/fragment/AccelerometerDataFragment.java create mode 100644 app/src/main/java/io/pslab/fragment/AccelerometerSettingsFragment.java create mode 100644 app/src/main/java/io/pslab/interfaces/sensorloggers/AccelerometerRecordables.java create mode 100644 app/src/main/java/io/pslab/models/AccelerometerData.java create mode 100644 app/src/main/res/layout/fragment_accelerometer_data.xml create mode 100644 app/src/main/res/layout/fragment_accelerometer_settings.xml create mode 100644 app/src/main/res/menu/accelerometer_data_log_menu.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 3aa9d4fcc..eaa3fed9c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -71,7 +71,8 @@ - + recordedAccelerometerData; -import butterknife.BindView; -import butterknife.ButterKnife; -import io.pslab.R; -import io.pslab.adapters.AccelerometerAdapter; -import io.pslab.others.CSVLogger; -import io.pslab.others.CustomSnackBar; -import io.pslab.others.GPSLogger; -import io.pslab.others.MathUtils; -import io.pslab.others.SwipeGestureDetector; + @Override + public int getMenu() { + return R.menu.sensor_data_log_menu; + } -public class AccelerometerActivity extends AppCompatActivity { + @Override + public SharedPreferences getStateSettings() { + return this.getSharedPreferences(PREF_NAME, MODE_PRIVATE); + } - private static final String PREF_NAME = "AccelerometerPreferences"; + @Override + public String getFirstTimeSettingID() { + return "AccelerometerFirstTime"; + } - private static final int MY_PERMISSIONS_REQUEST_STORAGE_FOR_DATA = 101; - private static final int MY_PERMISSIONS_REQUEST_STORAGE_FOR_MAPS = 102; + @Override + public String getSensorName() { + return getResources().getString(R.string.accelerometer); + } - public boolean recordData = false; - public boolean locationPref; - public GPSLogger gpsLogger; - public CSVLogger accLogger; - AccelerometerAdapter adapter; - BottomSheetBehavior bottomSheetBehavior; - GestureDetector gestureDetector; - @BindView(R.id.accel_toolbar) - Toolbar mToolbar; - @BindView(R.id.accel_coordinator_layout) - CoordinatorLayout coordinatorLayout; - @BindView(R.id.bottom_sheet) - LinearLayout bottomSheet; - @BindView(R.id.shadow) - View tvShadow; - @BindView(R.id.img_arrow) - ImageView arrowUpDown; - @BindView(R.id.sheet_slide_text) - TextView bottomSheetSlideText; - @BindView(R.id.guide_title) - TextView bottomSheetGuideTitle; - @BindView(R.id.custom_dialog_text) - TextView bottomSheetText; - @BindView(R.id.custom_dialog_schematic) - ImageView bottomSheetSchematic; - @BindView(R.id.custom_dialog_desc) - TextView bottomSheetDesc; - private boolean checkGpsOnResume = false; - private boolean isRecordingStarted = false; - private boolean isDataRecorded = false; - private Menu menu; + @Override + public int getGuideTitle() { + return R.string.accelerometer; + } @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_accelerometer_main); - ButterKnife.bind(this); - setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); + public int getGuideAbstract() { + return R.string.accelerometer_intro; + } - setUpBottomSheet(); - tvShadow.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - if (bottomSheetBehavior.getState() == BottomSheetBehavior.STATE_EXPANDED) - bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN); - tvShadow.setVisibility(View.GONE); - } - }); - setSupportActionBar(mToolbar); - ActionBar actionBar = getSupportActionBar(); - actionBar.setDisplayHomeAsUpEnabled(true); - adapter = new AccelerometerAdapter(new String[]{"X axis", "Y axis", "Z axis"}, getApplicationContext()); - RecyclerView recyclerView = this.findViewById(R.id.accelerometer_recycler_view); - LinearLayoutManager layoutManager = new LinearLayoutManager(this); - recyclerView.setLayoutManager(layoutManager); - recyclerView.setAdapter(adapter); + @Override + public int getGuideSchematics() { + return R.drawable.bh1750_schematic; } @Override - public boolean onCreateOptionsMenu(Menu menu) { - MenuInflater inflater = getMenuInflater(); - inflater.inflate(R.menu.data_log_menu, menu); - this.menu = menu; - return true; + public int getGuideDescription() { + return R.string.accelerometer_description_text; } @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case R.id.record_pause_data: - if (ContextCompat.checkSelfPermission(this, - Manifest.permission.WRITE_EXTERNAL_STORAGE) - != PackageManager.PERMISSION_GRANTED) { - ActivityCompat.requestPermissions(this, - new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, MY_PERMISSIONS_REQUEST_STORAGE_FOR_DATA); - return true; - } - if (recordData) { - item.setIcon(R.drawable.ic_record_white); - adapter.setRecordingStatus(false); - recordData = false; - CustomSnackBar.showSnackBar(coordinatorLayout, getString(R.string.data_recording_paused), null, null, Snackbar.LENGTH_LONG); - } else { - isDataRecorded = true; - item.setIcon(R.drawable.pause_icon); - adapter.setRecordingStatus(true); - if (!isRecordingStarted) { - accLogger = new CSVLogger(getString(R.string.accelerometer)); - accLogger.writeCSVFile("Timestamp,X,Y,Z\n"); - isRecordingStarted = true; - recordData = true; - } - if (locationPref) { - gpsLogger = new GPSLogger(this, (LocationManager) getSystemService(Context.LOCATION_SERVICE)); - if (gpsLogger.isGPSEnabled()) { - recordData = true; - CustomSnackBar.showSnackBar(coordinatorLayout, getString(R.string.data_recording_start) + "\n" + getString(R.string.location_enabled), null, null, Snackbar.LENGTH_LONG); - } else { - checkGpsOnResume = true; - } - gpsLogger.startCaptureLocation(); - } else { - recordData = true; - CustomSnackBar.showSnackBar(coordinatorLayout, getString(R.string.data_recording_start) + "\n" + getString(R.string.location_disabled), null, null, Snackbar.LENGTH_LONG); - } - } - break; - case R.id.record_csv_data: - if (isDataRecorded) { - MenuItem item1 = menu.findItem(R.id.record_pause_data); - item1.setIcon(R.drawable.ic_record_white); - - // Export Data - ArrayList dataX = adapter.getEntries(0); - ArrayList dataY = adapter.getEntries(1); - ArrayList dataZ = adapter.getEntries(2); - int length = Math.min(Math.min(dataX.size(), dataY.size()), dataZ.size()); - for (int i = 0; i < length; i++) { - accLogger.writeCSVFile(dataX.get(i).getX() + "," + dataX.get(i).getY() + "," - + dataY.get(i).getY() + "," + dataZ.get(i).getY() + "\n"); - } - if (locationPref && gpsLogger != null) { - String data; - Location location = gpsLogger.getDeviceLocation(); - if (location != null) { - data = "\nLocation" + "," + String.valueOf(location.getLatitude()) + "," + String.valueOf(location.getLongitude() + "\n"); - } else { - data = "\nLocation" + "," + "null" + "," + "null"; - } - accLogger.writeCSVFile(data); - gpsLogger.removeUpdate(); - } - CustomSnackBar.showSnackBar(coordinatorLayout, - getString(R.string.csv_store_text) + " " + accLogger.getCurrentFilePath() - , getString(R.string.delete_capital), new View.OnClickListener() { - @Override - public void onClick(View view) { - new AlertDialog.Builder(AccelerometerActivity.this, R.style.AlertDialogStyle) - .setTitle(R.string.delete_file) - .setMessage(R.string.delete_warning) - .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - accLogger.deleteFile(); - } - }) - .setNegativeButton(R.string.cancel, null) - .create() - .show(); - } - }, Snackbar.LENGTH_LONG); - adapter.setRecordingStatus(false); - isRecordingStarted = false; - recordData = false; - } else { - CustomSnackBar.showSnackBar(coordinatorLayout, getString(R.string.nothing_to_export), null, null, Snackbar.LENGTH_LONG); - } - break; - case R.id.delete_csv_data: - if (isDataRecorded) { - MenuItem item1 = menu.findItem(R.id.record_pause_data); - item1.setIcon(R.drawable.ic_record_white); - adapter.setRecordingStatus(false); - recordData = false; - isRecordingStarted = false; - isDataRecorded = false; - accLogger.deleteFile(); - CustomSnackBar.showSnackBar(coordinatorLayout, getString(R.string.data_deleted), null, null, Snackbar.LENGTH_LONG); - } else - CustomSnackBar.showSnackBar(coordinatorLayout, getString(R.string.nothing_to_delete), null, null, Snackbar.LENGTH_LONG); - break; - case R.id.show_map: - if (ContextCompat.checkSelfPermission(this, - Manifest.permission.WRITE_EXTERNAL_STORAGE) - != PackageManager.PERMISSION_GRANTED) { - ActivityCompat.requestPermissions(this, - new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, MY_PERMISSIONS_REQUEST_STORAGE_FOR_MAPS); - return true; - } - Intent MAP = new Intent(getApplicationContext(), MapsActivity.class); - startActivity(MAP); - break; - case R.id.settings: - Intent settingIntent = new Intent(this, SettingsActivity.class); - settingIntent.putExtra("title", getResources().getString(R.string.accelerometer_configurations)); - startActivity(settingIntent); - break; - case android.R.id.home: - this.finish(); - break; - case R.id.show_guide: - bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED); - default: - break; - } - return true; + public int getGuideExtraContent() { + return 0; } @Override - protected void onDestroy() { - super.onDestroy(); - if (isRecordingStarted) { - accLogger.deleteFile(); - isRecordingStarted = false; - } + public void recordSensorDataBlockID(SensorDataBlock categoryData) { + realm.beginTransaction(); + realm.copyToRealm(categoryData); + realm.commitTransaction(); } - private void setUpBottomSheet() { - bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet); + @Override + public void recordSensorData(RealmObject sensorData) { + realm.beginTransaction(); + realm.copyToRealm((AccelerometerData) sensorData); + realm.commitTransaction(); + } - final SharedPreferences settings = this.getSharedPreferences(PREF_NAME, MODE_PRIVATE); - Boolean isFirstTime = settings.getBoolean("AccelerometerFirstTime", true); + @Override + public void stopRecordSensorData() { + LocalDataLog.with().refresh(); + } - bottomSheetGuideTitle.setText(R.string.accelerometer); - bottomSheetText.setText(R.string.accelerometer_intro); - bottomSheetSchematic.setImageResource(R.drawable.find_mobile_axis); - bottomSheetDesc.setText(R.string.accelerometer_description_text); + @Override + public Fragment getSensorFragment() { + return AccelerometerDataFragment.newInstance(); + } - if (isFirstTime) { - bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED); - tvShadow.setVisibility(View.VISIBLE); - tvShadow.setAlpha(0.8f); - arrowUpDown.setRotation(180); - bottomSheetSlideText.setText(R.string.hide_guide_text); - SharedPreferences.Editor editor = settings.edit(); - editor.putBoolean("AccelerometerFirstTime", false); - editor.apply(); - } else { - bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN); + @Override + public void getDataFromDataLogger() { + if (getIntent().getExtras() != null && getIntent().getExtras().getBoolean(KEY_LOG)) { + //playingData = true; + viewingData = true; + recordedAccelerometerData = LocalDataLog.with() + .getBlockOfAccelerometerRecords(getIntent().getExtras().getLong(DATA_BLOCK)); + String title = titleFormat.format(recordedAccelerometerData.get(0).getTime()); + getSupportActionBar().setTitle(title); } + } - bottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() { - private Handler handler = new Handler(); - private Runnable runnable = new Runnable() { - @Override - public void run() { - bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN); - } - }; - - @Override - public void onStateChanged(@NonNull final View bottomSheet, int newState) { - switch (newState) { - case BottomSheetBehavior.STATE_EXPANDED: - handler.removeCallbacks(runnable); - bottomSheetSlideText.setText(R.string.hide_guide_text); - break; - - case BottomSheetBehavior.STATE_COLLAPSED: - handler.postDelayed(runnable, 2000); - break; + /** + * Once settings have been changed, those changes can be captured from onResume method. + */ + @Override + protected void onResume() { + super.onResume(); + reinstateConfigurations(); + } - default: - handler.removeCallbacks(runnable); - bottomSheetSlideText.setText(R.string.show_guide_text); - break; - } - } + private void reinstateConfigurations() { + SharedPreferences accelerometerConfigurations; + accelerometerConfigurations = PreferenceManager.getDefaultSharedPreferences(getBaseContext()); + locationEnabled = accelerometerConfigurations.getBoolean(AccelerometerSettingsFragment.KEY_INCLUDE_LOCATION, true); + AccelerometerDataFragment.setParameters( + getValueFromText(accelerometerConfigurations.getString(AccelerometerSettingsFragment.KEY_HIGH_LIMIT, "2000"), + 10, 10000), + getValueFromText(accelerometerConfigurations.getString(AccelerometerSettingsFragment.KEY_UPDATE_PERIOD, "1000"), + 100, 1000), + accelerometerConfigurations.getString(AccelerometerSettingsFragment.KEY_ACCELEROMETER_SENSOR_TYPE, "0"), + accelerometerConfigurations.getString(AccelerometerSettingsFragment.KEY_ACCELEROMETER_SENSOR_GAIN, "1")); + } - @Override - public void onSlide(@NonNull View bottomSheet, float slideOffset) { - Float value = (float) MathUtils.map((double) slideOffset, 0.0, 1.0, 0.0, 0.8); - tvShadow.setVisibility(View.VISIBLE); - tvShadow.setAlpha(value); - arrowUpDown.setRotation(slideOffset * 180); - } - }); - gestureDetector = new GestureDetector(this, new SwipeGestureDetector(bottomSheetBehavior)); + private int getValueFromText(String strValue, int lowerBound, int upperBound) { + if (strValue.isEmpty()) return lowerBound; + int value = Integer.parseInt(strValue); + if (value > upperBound) return upperBound; + else if (value < lowerBound) return lowerBound; + else return value; } -} +} \ No newline at end of file diff --git a/app/src/main/java/io/pslab/activity/DataLoggerActivity.java b/app/src/main/java/io/pslab/activity/DataLoggerActivity.java index 7394c5017..6c416ff46 100644 --- a/app/src/main/java/io/pslab/activity/DataLoggerActivity.java +++ b/app/src/main/java/io/pslab/activity/DataLoggerActivity.java @@ -49,7 +49,6 @@ public class DataLoggerActivity extends AppCompatActivity { RecyclerView recyclerView; @BindView(R.id.data_logger_blank_view) TextView blankView; - @BindView(R.id.toolbar) Toolbar toolbar; @@ -81,6 +80,10 @@ protected void onCreate(Bundle savedInstanceState) { getSupportActionBar().setTitle(caller); categoryData = LocalDataLog.with().getTypeOfSensorBlocks(getString(R.string.baro_meter)); break; + case "Accelerometer": + getSupportActionBar().setTitle(caller); + categoryData = LocalDataLog.with().getTypeOfSensorBlocks(getString(R.string.accelerometer)); + break; case "Multimeter": getSupportActionBar().setTitle(caller); categoryData = LocalDataLog.with().getTypeOfSensorBlocks(getString(R.string.multimeter)); @@ -99,7 +102,6 @@ private void fillData() { LinearLayoutManager linearLayoutManager = new LinearLayoutManager( this, LinearLayoutManager.VERTICAL, false); recyclerView.setLayoutManager(linearLayoutManager); - DividerItemDecoration itemDecor = new DividerItemDecoration(this, DividerItemDecoration.HORIZONTAL); recyclerView.addItemDecoration(itemDecor); recyclerView.setAdapter(adapter); diff --git a/app/src/main/java/io/pslab/activity/SensorDataLoggerActivity.java b/app/src/main/java/io/pslab/activity/SensorDataLoggerActivity.java index 13254331d..2462d1387 100644 --- a/app/src/main/java/io/pslab/activity/SensorDataLoggerActivity.java +++ b/app/src/main/java/io/pslab/activity/SensorDataLoggerActivity.java @@ -237,13 +237,6 @@ public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) realm.commitTransaction(); Toast.makeText(SensorDataLoggerActivity.this, "Data Logged Successfully", Toast.LENGTH_SHORT).show(); dialog.dismiss(); - /* - Log.v("Realm Transaction", "Successful"); - RealmResults results = realm.where(DataMPU6050.class).findAll(); - for (int i = 0; i < results.size(); i++) { - Log.v("Realm Saved Data ", results.get(i).toString()); - } - */ } }) .autoDismiss(false) @@ -300,7 +293,6 @@ protected void onPostExecute(Void aVoid) { } } - @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { if (requestCode == WRITE_EXTERNAL_STORAGE_REQUEST) { diff --git a/app/src/main/java/io/pslab/activity/SettingsActivity.java b/app/src/main/java/io/pslab/activity/SettingsActivity.java index c98417858..21b8b6fed 100644 --- a/app/src/main/java/io/pslab/activity/SettingsActivity.java +++ b/app/src/main/java/io/pslab/activity/SettingsActivity.java @@ -17,6 +17,7 @@ import butterknife.ButterKnife; import butterknife.Unbinder; import io.pslab.R; +import io.pslab.fragment.AccelerometerSettingsFragment; import io.pslab.fragment.BaroMeterSettingsFragment; import io.pslab.fragment.LuxMeterSettingFragment; import io.pslab.fragment.SettingsFragment; @@ -60,6 +61,8 @@ protected void onCreate(Bundle savedInstanceState) { case PSLabSensor.BAROMETER_CONFIGURATIONS: fragment = new BaroMeterSettingsFragment(); break; + case PSLabSensor.ACCELEROMETER: + fragment = new AccelerometerSettingsFragment(); default: fragment = new SettingsFragment(); break; diff --git a/app/src/main/java/io/pslab/adapters/AccelerometerAdapter.java b/app/src/main/java/io/pslab/adapters/AccelerometerAdapter.java deleted file mode 100644 index 1fe029076..000000000 --- a/app/src/main/java/io/pslab/adapters/AccelerometerAdapter.java +++ /dev/null @@ -1,232 +0,0 @@ -package io.pslab.adapters; - -import android.content.Context; -import android.graphics.Color; -import android.hardware.Sensor; -import android.hardware.SensorEvent; -import android.hardware.SensorEventListener; -import android.hardware.SensorManager; -import android.support.annotation.NonNull; -import android.support.v7.widget.RecyclerView; -import android.text.Html; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageView; -import android.widget.TextView; - -import com.github.mikephil.charting.charts.LineChart; -import com.github.mikephil.charting.components.Legend; -import com.github.mikephil.charting.components.XAxis; -import com.github.mikephil.charting.components.YAxis; -import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.data.LineData; -import com.github.mikephil.charting.data.LineDataSet; - -import io.pslab.R; - -import java.text.DecimalFormat; -import java.util.ArrayList; - -import butterknife.BindView; -import butterknife.ButterKnife; - -import static android.content.Context.SENSOR_SERVICE; - -/** - * Created by Vikum on 6/10/18. - */ - -public class AccelerometerAdapter extends RecyclerView.Adapter { - - private String[] dataset; - private SensorManager sensorManager; - private Sensor accelerometer; - private DecimalFormat df = new DecimalFormat("+#0.0;-#0.0"); - private Context context; - private long startTime; - private int[] colors = {Color.YELLOW, Color.MAGENTA, Color.GREEN}; - private ArrayList xAxis, yAxis, zAxis; - private boolean isRecording = false; - - public AccelerometerAdapter(String[] dataset, Context context) { - this.dataset = dataset; - this.context = context; - } - - @Override - public void onBindViewHolder(@NonNull final ViewHolder holder, final int position) { - holder.setIsRecyclable(true); - holder.entries = new ArrayList<>(); - XAxis x = holder.chart.getXAxis(); - holder.y = holder.chart.getAxisLeft(); - YAxis y2 = holder.chart.getAxisRight(); - - holder.chart.setTouchEnabled(true); - holder.chart.setHighlightPerDragEnabled(true); - holder.chart.setDragEnabled(true); - holder.chart.setScaleEnabled(true); - holder.chart.setDrawGridBackground(false); - holder.chart.setPinchZoom(true); - holder.chart.setScaleYEnabled(false); - holder.chart.setBackgroundColor(Color.BLACK); - holder.chart.getDescription().setEnabled(false); - Legend l = holder.chart.getLegend(); - l.setForm(Legend.LegendForm.LINE); - l.setTextColor(Color.WHITE); - - holder.chart.setData(holder.data); - - x.setTextColor(Color.WHITE); - x.setDrawGridLines(true); - x.setAvoidFirstLastClipping(true); - x.setDrawLabels(false); - - holder.y.setTextColor(Color.WHITE); - holder.y.setAxisMaximum(20); - holder.y.setAxisMinimum(-20); - holder.y.setDrawGridLines(true); - holder.y.setLabelCount(6); - - y2.setDrawGridLines(false); - - holder.previousTimeElapsed = 0; - - sensorManager.registerListener(new SensorEventListener() { - @Override - public void onSensorChanged(SensorEvent event) { - float currentAcc = event.values[holder.getAdapterPosition()]; - StringBuilder builder = new StringBuilder(); - builder.append(df.format(currentAcc)); - builder.append(" "); - builder.append(context.getResources().getString(R.string.meters_per_sec_text)); - holder.value.setText(Html.fromHtml(builder.toString())); - - if (currentAcc > holder.currentMax) { - builder.insert(0, context.getResources().getString(R.string.text_max)); - builder.insert(3, " "); - holder.maxValue.setText(Html.fromHtml(builder.toString())); - holder.currentMax = currentAcc; - } else if (currentAcc < holder.currentMin) { - builder.insert(0, context.getResources().getString(R.string.text_min)); - builder.insert(3, " "); - holder.minValue.setText(Html.fromHtml(builder.toString())); - holder.currentMin = currentAcc; - } - - holder.timeElapsed = (System.currentTimeMillis() - startTime) / 1000; - if (holder.timeElapsed != holder.previousTimeElapsed) { - holder.previousTimeElapsed = holder.timeElapsed; - holder.entries.add(new Entry((float) holder.timeElapsed, currentAcc)); - LineDataSet dataSet = new LineDataSet(holder.entries, dataset[holder.getAdapterPosition()]); - LineData data = new LineData(dataSet); - dataSet.setDrawCircles(false); - dataSet.setDrawValues(false); - dataSet.setMode(LineDataSet.Mode.CUBIC_BEZIER); - dataSet.setLineWidth(1); - dataSet.setColor(colors[holder.getAdapterPosition()]); - - holder.chart.setData(data); - holder.chart.notifyDataSetChanged(); - holder.chart.setVisibleXRangeMaximum(3); - holder.chart.moveViewToX(data.getEntryCount()); - holder.chart.invalidate(); - } - - switch (holder.getAdapterPosition()) { - case 0: - if (isRecording) - xAxis = holder.entries; - break; - case 1: - if (isRecording) - yAxis = holder.entries; - break; - case 2: - if (isRecording) - zAxis = holder.entries; - break; - default: - break; - } - } - - @Override - public void onAccuracyChanged(Sensor sensor, int accuracy) { - //do nothing - } - }, accelerometer, SensorManager.SENSOR_DELAY_NORMAL); - - switch (position) { - case 0: - holder.axisImage.setImageResource(R.drawable.phone_x_axis); - break; - case 1: - holder.axisImage.setImageResource(R.drawable.phone_y_axis); - break; - case 2: - holder.axisImage.setImageResource(R.drawable.phone_z_axis); - break; - default: - break; - } - } - - @NonNull - @Override - public AccelerometerAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.accelerometer_list_item, parent, false); - sensorManager = (SensorManager) parent.getContext().getSystemService(SENSOR_SERVICE); - accelerometer = sensorManager != null ? sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) : null; - startTime = System.currentTimeMillis(); - return new ViewHolder(v); - } - - @Override - public int getItemCount() { - return dataset.length; - } - - public void setRecordingStatus(boolean status) { - this.isRecording = status; - } - - public ArrayList getEntries(int axis) { - switch (axis) { - case 0: - return this.xAxis; - case 1: - return this.yAxis; - case 2: - return this.zAxis; - default: - return this.xAxis; - } - } - - static class ViewHolder extends RecyclerView.ViewHolder { - @BindView(R.id.axis_image) - ImageView axisImage; - @BindView(R.id.accel_value) - TextView value; - @BindView(R.id.accel_max_text) - TextView maxValue; - @BindView(R.id.accel_min_text) - TextView minValue; - @BindView(R.id.chart_accelerometer) - LineChart chart; - - private float currentMax = Integer.MIN_VALUE; - private float currentMin = Integer.MAX_VALUE; - private YAxis y; - private LineData data = new LineData(); - private ArrayList entries; - private long timeElapsed; - private long previousTimeElapsed; - - public ViewHolder(View itemView) { - super(itemView); - ButterKnife.bind(this, itemView); - } - } -} diff --git a/app/src/main/java/io/pslab/adapters/SensorLoggerListAdapter.java b/app/src/main/java/io/pslab/adapters/SensorLoggerListAdapter.java index 03deed2b1..34831f51e 100644 --- a/app/src/main/java/io/pslab/adapters/SensorLoggerListAdapter.java +++ b/app/src/main/java/io/pslab/adapters/SensorLoggerListAdapter.java @@ -23,9 +23,11 @@ import java.util.Date; import io.pslab.R; +import io.pslab.activity.AccelerometerActivity; import io.pslab.activity.BarometerActivity; import io.pslab.activity.LuxMeterActivity; import io.pslab.activity.MapsActivity; +import io.pslab.models.AccelerometerData; import io.pslab.models.BaroData; import io.pslab.models.LuxData; import io.pslab.models.PSLabSensor; @@ -38,7 +40,6 @@ /** * Created by Avjeet on 03-08-2018. */ - public class SensorLoggerListAdapter extends RealmRecyclerViewAdapter { @@ -72,6 +73,10 @@ public void onBindViewHolder(@NonNull final ViewHolder holder, int position) { holder.sensor.setText(context.getResources().getString(R.string.baro_meter)); holder.tileIcon.setImageDrawable(context.getResources().getDrawable(R.drawable.tile_icon_barometer_log)); break; + case PSLabSensor.ACCELEROMETER: + holder.sensor.setText(context.getResources().getString(R.string.accelerometer)); + holder.tileIcon.setImageDrawable(context.getResources().getDrawable(R.drawable.tile_icon_accelerometer)); + break; default: break; } @@ -107,6 +112,11 @@ private void handleCardViewClick(SensorDataBlock block) { BaroMeter.putExtra(KEY_LOG, true); BaroMeter.putExtra(DATA_BLOCK, block.getBlock()); context.startActivity(BaroMeter); + } else if (block.getSensorType().equalsIgnoreCase(context.getResources().getString(R.string.accelerometer))) { + Intent Accelerometer = new Intent(context, AccelerometerActivity.class); + Accelerometer.putExtra(KEY_LOG, true); + Accelerometer.putExtra(DATA_BLOCK, block.getBlock()); + context.startActivity(Accelerometer); } } @@ -130,6 +140,8 @@ public void onClick(DialogInterface dialog, int whichButton) { LocalDataLog.with().clearBlockOfLuxRecords(block.getBlock()); } else if (block.getSensorType().equalsIgnoreCase(PSLabSensor.BAROMETER)) { LocalDataLog.with().clearBlockOfBaroRecords(block.getBlock()); + } else if (block.getSensorType().equalsIgnoreCase(PSLabSensor.ACCELEROMETER)) { + LocalDataLog.with().clearBlockOfAccelerometerRecords(block.getBlock()); } LocalDataLog.with().clearSensorBlock(block.getBlock()); dialog.dismiss(); @@ -182,6 +194,24 @@ private void populateMapData(SensorDataBlock block) { } } setMapDataToIntent(array); + } else if (block.getSensorType().equalsIgnoreCase(PSLabSensor.ACCELEROMETER)) { + RealmResults data = LocalDataLog.with().getBlockOfAccelerometerRecords(block.getBlock()); + JSONArray array = new JSONArray(); + for (AccelerometerData d : data) { + try { + JSONObject i = new JSONObject(); + i.put("date", CSVLogger.FILE_NAME_FORMAT.format(d.getTime())); + i.put("dataX", d.getAccelerometerX()); + i.put("dataY", d.getAccelerometerY()); + i.put("dataZ", d.getAccelerometerZ()); + i.put("lon", d.getLon()); + i.put("lat", d.getLat()); + if (d.getLat() != 0.0 && d.getLon() != 0.0) array.put(i); + } catch (JSONException e) { + e.printStackTrace(); + } + } + setMapDataToIntent(array); } } diff --git a/app/src/main/java/io/pslab/fragment/AccelerometerDataFragment.java b/app/src/main/java/io/pslab/fragment/AccelerometerDataFragment.java new file mode 100644 index 000000000..49ef3ead6 --- /dev/null +++ b/app/src/main/java/io/pslab/fragment/AccelerometerDataFragment.java @@ -0,0 +1,897 @@ +package io.pslab.fragment; + +import android.graphics.Color; +import android.hardware.Sensor; +import android.hardware.SensorEvent; +import android.hardware.SensorEventListener; +import android.hardware.SensorManager; +import android.location.Location; +import android.os.Bundle; +import android.os.Handler; +import android.support.annotation.NonNull; +import android.support.v4.app.Fragment; +import android.text.Html; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; +import android.widget.Toast; + +import com.github.mikephil.charting.charts.LineChart; +import com.github.mikephil.charting.components.Legend; +import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.LineData; +import com.github.mikephil.charting.data.LineDataSet; + +import java.io.IOException; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.Timer; +import java.util.TimerTask; + +import butterknife.BindView; +import butterknife.ButterKnife; +import butterknife.Unbinder; +import io.pslab.R; +import io.pslab.activity.AccelerometerActivity; +import io.pslab.communication.ScienceLab; +import io.pslab.communication.peripherals.I2C; +import io.pslab.communication.sensors.BH1750; +import io.pslab.communication.sensors.TSL2561; +import io.pslab.models.AccelerometerData; +import io.pslab.models.SensorDataBlock; +import io.pslab.others.CSVLogger; +import io.pslab.others.ScienceLabCommon; + +import static android.content.Context.SENSOR_SERVICE; + +/** + * Created by Kunal on 18-12-18 + */ + +public class AccelerometerDataFragment extends Fragment { + + private static int sensorType = 0; + private static int highLimit = 2000; + private static int updatePeriod = 100; + private static int gain = 1; + private int count = 0, turns = 0; + private float sum = 0; + private boolean returningFromPause = false; + private int[] colors = {Color.YELLOW, Color.MAGENTA, Color.GREEN}; + private float accelerometerValue_X = -1; + private float accelerometerValue_Y = -1; + private float accelerometerValue_Z = -1; + + private enum ACCELEROMETER_SENSOR {INBUILT_SENSOR, BH1750_SENSOR, TSL2561_SENSOR} + + @BindView(R.id.x_axis_image) + ImageView x_axis; + @BindView(R.id.x_accel_value) + TextView x_accel_value; + @BindView(R.id.x_accel_min_text) + TextView x_accel_min; + @BindView(R.id.x_accel_max_text) + TextView x_accel_max; + @BindView(R.id.x_tv_graph_label_xaxis_hmc) + TextView x_tv_graph_label_xaxis_hmc; + @BindView(R.id.x_tv_label_left_yaxis_hmc) + TextView x_tv_label_left_yaxis_hmc; + @BindView(R.id.chart_accelerometer_x) + LineChart x_chart_accelerometer; + + @BindView(R.id.y_axis_image) + ImageView y_axis; + @BindView(R.id.y_accel_value) + TextView y_accel_value; + @BindView(R.id.y_accel_min_text) + TextView y_accel_min_text; + @BindView(R.id.y_accel_max_text) + TextView y_accel_max_text; + @BindView(R.id.y_tv_graph_label_xaxis_hmc) + TextView y_tv_graph_label_xaxis_hmc; + @BindView(R.id.y_tv_label_left_yaxis_hmc) + TextView y_tv_label_left_yaxis_hmc; + @BindView(R.id.y_chart_accelerometer) + LineChart y_chart_accelerometer; + + @BindView(R.id.z_axis_image) + ImageView z_axis_image; + @BindView(R.id.z_accel_value) + TextView z_accel_value; + @BindView(R.id.z_accel_min_text) + TextView z_accel_min_text; + @BindView(R.id.z_accel_max_text) + TextView z_accel_max_text; + @BindView(R.id.z_tv_graph_label_xaxis_hmc) + TextView z_tv_graph_label_xaxis_hmc; + @BindView(R.id.z_tv_label_left_yaxis_hmc) + TextView z_tv_label_left_yaxis_hmc; + @BindView(R.id.z_chart_accelerometer) + LineChart z_chart_accelerometer; + + private Timer graphTimer; + private SensorManager sensorManager; + private Sensor sensor; + private long startTime, block; + private ArrayList entriesX,entriesY,entriesZ; + private ArrayList recordedAccelerometerArray; + private AccelerometerData sensorData; + private float currentMinX = Integer.MAX_VALUE; + private float currentMaxX = Integer.MIN_VALUE; + private float currentMinY = Integer.MAX_VALUE; + private float currentMaxY = Integer.MIN_VALUE; + private float currentMinZ = Integer.MAX_VALUE; + private float currentMaxZ = Integer.MIN_VALUE; + private YAxis y; + private Unbinder unbinder; + private long previousTimeElapsed_X = (System.currentTimeMillis() - startTime) / updatePeriod; + private long previousTimeElapsed_Y = (System.currentTimeMillis() - startTime) / updatePeriod; + private long previousTimeElapsed_Z = (System.currentTimeMillis() - startTime) / updatePeriod; + private AccelerometerActivity accelerometerSensor; + private DecimalFormat df = new DecimalFormat("+#0.0;-#0.0"); + + public static AccelerometerDataFragment newInstance() { + return new AccelerometerDataFragment(); + } + + public static void setParameters(int highLimit, int updatePeriod, String type, String gain) { + AccelerometerDataFragment.highLimit = highLimit; + AccelerometerDataFragment.updatePeriod = updatePeriod; + AccelerometerDataFragment.sensorType = Integer.valueOf(type); + AccelerometerDataFragment.gain = Integer.valueOf(gain); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + startTime = System.currentTimeMillis(); + entriesX = new ArrayList<>(); + entriesY = new ArrayList<>(); + entriesZ = new ArrayList<>(); + accelerometerSensor = (AccelerometerActivity) getActivity(); + } + + @Override + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.fragment_accelerometer_data, container, false); + unbinder = ButterKnife.bind(this, view); + setupInstruments(); + return view; + } + + @Override + public void onResume() { + super.onResume(); + if (accelerometerSensor.playingData) { + recordedAccelerometerArray = new ArrayList<>(); + resetInstrumentData(); + playRecordedData(); + }else if (accelerometerSensor.viewingData) { + recordedAccelerometerArray = new ArrayList<>(); + resetInstrumentData(); + plotAllRecordedData(); + } else if (!accelerometerSensor.isRecording) { + updateGraphs(); + sum = 0; + count = 0; + currentMinX = Integer.MAX_VALUE; + currentMaxX = Integer.MIN_VALUE; + currentMinY = Integer.MAX_VALUE; + currentMaxY = Integer.MIN_VALUE; + currentMinZ = Integer.MAX_VALUE; + currentMaxZ = Integer.MIN_VALUE; + entriesX.clear(); + entriesY.clear(); + entriesZ.clear(); + + x_chart_accelerometer.clear(); + x_chart_accelerometer.invalidate(); + + y_chart_accelerometer.clear(); + y_chart_accelerometer.invalidate(); + + z_chart_accelerometer.clear(); + z_chart_accelerometer.invalidate(); + + initiateAccelerometerSensor(sensorType); + } else if (returningFromPause) { + updateGraphs(); + } + } + + private void plotAllRecordedData() { + recordedAccelerometerArray.addAll(accelerometerSensor.recordedAccelerometerData); + if (recordedAccelerometerArray.size() != 0) { + for (AccelerometerData d: recordedAccelerometerArray) { + if (currentMaxX < d.getAccelerometerX()) { + currentMaxX = d.getAccelerometerX(); + } + if (currentMinX > d.getAccelerometerX()) { + currentMinX = d.getAccelerometerX(); + } + Entry entryX = new Entry((float) (d.getTime() - d.getBlock()) / 1000, d.getAccelerometerX()); + entriesX.add(entryX); + count++; + sum += entryX.getY(); + Entry entryY = new Entry((float) (d.getTime() - d.getBlock()) / 1000, d.getAccelerometerY()); + entriesY.add(entryY); + count++; + sum += entryY.getY(); + Entry entryZ = new Entry((float) (d.getTime() - d.getBlock()) / 1000, d.getAccelerometerZ()); + entriesZ.add(entryZ); + count++; + sum += entryZ.getY(); + } + y.setAxisMaximum(20); + y.setAxisMinimum(-20); + y.setLabelCount(5); + + LineDataSet dataSet_X = new LineDataSet(entriesX, getString(R.string.accelerometer)); + LineData data_x = new LineData(dataSet_X); + dataSet_X.setDrawCircles(false); + dataSet_X.setDrawValues(false); + dataSet_X.setMode(LineDataSet.Mode.CUBIC_BEZIER); + dataSet_X.setLineWidth(1); + dataSet_X.setColor(colors[0]); + + x_chart_accelerometer.setData(data_x); + x_chart_accelerometer.notifyDataSetChanged(); + x_chart_accelerometer.setVisibleXRangeMaximum(3); + x_chart_accelerometer.moveViewToX(data_x.getEntryCount()); + x_chart_accelerometer.invalidate(); + + LineDataSet dataSet_Y = new LineDataSet(entriesY, getString(R.string.accelerometer)); + LineData data_y = new LineData(dataSet_Y); + dataSet_Y.setDrawCircles(false); + dataSet_Y.setDrawValues(false); + dataSet_Y.setMode(LineDataSet.Mode.CUBIC_BEZIER); + dataSet_Y.setLineWidth(1); + dataSet_Y.setColor(colors[1]); + + y_chart_accelerometer.setData(data_y); + y_chart_accelerometer.notifyDataSetChanged(); + y_chart_accelerometer.setVisibleXRangeMaximum(3); + y_chart_accelerometer.moveViewToX(data_y.getEntryCount()); + y_chart_accelerometer.invalidate(); + + LineDataSet dataSet_Z = new LineDataSet(entriesZ, getString(R.string.accelerometer)); + LineData data_z = new LineData(dataSet_Z); + dataSet_Z.setDrawCircles(false); + dataSet_Z.setDrawValues(false); + dataSet_Z.setMode(LineDataSet.Mode.CUBIC_BEZIER); + dataSet_Z.setLineWidth(1); + dataSet_Z.setColor(colors[2]); + + z_chart_accelerometer.setData(data_z); + z_chart_accelerometer.notifyDataSetChanged(); + z_chart_accelerometer.setVisibleXRangeMaximum(3); + z_chart_accelerometer.moveViewToX(data_z.getEntryCount()); + z_chart_accelerometer.invalidate(); + } + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + if (graphTimer != null) { + graphTimer.cancel(); + } + if (sensorManager != null) { + sensorManager.unregisterListener(accelerometerSensorEventListener); + } + unbinder.unbind(); + } + + private void playRecordedData() { + recordedAccelerometerArray.addAll(accelerometerSensor.recordedAccelerometerData); + try { + if (recordedAccelerometerArray.size() > 1) { + AccelerometerData i = recordedAccelerometerArray.get(1); + long timeGap = i.getTime() - i.getBlock(); + processRecordedData(timeGap); + } else { + processRecordedData(0); + } + } catch (IllegalArgumentException e) { + Toast.makeText(getActivity(), + getActivity().getResources().getString(R.string.no_data_fetched), Toast.LENGTH_SHORT).show(); + } + } + + private void processRecordedData(long timeGap) { + final Handler handler = new Handler(); + if (graphTimer != null) { + graphTimer.cancel(); + } else { + graphTimer = new Timer(); + } + graphTimer.schedule(new TimerTask() { + @Override + public void run() { + handler.post(new Runnable() { + @Override + public void run() { + try { + boolean playComplete = false; + AccelerometerData d = recordedAccelerometerArray.get(turns); + turns++; + StringBuilder builder_x = new StringBuilder(); + builder_x.append(df.format(d.getAccelerometerX())); + builder_x.append(" "); + builder_x.append(getResources().getString(R.string.meters_per_sec_text)); + x_accel_value.setText(Html.fromHtml(builder_x.toString())); + + if (currentMaxX < d.getAccelerometerX()) { + currentMaxX = d.getAccelerometerX(); + StringBuilder builder_x_max = new StringBuilder(); + builder_x_max.append("Max: "); + builder_x_max.append(df.format(currentMaxX)); + builder_x_max.append(" "); + builder_x_max.append(getResources().getString(R.string.meters_per_sec_text)); + x_accel_max.setText(Html.fromHtml(builder_x_max.toString())); + } + if (currentMinX > d.getAccelerometerX()) { + currentMinX = d.getAccelerometerX(); + StringBuilder builder_x_min = new StringBuilder(); + builder_x_min.append("Min: "); + builder_x_min.append(df.format(currentMinX)); + builder_x_min.append(" "); + builder_x_min.append(getResources().getString(R.string.meters_per_sec_text)); + x_accel_min.setText(Html.fromHtml(builder_x_min.toString())); + } + StringBuilder builder_y = new StringBuilder(); + builder_y.append(df.format(d.getAccelerometerY())); + builder_y.append(" "); + builder_y.append(getResources().getString(R.string.meters_per_sec_text)); + y_accel_value.setText(Html.fromHtml(builder_y.toString())); + if (currentMaxY < d.getAccelerometerY()) { + currentMaxY = d.getAccelerometerY(); + StringBuilder builder_y_max = new StringBuilder(); + builder_y_max.append("Max: "); + builder_y_max.append(df.format(currentMaxY)); + builder_y_max.append(" "); + builder_y_max.append(getResources().getString(R.string.meters_per_sec_text)); + y_accel_max_text.setText(Html.fromHtml(builder_y_max.toString())); + } + if (currentMinY > d.getAccelerometerY()) { + currentMinY = d.getAccelerometerY(); + StringBuilder builder_y_min = new StringBuilder(); + builder_y_min.append("Min: "); + builder_y_min.append(df.format(currentMinY)); + builder_y_min.append(" "); + builder_y_min.append(getResources().getString(R.string.meters_per_sec_text)); + y_accel_min_text.setText(Html.fromHtml(builder_y_min.toString())); + } + StringBuilder builder_z = new StringBuilder(); + builder_z.append(df.format(d.getAccelerometerZ())); + builder_z.append(" "); + builder_z.append(getResources().getString(R.string.meters_per_sec_text)); + z_accel_value.setText(Html.fromHtml(builder_z.toString())); + if (currentMaxZ < d.getAccelerometerZ()) { + currentMaxZ = d.getAccelerometerZ(); + StringBuilder builder_z_max = new StringBuilder(); + builder_z_max.append("Max: "); + builder_z_max.append(df.format(currentMaxZ)); + builder_z_max.append(" "); + builder_z_max.append(getResources().getString(R.string.meters_per_sec_text)); + z_accel_max_text.setText(Html.fromHtml(builder_z_max.toString())); + } + if (currentMinZ > d.getAccelerometerZ()) { + currentMinZ = d.getAccelerometerZ(); + StringBuilder builder_z_min = new StringBuilder(); + builder_z_min.append("Min: "); + builder_z_min.append(df.format(currentMinZ)); + builder_z_min.append(" "); + builder_z_min.append(getResources().getString(R.string.meters_per_sec_text)); + z_accel_min_text.setText(Html.fromHtml(builder_z_min.toString())); + } + y.setAxisMaximum(20); + y.setAxisMinimum(-20); + y.setLabelCount(5); + + Entry entryX = new Entry((float) (d.getTime() - d.getBlock()) / 1000, d.getAccelerometerX()); + entriesX.add(entryX); + count++; + sum += entryX.getY(); + Entry entryY = new Entry((float) (d.getTime() - d.getBlock()) / 1000, d.getAccelerometerY()); + entriesY.add(entryY); + count++; + sum += entryY.getY(); + Entry entryZ = new Entry((float) (d.getTime() - d.getBlock()) / 1000, d.getAccelerometerZ()); + entriesZ.add(entryZ); + count++; + sum += entryZ.getY(); + + LineDataSet dataSet_X = new LineDataSet(entriesX, getString(R.string.accelerometer)); + LineData data_x = new LineData(dataSet_X); + dataSet_X.setDrawCircles(false); + dataSet_X.setDrawValues(false); + dataSet_X.setMode(LineDataSet.Mode.CUBIC_BEZIER); + dataSet_X.setLineWidth(1); + dataSet_X.setColor(colors[0]); + + x_chart_accelerometer.setData(data_x); + x_chart_accelerometer.notifyDataSetChanged(); + x_chart_accelerometer.setVisibleXRangeMaximum(3); + x_chart_accelerometer.moveViewToX(data_x.getEntryCount()); + x_chart_accelerometer.invalidate(); + + LineDataSet dataSet_Y = new LineDataSet(entriesY, getString(R.string.accelerometer)); + LineData data_y = new LineData(dataSet_Y); + dataSet_Y.setDrawCircles(false); + dataSet_Y.setDrawValues(false); + dataSet_Y.setMode(LineDataSet.Mode.CUBIC_BEZIER); + dataSet_Y.setLineWidth(1); + dataSet_Y.setColor(colors[1]); + + y_chart_accelerometer.setData(data_y); + y_chart_accelerometer.notifyDataSetChanged(); + y_chart_accelerometer.setVisibleXRangeMaximum(3); + y_chart_accelerometer.moveViewToX(data_y.getEntryCount()); + y_chart_accelerometer.invalidate(); + + LineDataSet dataSet_Z = new LineDataSet(entriesZ, getString(R.string.accelerometer)); + LineData data_z = new LineData(dataSet_Z); + dataSet_Z.setDrawCircles(false); + dataSet_Z.setDrawValues(false); + dataSet_Z.setMode(LineDataSet.Mode.CUBIC_BEZIER); + dataSet_Z.setLineWidth(1); + dataSet_Z.setColor(colors[2]); + + z_chart_accelerometer.setData(data_z); + z_chart_accelerometer.notifyDataSetChanged(); + z_chart_accelerometer.setVisibleXRangeMaximum(3); + z_chart_accelerometer.moveViewToX(data_z.getEntryCount()); + z_chart_accelerometer.invalidate(); + + } catch (IndexOutOfBoundsException e) { + graphTimer.cancel(); + graphTimer = null; + turns = 0; + accelerometerSensor.playingData = false; + accelerometerSensor.startedPlay = false; + accelerometerSensor.invalidateOptionsMenu(); + } + } + }); + } + }, 0, timeGap); + } + + public void stopData() { + if (graphTimer != null) { + graphTimer.cancel(); + graphTimer = null; + } + recordedAccelerometerArray.clear(); + entriesX.clear(); + entriesY.clear(); + entriesZ.clear(); + plotAllRecordedData(); + accelerometerSensor.startedPlay = false; + accelerometerSensor.playingData = false; + turns = 0; + accelerometerSensor.invalidateOptionsMenu(); + } + + public void saveGraph() { + // Todo: Save graph view to gallery + } + + + public void playData() { + resetInstrumentData(); + accelerometerSensor.startedPlay = true; + try { + if (recordedAccelerometerArray.size() > 1) { + AccelerometerData i = recordedAccelerometerArray.get(1); + long timeGap = i.getTime() - i.getBlock(); + processRecordedData(timeGap); + } else { + processRecordedData(0); + } + } catch (IllegalArgumentException e) { + Toast.makeText(getActivity(), + getActivity().getResources().getString(R.string.no_data_fetched), Toast.LENGTH_SHORT).show(); + } + } + + private void setupInstruments() { + LineData data_x = new LineData(); + XAxis x = x_chart_accelerometer.getXAxis(); + this.y = x_chart_accelerometer.getAxisLeft(); + YAxis y2 = x_chart_accelerometer.getAxisRight(); + + x_chart_accelerometer.setTouchEnabled(true); + x_chart_accelerometer.setHighlightPerDragEnabled(true); + x_chart_accelerometer.setDragEnabled(true); + x_chart_accelerometer.setScaleEnabled(true); + x_chart_accelerometer.setDrawGridBackground(false); + x_chart_accelerometer.setPinchZoom(true); + x_chart_accelerometer.setScaleYEnabled(false); + x_chart_accelerometer.setBackgroundColor(Color.BLACK); + x_chart_accelerometer.getDescription().setEnabled(false); + + Legend l = x_chart_accelerometer.getLegend(); + l.setForm(Legend.LegendForm.LINE); + l.setTextColor(Color.WHITE); + + x_chart_accelerometer.setData(data_x); + + x.setTextColor(Color.WHITE); + x.setDrawGridLines(true); + x.setAvoidFirstLastClipping(true); + x.setDrawLabels(false); + + y.setTextColor(Color.WHITE); + y.setAxisMaximum(20); + y.setAxisMinimum(-20); + y.setDrawGridLines(true); + y.setLabelCount(6); + + y2.setDrawGridLines(false); + + LineData data_y = new LineData(); + XAxis x_1 = y_chart_accelerometer.getXAxis(); + this.y = y_chart_accelerometer.getAxisLeft(); + YAxis y2_1 = y_chart_accelerometer.getAxisRight(); + + y_chart_accelerometer.setTouchEnabled(true); + y_chart_accelerometer.setHighlightPerDragEnabled(true); + y_chart_accelerometer.setDragEnabled(true); + y_chart_accelerometer.setScaleEnabled(true); + y_chart_accelerometer.setDrawGridBackground(false); + y_chart_accelerometer.setPinchZoom(true); + y_chart_accelerometer.setScaleYEnabled(false); + y_chart_accelerometer.setBackgroundColor(Color.BLACK); + y_chart_accelerometer.getDescription().setEnabled(false); + + Legend l_1 = y_chart_accelerometer.getLegend(); + l_1.setForm(Legend.LegendForm.LINE); + l_1.setTextColor(Color.WHITE); + + y_chart_accelerometer.setData(data_y); + + x_1.setTextColor(Color.WHITE); + x_1.setDrawGridLines(true); + x_1.setAvoidFirstLastClipping(true); + x_1.setDrawLabels(false); + + y.setTextColor(Color.WHITE); + y.setAxisMaximum(20); + y.setAxisMinimum(-20); + y.setDrawGridLines(true); + y.setLabelCount(6); + + y2_1.setDrawGridLines(false); + + LineData data_z = new LineData(); + XAxis x_2 = z_chart_accelerometer.getXAxis(); + this.y = z_chart_accelerometer.getAxisLeft(); + YAxis y2_2 = z_chart_accelerometer.getAxisRight(); + + z_chart_accelerometer.setTouchEnabled(true); + z_chart_accelerometer.setHighlightPerDragEnabled(true); + z_chart_accelerometer.setDragEnabled(true); + z_chart_accelerometer.setScaleEnabled(true); + z_chart_accelerometer.setDrawGridBackground(false); + z_chart_accelerometer.setPinchZoom(true); + z_chart_accelerometer.setScaleYEnabled(false); + z_chart_accelerometer.setBackgroundColor(Color.BLACK); + z_chart_accelerometer.getDescription().setEnabled(false); + + Legend l_2 = z_chart_accelerometer.getLegend(); + l_2.setForm(Legend.LegendForm.LINE); + l_2.setTextColor(Color.WHITE); + + z_chart_accelerometer.setData(data_z); + + x_2.setTextColor(Color.WHITE); + x_2.setDrawGridLines(true); + x_2.setAvoidFirstLastClipping(true); + x_2.setDrawLabels(false); + + y.setTextColor(Color.WHITE); + y.setAxisMaximum(20); + y.setAxisMinimum(-20); + y.setDrawGridLines(true); + y.setLabelCount(6); + + y2_2.setDrawGridLines(false); + } + + @Override + public void onPause() { + super.onPause(); + if (graphTimer != null) { + returningFromPause = true; + graphTimer.cancel(); + graphTimer = null; + if (accelerometerSensor.playingData) { + accelerometerSensor.finish(); + } + } + } + + private void updateGraphs() { + final Handler handler = new Handler(); + if (graphTimer != null) { + graphTimer.cancel(); + } + graphTimer = new Timer(); + graphTimer.schedule(new TimerTask() { + @Override + public void run() { + handler.post(new Runnable() { + @Override + public void run() { + try { + visualizeData(); + } catch (NullPointerException e) { + /* Pass for another refresh round */ + } + } + }); + } + }, 0, updatePeriod); + } + + private void writeLogToFile(long timestamp, float sensorReading) { + if (getActivity() != null && accelerometerSensor.isRecording) { + if (accelerometerSensor.writeHeaderToFile) { + accelerometerSensor.csvLogger.prepareLogFile(); + accelerometerSensor.csvLogger.writeCSVFile("Timestamp,DateTime,Readings,Latitude,Longitude"); + block = timestamp; + accelerometerSensor.recordSensorDataBlockID(new SensorDataBlock(timestamp, accelerometerSensor.getSensorName())); + accelerometerSensor.writeHeaderToFile = !accelerometerSensor.writeHeaderToFile; + } + if (accelerometerSensor.addLocation && accelerometerSensor.gpsLogger.isGPSEnabled()) { + String dateTime = CSVLogger.FILE_NAME_FORMAT.format(new Date(timestamp)); + Location location = accelerometerSensor.gpsLogger.getDeviceLocation(); + accelerometerSensor.csvLogger.writeCSVFile(timestamp + "," + dateTime + "," + + sensorReading + "," + location.getLatitude() + "," + location.getLongitude()); + sensorData = new AccelerometerData(timestamp, block, accelerometerValue_X,accelerometerValue_Y,accelerometerValue_Z, location.getLatitude(), location.getLongitude()); + } else { + String dateTime = CSVLogger.FILE_NAME_FORMAT.format(new Date(timestamp)); + accelerometerSensor.csvLogger.writeCSVFile(timestamp + "," + dateTime + "," + + sensorReading + ",0.0,0.0"); + sensorData = new AccelerometerData(timestamp, block, accelerometerValue_X,accelerometerValue_Y,accelerometerValue_Z, 0.0, 0.0); + } + accelerometerSensor.recordSensorData(sensorData); + } else { + accelerometerSensor.writeHeaderToFile = true; + } + } + + private void visualizeData() { + long timeElapsed = (System.currentTimeMillis() - startTime) / 1000; + if (timeElapsed != previousTimeElapsed_X) { + previousTimeElapsed_X = timeElapsed; + Long currentTime = System.currentTimeMillis(); + writeLogToFile(currentTime, accelerometerValue_X); + entriesX.add(new Entry((float) timeElapsed, accelerometerValue_X)); + + LineDataSet dataSet = new LineDataSet(entriesX, getString(R.string.accelerometer)); + LineData data = new LineData(dataSet); + dataSet.setDrawCircles(false); + dataSet.setDrawValues(false); + dataSet.setMode(LineDataSet.Mode.CUBIC_BEZIER); + dataSet.setLineWidth(1); + dataSet.setColor(colors[0]); + + x_chart_accelerometer.setData(data); + x_chart_accelerometer.notifyDataSetChanged(); + x_chart_accelerometer.setVisibleXRangeMaximum(3); + x_chart_accelerometer.moveViewToX(data.getEntryCount()); + x_chart_accelerometer.invalidate(); + } + + timeElapsed = (System.currentTimeMillis() - startTime) / 1000; + if (timeElapsed != previousTimeElapsed_Y) { + previousTimeElapsed_Y = timeElapsed; + Long currentTime = System.currentTimeMillis(); + writeLogToFile(currentTime, accelerometerValue_Y); + entriesY.add(new Entry((float) timeElapsed, accelerometerValue_Y)); + + LineDataSet dataSet = new LineDataSet(entriesY, getString(R.string.accelerometer)); + LineData data = new LineData(dataSet); + dataSet.setDrawCircles(false); + dataSet.setDrawValues(false); + dataSet.setMode(LineDataSet.Mode.CUBIC_BEZIER); + dataSet.setLineWidth(1); + dataSet.setColor(colors[1]); + + y_chart_accelerometer.setData(data); + y_chart_accelerometer.notifyDataSetChanged(); + y_chart_accelerometer.setVisibleXRangeMaximum(3); + y_chart_accelerometer.moveViewToX(data.getEntryCount()); + y_chart_accelerometer.invalidate(); + } + timeElapsed = (System.currentTimeMillis() - startTime) / 1000; + if (timeElapsed != previousTimeElapsed_Z) { + previousTimeElapsed_Z = timeElapsed; + Long currentTime = System.currentTimeMillis(); + writeLogToFile(currentTime, accelerometerValue_Z); + entriesZ.add(new Entry((float) timeElapsed, accelerometerValue_Z)); + + LineDataSet dataSet = new LineDataSet(entriesZ, getString(R.string.accelerometer)); + LineData data = new LineData(dataSet); + dataSet.setDrawCircles(false); + dataSet.setDrawValues(false); + dataSet.setMode(LineDataSet.Mode.CUBIC_BEZIER); + dataSet.setLineWidth(1); + dataSet.setColor(colors[2]); + + z_chart_accelerometer.setData(data); + z_chart_accelerometer.notifyDataSetChanged(); + z_chart_accelerometer.setVisibleXRangeMaximum(3); + z_chart_accelerometer.moveViewToX(data.getEntryCount()); + z_chart_accelerometer.invalidate(); + } + y.setAxisMaximum(20); + y.setAxisMinimum(-20); + y.setLabelCount(5); + } + + private SensorEventListener accelerometerSensorEventListener = new SensorEventListener() { + + @Override + public void onAccuracyChanged(Sensor sensor, int accuracy) {/**/} + + @Override + public void onSensorChanged(SensorEvent event) { + if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { + accelerometerValue_X = event.values[0]; + StringBuilder builder_x = new StringBuilder(); + builder_x.append(df.format(accelerometerValue_X)); + builder_x.append(" "); + builder_x.append(getResources().getString(R.string.meters_per_sec_text)); + x_accel_value.setText(Html.fromHtml(builder_x.toString())); + if (accelerometerValue_X > currentMaxX) { + builder_x.insert(0, getResources().getString(R.string.text_max)); + builder_x.insert(3, " "); + x_accel_max.setText(Html.fromHtml(builder_x.toString())); + currentMaxX = accelerometerValue_X; + } else if (accelerometerValue_X < currentMinX) { + builder_x.insert(0, getResources().getString(R.string.text_min)); + builder_x.insert(3, " "); + x_accel_min.setText(Html.fromHtml(builder_x.toString())); + currentMinX = accelerometerValue_X; + } + accelerometerValue_Y = event.values[1]; + StringBuilder builder_y = new StringBuilder(); + builder_y.append(df.format(accelerometerValue_Y)); + builder_y.append(" "); + builder_y.append(getResources().getString(R.string.meters_per_sec_text)); + y_accel_value.setText(Html.fromHtml(builder_y.toString())); + if (accelerometerValue_Y > currentMaxY) { + builder_y.insert(0, getResources().getString(R.string.text_max)); + builder_y.insert(3, " "); + y_accel_max_text.setText(Html.fromHtml(builder_y.toString())); + currentMaxY = accelerometerValue_Y; + } else if (accelerometerValue_Y < currentMinY) { + builder_y.insert(0, getResources().getString(R.string.text_min)); + builder_y.insert(3, " "); + y_accel_min_text.setText(Html.fromHtml(builder_y.toString())); + currentMinY = accelerometerValue_Y; + } + accelerometerValue_Z = event.values[2]; + StringBuilder builder_z = new StringBuilder(); + builder_z.append(df.format(accelerometerValue_Z)); + builder_z.append(" "); + builder_z.append(getResources().getString(R.string.meters_per_sec_text)); + z_accel_value.setText(Html.fromHtml(builder_z.toString())); + + if (accelerometerValue_Z > currentMaxZ) { + builder_z.insert(0, getResources().getString(R.string.text_max)); + builder_z.insert(3, " "); + z_accel_max_text.setText(Html.fromHtml(builder_z.toString())); + currentMaxZ = accelerometerValue_Z; + } else if (accelerometerValue_Z < currentMinZ) { + builder_z.insert(0, getResources().getString(R.string.text_min)); + builder_z.insert(3, " "); + z_accel_min_text.setText(Html.fromHtml(builder_z.toString())); + currentMinZ = accelerometerValue_Z; + } + } + } + }; + + private void resetInstrumentData(){ + accelerometerValue_X = 0; + accelerometerValue_Y = 0; + accelerometerValue_Z = 0; + count = 0; + currentMinX = Integer.MAX_VALUE; + currentMaxX = Integer.MIN_VALUE; + currentMinY = Integer.MAX_VALUE; + currentMaxY = Integer.MIN_VALUE; + currentMinZ = Integer.MAX_VALUE; + currentMaxZ = Integer.MIN_VALUE; + sum = 0; + sensor = null; + startTime = System.currentTimeMillis(); + z_axis_image.setImageResource(R.drawable.phone_z_axis); + y_axis.setImageResource(R.drawable.phone_y_axis); + x_axis.setImageResource(R.drawable.phone_x_axis); + entriesX.clear(); + entriesZ.clear(); + entriesY.clear(); + } + + private void initiateAccelerometerSensor(int type) { + ACCELEROMETER_SENSOR s = ACCELEROMETER_SENSOR.values()[type]; + resetInstrumentData(); + ScienceLab scienceLab; + switch (s) { + case INBUILT_SENSOR: + //z_accel_max_text.setText(getResources().getStringArray(R.array.lux_sensors)[0]); + sensorManager = (SensorManager) getContext().getSystemService(SENSOR_SERVICE); + sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); + if (sensor == null) { + Toast.makeText(getContext(), getResources().getString(R.string.no_accelerometer_sensor), Toast.LENGTH_LONG).show(); + } else { + float max = sensor.getMaximumRange(); + //z_tv_label_left_yaxis_hmc.setMaxSpeed(max); + sensorManager.registerListener(accelerometerSensorEventListener, + sensor, SensorManager.SENSOR_DELAY_FASTEST); + } + break; + case BH1750_SENSOR: + //z_accel_max_text.setText(getResources().getStringArray(R.array.lux_sensors)[1]); + scienceLab = ScienceLabCommon.scienceLab; + if (scienceLab.isConnected()) { + ArrayList data; + try { + I2C i2c = scienceLab.i2c; + data = i2c.scan(null); + if (data.contains(0x23)) { + BH1750 sensorBH1750 = new BH1750(i2c); + sensorBH1750.setRange(String.valueOf(gain)); + sensorType = 0; + } else { + Toast.makeText(getContext(), getResources().getText(R.string.sensor_not_connected_tls), Toast.LENGTH_SHORT).show(); + sensorType = 0; + } + } catch (IOException | InterruptedException e) { + e.printStackTrace(); + } + } else { + Toast.makeText(getContext(), getResources().getText(R.string.device_not_found), Toast.LENGTH_SHORT).show(); + sensorType = 0; + } + break; + case TSL2561_SENSOR: + scienceLab = ScienceLabCommon.scienceLab; + if (scienceLab.isConnected()) { + try { + I2C i2c = scienceLab.i2c; + ArrayList data; + data = i2c.scan(null); + if (data.contains(0x39)) { + TSL2561 sensorTSL2561 = new TSL2561(i2c, scienceLab); + sensorTSL2561.setGain(String.valueOf(gain)); + sensorType = 2; + } else { + Toast.makeText(getContext(), getResources().getText(R.string.sensor_not_connected_tls), Toast.LENGTH_SHORT).show(); + sensorType = 0; + } + } catch (IOException | InterruptedException e) { + e.printStackTrace(); + } + } else { + Toast.makeText(getContext(), getResources().getText(R.string.device_not_found), Toast.LENGTH_SHORT).show(); + sensorType = 0; + } + break; + default: + break; + } + } +} \ No newline at end of file diff --git a/app/src/main/java/io/pslab/fragment/AccelerometerSettingsFragment.java b/app/src/main/java/io/pslab/fragment/AccelerometerSettingsFragment.java new file mode 100644 index 000000000..27f9cc5f4 --- /dev/null +++ b/app/src/main/java/io/pslab/fragment/AccelerometerSettingsFragment.java @@ -0,0 +1,123 @@ +package io.pslab.fragment; + +import android.annotation.SuppressLint; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.support.v7.preference.CheckBoxPreference; +import android.support.v7.preference.EditTextPreference; +import android.support.v7.preference.ListPreference; +import android.support.v7.preference.PreferenceFragmentCompat; +import android.support.v7.preference.PreferenceManager; + +import io.pslab.R; +import io.pslab.others.PSLabPermission; + +/** + * Created by Kunal on 18-12-2018. + */ +public class AccelerometerSettingsFragment extends PreferenceFragmentCompat implements SharedPreferences.OnSharedPreferenceChangeListener { + + public static final String KEY_INCLUDE_LOCATION = "include_location_sensor_data"; + public static final String KEY_UPDATE_PERIOD = "setting_lux_update_period"; + public static final String KEY_HIGH_LIMIT = "setting_lux_high_limit"; + public static final String KEY_ACCELEROMETER_SENSOR_TYPE = "setting_lux_sensor_type"; + public static final String KEY_ACCELEROMETER_SENSOR_GAIN = "setting_lux_sensor_gain"; + + private PSLabPermission psLabPermission; + + private EditTextPreference updatePeriodPref; + private EditTextPreference higLimitPref; + private EditTextPreference sensorGainPref; + private CheckBoxPreference locationPreference; + private ListPreference sensorTypePreference; + private SharedPreferences sharedPref; + + @Override + public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { + setPreferencesFromResource(R.xml.lux_meter_settings, rootKey); + updatePeriodPref = (EditTextPreference) getPreferenceScreen().findPreference(KEY_UPDATE_PERIOD); + higLimitPref = (EditTextPreference) getPreferenceScreen().findPreference(KEY_HIGH_LIMIT); + sensorGainPref = (EditTextPreference) getPreferenceScreen().findPreference(KEY_ACCELEROMETER_SENSOR_GAIN); + locationPreference = (CheckBoxPreference) getPreferenceScreen().findPreference(KEY_INCLUDE_LOCATION); + sensorTypePreference = (ListPreference) getPreferenceScreen().findPreference(KEY_ACCELEROMETER_SENSOR_TYPE); + sharedPref = PreferenceManager.getDefaultSharedPreferences(getActivity()); + + psLabPermission = PSLabPermission.getInstance(); + if (!psLabPermission.checkPermissions(getActivity(), PSLabPermission.MAP_PERMISSION)) { + SharedPreferences.Editor editor = sharedPref.edit(); + editor.putBoolean(LuxMeterSettingFragment.KEY_INCLUDE_LOCATION, true); + editor.apply(); + } + } + + @Override + public void onResume() { + super.onResume(); + locationPreference.setChecked(sharedPref.getBoolean(KEY_INCLUDE_LOCATION, true)); + updatePeriodPref.setSummary(updatePeriodPref.getText() + " ms"); + higLimitPref.setSummary(higLimitPref.getText() + " Lx"); + sensorTypePreference.setSummary(sensorTypePreference.getEntry()); + sensorGainPref.setSummary(sensorGainPref.getText()); + getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this); + } + + @Override + public void onPause() { + super.onPause(); + getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this); + } + + @SuppressLint("ApplySharedPref") + @Override + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String s) { + switch (s) { + case KEY_INCLUDE_LOCATION: + if (locationPreference.isChecked()) { + psLabPermission.checkPermissions( + getActivity(), PSLabPermission.MAP_PERMISSION); + } + break; + case KEY_UPDATE_PERIOD: + try { + Integer updatePeriod = Integer.valueOf(updatePeriodPref.getText()); + updatePeriodPref.setSummary(updatePeriod + " ms"); + } catch (NumberFormatException e) { + updatePeriodPref.setSummary("1000 ms"); + updatePeriodPref.setText("1000"); + SharedPreferences.Editor editor = sharedPref.edit(); + editor.putString(s, "1000"); + editor.commit(); + } + break; + case KEY_ACCELEROMETER_SENSOR_GAIN: + try { + Integer gain = Integer.valueOf(sensorGainPref.getText()); + sensorGainPref.setSummary(String.valueOf(gain)); + } catch (NumberFormatException e) { + sensorGainPref.setSummary("1"); + sensorGainPref.setText("1"); + SharedPreferences.Editor editor = sharedPref.edit(); + editor.putString(KEY_ACCELEROMETER_SENSOR_GAIN, "1"); + editor.commit(); + } + break; + case KEY_HIGH_LIMIT: + try { + Integer highLimit = Integer.valueOf(higLimitPref.getText()); + higLimitPref.setSummary(String.valueOf(highLimit)); + } catch (NumberFormatException e) { + higLimitPref.setSummary("2000 Lx"); + higLimitPref.setText("2000"); + SharedPreferences.Editor editor = sharedPref.edit(); + editor.putString(KEY_HIGH_LIMIT, "2000"); + editor.commit(); + } + break; + case KEY_ACCELEROMETER_SENSOR_TYPE: + sensorTypePreference.setSummary(sensorTypePreference.getEntry()); + break; + default: + break; + } + } +} diff --git a/app/src/main/java/io/pslab/interfaces/sensorloggers/AccelerometerRecordables.java b/app/src/main/java/io/pslab/interfaces/sensorloggers/AccelerometerRecordables.java new file mode 100644 index 000000000..e1043368e --- /dev/null +++ b/app/src/main/java/io/pslab/interfaces/sensorloggers/AccelerometerRecordables.java @@ -0,0 +1,17 @@ +package io.pslab.interfaces.sensorloggers; + +import io.pslab.models.AccelerometerData; +import io.realm.RealmResults; + +public interface AccelerometerRecordables { + + AccelerometerData getAccelerometerData(long timeStamp); + + void clearAllAccelerometerRecords(); + + void clearBlockOfAccelerometerRecords(long block); + + RealmResults getAllAccelerometerRecords(); + + RealmResults getBlockOfAccelerometerRecords(long block); +} diff --git a/app/src/main/java/io/pslab/models/AccelerometerData.java b/app/src/main/java/io/pslab/models/AccelerometerData.java new file mode 100644 index 000000000..89b543a11 --- /dev/null +++ b/app/src/main/java/io/pslab/models/AccelerometerData.java @@ -0,0 +1,92 @@ +package io.pslab.models; + +import io.realm.RealmObject; +import io.realm.annotations.PrimaryKey; + +/** + * Created by Kunal on 18-12-2018. + */ + +public class AccelerometerData extends RealmObject { + + @PrimaryKey + private long time; + private long block; + private float accelerometer_X; + private float accelerometer_Y; + private float accelerometer_Z; + private double lat, lon; + + public AccelerometerData() {/**/} + + public AccelerometerData(long time, long block, float accelerometer_X, float accelerometer_Y, float accelerometer_Z, double lat, double lon) { + this.time = time; + this.block = block; + this.accelerometer_X = accelerometer_X; + this.accelerometer_Y = accelerometer_Y; + this.accelerometer_Z = accelerometer_Z; + this.lat = lat; + this.lon = lon; + } + + public long getTime() { + return time; + } + + public void setTime(long time) { + this.time = time; + } + + public long getBlock() { + return block; + } + + public void setBlock(long block) { + this.block = block; + } + + public float getAccelerometerX() { + return accelerometer_X; + } + + public void setAccelerometerX(float accelerometer) { + this.accelerometer_X = accelerometer_X; + } + + public float getAccelerometerY() { + return accelerometer_Y; + } + + public void setAccelerometerY(float accelerometer) { + this.accelerometer_Y = accelerometer_Y; + } + + public float getAccelerometerZ() { + return accelerometer_Z; + } + + public void setAccelerometerZ(float accelerometer) { + this.accelerometer_Z = accelerometer_Z; + } + + public double getLat() { + return lat; + } + + public void setLat(double lat) { + this.lat = lat; + } + + public double getLon() { + return lon; + } + + public void setLon(double lon) { + this.lon = lon; + } + + @Override + public String toString() { + return "Block - " + block + ", Time - " + time + ", Accelerometer_X - " + accelerometer_X +", Accelerometer_Y - " + accelerometer_Y + ", Accelerometer_Z - " + accelerometer_Z + ", Lat - " + lat + ", Lon - " + lon; + } +} diff --git a/app/src/main/java/io/pslab/models/PSLabSensor.java b/app/src/main/java/io/pslab/models/PSLabSensor.java index 123907a08..9ccfb4c80 100644 --- a/app/src/main/java/io/pslab/models/PSLabSensor.java +++ b/app/src/main/java/io/pslab/models/PSLabSensor.java @@ -43,6 +43,7 @@ import io.pslab.activity.DataLoggerActivity; import io.pslab.activity.MapsActivity; import io.pslab.activity.SettingsActivity; +import io.pslab.fragment.AccelerometerDataFragment; import io.pslab.fragment.BaroMeterDataFragment; import io.pslab.fragment.LuxMeterDataFragment; import io.pslab.others.CSVLogger; @@ -92,7 +93,9 @@ public abstract class PSLabSensor extends AppCompatActivity { public static final String LUXMETER_DATA_FORMAT = "%.2f"; public static final String BAROMETER = "Barometer"; public static final String BAROMETER_CONFIGURATIONS = "Barometer Configurations"; - public static final String BAROMETER_DATA_FORMAT = "%.2f"; + public static final String BAROMETER_DATA_FORMAT = "%.5f"; + public static final String ACCELEROMETER = "Accelerometer"; + public static final String ACCELEROMETER_DATA_FORMAT = "%.2f"; @BindView(R.id.sensor_toolbar) Toolbar sensorToolBar; @@ -251,9 +254,8 @@ private void setUpMenu(Menu menu) { menu.getItem(i).setVisible(false); } } - menu.findItem(R.id.save_graph).setVisible(viewingData || playingData); menu.findItem(R.id.play_data).setVisible(viewingData || playingData); - menu.findItem(R.id.settings).setTitle(getSensorName() + " Configurations"); + menu.findItem(R.id.settings).setTitle(getSensorName() + "Configurations"); menu.findItem(R.id.stop_data).setVisible(viewingData).setEnabled(startedPlay); } @@ -314,6 +316,9 @@ public boolean onOptionsItemSelected(MenuItem item) { } else if (getSensorFragment() instanceof BaroMeterDataFragment) { ((BaroMeterDataFragment) getSupportFragmentManager() .findFragmentByTag(getSensorName())).playData(); + }else if(getSensorFragment() instanceof AccelerometerDataFragment){ + ((AccelerometerDataFragment) getSupportFragmentManager() + .findFragmentByTag(getSensorName())).playData(); } } invalidateOptionsMenu(); @@ -325,6 +330,9 @@ public boolean onOptionsItemSelected(MenuItem item) { } else if (getSensorFragment() instanceof BaroMeterDataFragment) { ((BaroMeterDataFragment) getSupportFragmentManager() .findFragmentByTag(getSensorName())).stopData(); + }else if (getSensorFragment() instanceof AccelerometerDataFragment) { + ((AccelerometerDataFragment) getSupportFragmentManager() + .findFragmentByTag(getSensorName())).stopData(); } break; case R.id.show_map: @@ -349,16 +357,6 @@ public boolean onOptionsItemSelected(MenuItem item) { case R.id.show_guide: bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED); break; - case R.id.save_graph: - displayLogLocationOnSnackBar(); - if (getSensorFragment() instanceof LuxMeterDataFragment) { - ((LuxMeterDataFragment) getSupportFragmentManager() - .findFragmentByTag(getSensorName())).saveGraph(); - } else if (getSensorFragment() instanceof BaroMeterDataFragment) { - ((BaroMeterDataFragment) getSupportFragmentManager() - .findFragmentByTag(getSensorName())).saveGraph(); - } - break; default: break; } diff --git a/app/src/main/java/io/pslab/others/LocalDataLog.java b/app/src/main/java/io/pslab/others/LocalDataLog.java index b43985d9c..1e16a91fc 100644 --- a/app/src/main/java/io/pslab/others/LocalDataLog.java +++ b/app/src/main/java/io/pslab/others/LocalDataLog.java @@ -1,8 +1,10 @@ package io.pslab.others; +import io.pslab.interfaces.sensorloggers.AccelerometerRecordables; import io.pslab.interfaces.sensorloggers.BaroMeterRecordables; import io.pslab.interfaces.sensorloggers.LuxMeterRecordables; import io.pslab.interfaces.sensorloggers.SensorRecordables; +import io.pslab.models.AccelerometerData; import io.pslab.models.BaroData; import io.pslab.models.LuxData; import io.pslab.models.SensorDataBlock; @@ -14,7 +16,7 @@ * Created by Padmal on 11/5/18. */ -public class LocalDataLog implements LuxMeterRecordables, BaroMeterRecordables, SensorRecordables { +public class LocalDataLog implements LuxMeterRecordables, BaroMeterRecordables, SensorRecordables, AccelerometerRecordables { private static LocalDataLog instance; private final Realm realm; @@ -121,6 +123,41 @@ public RealmResults getBlockOfLuxRecords(long block) { .findAll(); } + /*********************************************************************************************** + * Accelerometer Sensor Section + ***********************************************************************************************/ + @Override + public AccelerometerData getAccelerometerData(long timestamp) { + return realm.where(AccelerometerData.class).equalTo("time", timestamp).findFirst(); + } + + @Override + public void clearAllAccelerometerRecords() { + realm.beginTransaction(); + realm.delete(AccelerometerData.class); + realm.commitTransaction(); + } + + @Override + public void clearBlockOfAccelerometerRecords(long block) { + realm.beginTransaction(); + RealmResults data = getBlockOfAccelerometerRecords(block); + data.deleteAllFromRealm(); + realm.commitTransaction(); + } + + @Override + public RealmResults getAllAccelerometerRecords() { + return realm.where(AccelerometerData.class).findAll(); + } + + @Override + public RealmResults getBlockOfAccelerometerRecords(long block) { + return realm.where(AccelerometerData.class) + .equalTo("block", block) + .findAll(); + } + /*********************************************************************************************** * Baro Sensor Section ***********************************************************************************************/ diff --git a/app/src/main/res/layout/fragment_accelerometer_data.xml b/app/src/main/res/layout/fragment_accelerometer_data.xml new file mode 100644 index 000000000..a3d3a7bf2 --- /dev/null +++ b/app/src/main/res/layout/fragment_accelerometer_data.xml @@ -0,0 +1,445 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_accelerometer_settings.xml b/app/src/main/res/layout/fragment_accelerometer_settings.xml new file mode 100644 index 000000000..4c8210af2 --- /dev/null +++ b/app/src/main/res/layout/fragment_accelerometer_settings.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/sensor_main.xml b/app/src/main/res/layout/sensor_main.xml index 1117c8401..df48e3163 100644 --- a/app/src/main/res/layout/sensor_main.xml +++ b/app/src/main/res/layout/sensor_main.xml @@ -18,7 +18,7 @@