diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml
new file mode 100644
index 000000000..3ee1ee1b5
--- /dev/null
+++ b/.github/release-drafter.yml
@@ -0,0 +1,19 @@
+name-template: 'PSLab Version $NEXT_PATCH_VERSION'
+tag-template: 'v$NEXT_PATCH_VERSION'
+change-template: '- $TITLE (#$NUMBER) - @$AUTHOR'
+categories:
+ - title: ':rocket: Features and Enhancements'
+ labels:
+ - 'Feature'
+ - 'Enhancement'
+ - title: ':bug: Bug Fixes'
+ label: 'Fix'
+ - title: ':wrench: Maintenance'
+ label: 'Chore'
+ - title: ':page_facing_up: Documentation'
+ label: 'Documentation'
+template: |-
+ ## Changes
+ $CHANGES
+
+ This release was made possible thanks to $CONTRIBUTORS
diff --git a/README.md b/README.md
index 60c13d83c..9980c9310 100644
--- a/README.md
+++ b/README.md
@@ -9,6 +9,10 @@
[![Mailing List](https://img.shields.io/badge/Mailing%20List-FOSSASIA-blue.svg)](https://groups.google.com/forum/#!forum/pslab-fossasia)
[![Twitter Follow](https://img.shields.io/twitter/follow/pslabio.svg?style=social&label=Follow&maxAge=2592000?style=flat-square)](https://twitter.com/pslabio)
+![Minimum API Level](https://img.shields.io/badge/Min%20API%20Level-23-green)
+![Maximum API Level](https://img.shields.io/badge/Max%20API%20Level-28-orange)
+![GitHub repo size](https://img.shields.io/github/repo-size/fossasia/pslab-android)
+
This repository holds the Android App for performing experiments with [PSLab](https://pslab.io/). PSLab is a tiny pocket science lab that provides an array of equipment for doing science and engineering experiments. It can function like an oscilloscope, waveform generator, frequency counter, programmable voltage and current source and also as a data logger. Our website is at https://pslab.io
## Communication
@@ -19,8 +23,8 @@ Please join us on the following channels:
## Roadmap
- [x] First we need to get communication between Android App and PSLab working.
- - [ ] Implement Applications and expose PSLab Hardware functionality to the user.
- - [ ] Implement Functionality to Perform Experiment using PSLab Hardware Device.
+ - [x] Implement Applications and expose PSLab Hardware functionality to the user.
+ - [ ] Implement wireless connectivity
## Screenshots
@@ -54,8 +58,8 @@ Please join us on the following channels:
@@ -82,7 +86,8 @@ Please join us on the following channels:
@@ -93,27 +98,35 @@ Please join us on the following channels:
- [Generating and Observing Waveforms Using Pocket Science Lab](https://www.youtube.com/watch?v=Ua9_OCR4p8Y)
## Features
-| **Feature** | **Description** | **Status** |
-|------------------|-------------------------------------------------------|-----------------|
-| Home Screen | Show status and version of PSLab device | ✓ |
-| Instruments | Exposes PSLab instruments like Oscilloscope, etc | ✓ |
-| Oscilloscope | Shows variation of analog signals | ✓ |
-| Multimeter | Measures voltage, current, resistance and capacitance | ✓ |
-| Logical Analyzer | Captures and displays signals from digital system | ✓ |
-| Wave Generator | Generates arbitrary analog and digital waveforms | ✓ |
-| Power Source | Generates programmable voltage and currents | ✓ |
-| Lux Meter | Measures the ambient light intensity | ✓ |
-| Baro Meter | Measures the Pressure | ✓ |
-| AcceleroMeter | Measures the acceleration of the device | ✓ |
-| Gyro Meter | Measures the rate of rotation | ✓ |
-| Compass | Measures the absolute rotation relative to earth magnetic poles | ✓ |
-| Thermometer | Measures the ambient temperature | |
-| Robotic Arm Controller | Allows to control 4 servo motors of the robotic arm | |
+| **Feature** | **Description** | **Status** |
+|------------------------|-------------------------------------------------------------------|--------------------|
+| Home Screen | Show status and version of PSLab device | :heavy_check_mark: |
+| Instruments | Exposes PSLab instruments like Oscilloscope, etc | :heavy_check_mark: |
+| Oscilloscope | Shows variation of analog signals | :heavy_check_mark: |
+| Multimeter | Measures voltage, current, resistance and capacitance | :heavy_check_mark: |
+| Logical Analyzer | Captures and displays signals from digital system | :heavy_check_mark: |
+| Wave Generator | Generates arbitrary analog and digital waveforms | :heavy_check_mark: |
+| Power Source | Generates programmable voltage and currents | :heavy_check_mark: |
+| Lux Meter | Measures the ambient light intensity | :heavy_check_mark: |
+| Baro Meter | Measures the Pressure | :heavy_check_mark: |
+| AcceleroMeter | Measures the acceleration of the device | :heavy_check_mark: |
+| Gyro Meter | Measures the rate of rotation | :heavy_check_mark: |
+| Compass | Measures the absolute rotation relative to earth magnetic poles | :heavy_check_mark: |
+| Thermometer | Measures the ambient temperature | :heavy_check_mark: |
+| Gas Sensor | Detects gases, including NH3, NOx, alcohol, benzene, smoke and CO2| :heavy_check_mark: |
+| Robotic Arm Controller | Allows to control 4 servo motors of the robotic arm independently | :heavy_check_mark: |
+
## How to set up the Android app in your development environment
- Minimum Android version 5.0 (API Level 21)
- Maximum Android version 8.1 (API Level 27)
+### Application Flavors
+
+There are 2 flavors (build variants) of PSLab Android application.
+
+1. #### Play Store Flavor
+ - Play Store flavor uses Google Maps to display location stored in logs in Data logger.
+2. #### Fdroid Flavors
+ - Fdroid flavor uses Open Street Maps to display location stored in logs in Data logger.
### Development Setup
diff --git a/app/build.gradle b/app/build.gradle
index a1bb8b692..a23481f1b 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -13,8 +13,8 @@ android {
applicationId "io.pslab"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
- versionCode 18
- versionName "2.0.17"
+ versionCode 19
+ versionName "2.0.18"
multiDexEnabled true
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
@@ -107,6 +107,8 @@ dependencies {
implementation 'com.github.GoodieBag:ProtractorView:v1.2'
implementation 'com.github.Triggertrap:SeekArc:v1.1'
+ implementation "com.squareup.okhttp3:okhttp:$rootProject.okHttpVersion"
+
implementation "com.jakewharton:butterknife:$rootProject.butterKnifeVersion"
annotationProcessor "com.jakewharton:butterknife-compiler:$rootProject.butterKnifeVersion"
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 3dafc0da1..0a6a4a3c2 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -99,6 +99,9 @@
+
diff --git a/app/src/main/java/io/pslab/activity/DataLoggerActivity.java b/app/src/main/java/io/pslab/activity/DataLoggerActivity.java
index 34129322e..0162b5188 100644
--- a/app/src/main/java/io/pslab/activity/DataLoggerActivity.java
+++ b/app/src/main/java/io/pslab/activity/DataLoggerActivity.java
@@ -34,7 +34,9 @@
import io.pslab.models.AccelerometerData;
import io.pslab.models.BaroData;
import io.pslab.models.CompassData;
+import io.pslab.models.GasSensorData;
import io.pslab.models.GyroData;
+import io.pslab.models.LogicAnalyzerData;
import io.pslab.models.LuxData;
import io.pslab.models.OscilloscopeData;
import io.pslab.models.PowerSourceData;
@@ -120,6 +122,12 @@ protected void onCreate(Bundle savedInstanceState) {
case "Power Source":
categoryData = LocalDataLog.with().getTypeOfSensorBlocks(getResources().getString(R.string.power_source));
break;
+ case "Logic Analyzer":
+ categoryData = LocalDataLog.with().getTypeOfSensorBlocks(getResources().getString(R.string.logical_analyzer));
+ break;
+ case "Gas Sensor":
+ categoryData = LocalDataLog.with().getTypeOfSensorBlocks(getString(R.string.gas_sensor));
+ break;
default:
categoryData = LocalDataLog.with().getAllSensorBlocks();
getSupportActionBar().setTitle(getString(R.string.logged_data));
@@ -253,7 +261,7 @@ private RealmObject getObject(String objectType, String[] data, long time, long
returnObject = new LuxData(time, block, Float.valueOf(data[2]), Double.valueOf(data[3]), Double.valueOf(data[4]));
break;
case "Barometer":
- returnObject = new BaroData(time, block, Float.valueOf(data[2]), Double.valueOf(data[3]), Double.valueOf(data[4]));
+ returnObject = new BaroData(time, block, Float.valueOf(data[2]), Float.valueOf(data[3]), Double.valueOf(data[4]), Double.valueOf(data[5]));
break;
case "Accelerometer":
returnObject = new AccelerometerData(time, block, Float.valueOf(data[2]), Float.valueOf(data[3]), Float.valueOf(data[4]), Double.valueOf(data[5]), Double.valueOf(data[6]));
@@ -279,6 +287,12 @@ private RealmObject getObject(String objectType, String[] data, long time, long
case "Power Source":
returnObject = new PowerSourceData(time, block, Float.valueOf(data[2]), Float.valueOf(data[3]), Float.valueOf(data[4]), Float.valueOf(data[5]), Float.valueOf(data[6]), Float.valueOf(data[7]));
break;
+ case "Logic Analyzer":
+ returnObject = new LogicAnalyzerData(time, block, data[2], Integer.valueOf(data[3]), data[4], data[5], Float.valueOf(data[6]), Float.valueOf(data[7]));
+ break;
+ case "Gas Sensor":
+ returnObject = new GasSensorData(time, block, Float.valueOf(data[2]), Double.valueOf(data[3]), Double.valueOf(data[4]));
+ break;
default:
returnObject = null;
break;
diff --git a/app/src/main/java/io/pslab/activity/GasSensorActivity.java b/app/src/main/java/io/pslab/activity/GasSensorActivity.java
new file mode 100644
index 000000000..dcea3bdc3
--- /dev/null
+++ b/app/src/main/java/io/pslab/activity/GasSensorActivity.java
@@ -0,0 +1,100 @@
+package io.pslab.activity;
+
+import android.content.SharedPreferences;
+import android.support.v4.app.Fragment;
+
+import io.pslab.R;
+import io.pslab.fragment.GasSensorDataFragment;
+import io.pslab.models.GasSensorData;
+import io.pslab.models.PSLabSensor;
+import io.pslab.models.SensorDataBlock;
+import io.pslab.others.LocalDataLog;
+import io.realm.RealmObject;
+import io.realm.RealmResults;
+
+public class GasSensorActivity extends PSLabSensor {
+
+ private static final String PREF_NAME = "customDialogPreference";
+ public RealmResults recordedGasSensorData;
+
+ @Override
+ public int getMenu() {
+ return R.menu.sensor_data_log_menu;
+ }
+
+ @Override
+ public SharedPreferences getStateSettings() {
+ return this.getSharedPreferences(PREF_NAME, MODE_PRIVATE);
+
+ }
+
+ @Override
+ public String getFirstTimeSettingID() {
+ return "GasSensorFirstTime";
+ }
+
+ @Override
+ public String getSensorName() {
+ return getResources().getString(R.string.gas_sensor);
+ }
+
+ @Override
+ public int getGuideTitle() {
+ return R.string.gas_sensor;
+ }
+
+ @Override
+ public int getGuideAbstract() {
+ return R.string.gas_sensor;
+ }
+
+ @Override
+ public int getGuideSchematics() {
+ return R.drawable.bmp180_schematic;
+ }
+
+ @Override
+ public int getGuideDescription() {
+ return R.string.gas_sensor;
+ }
+
+ @Override
+ public int getGuideExtraContent() {
+ return 0;
+ }
+
+ @Override
+ public void recordSensorDataBlockID(SensorDataBlock block) {
+ realm.beginTransaction();
+ realm.copyToRealm(block);
+ realm.commitTransaction();
+ }
+
+ @Override
+ public void recordSensorData(RealmObject sensorData) {
+ realm.beginTransaction();
+ realm.copyToRealm((GasSensorData) sensorData);
+ realm.commitTransaction();
+ }
+
+ @Override
+ public void stopRecordSensorData() {
+ LocalDataLog.with().refresh();
+ }
+
+ @Override
+ public Fragment getSensorFragment() {
+ return GasSensorDataFragment.newInstance();
+ }
+
+ @Override
+ public void getDataFromDataLogger() {
+ if (getIntent().getExtras() != null && getIntent().getExtras().getBoolean(KEY_LOG)) {
+ viewingData = true;
+ recordedGasSensorData = LocalDataLog.with()
+ .getBlockOfGasSensorRecords(getIntent().getExtras().getLong(DATA_BLOCK));
+ String title = titleFormat.format(recordedGasSensorData.get(0).getTime());
+ getSupportActionBar().setTitle(title);
+ }
+ }
+}
diff --git a/app/src/main/java/io/pslab/activity/LogicalAnalyzerActivity.java b/app/src/main/java/io/pslab/activity/LogicalAnalyzerActivity.java
index d5152d553..31efdc317 100644
--- a/app/src/main/java/io/pslab/activity/LogicalAnalyzerActivity.java
+++ b/app/src/main/java/io/pslab/activity/LogicalAnalyzerActivity.java
@@ -9,7 +9,6 @@
import android.support.design.widget.BottomSheetBehavior;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
-import android.support.v7.widget.TooltipCompat;
import android.view.GestureDetector;
import android.view.MenuItem;
import android.view.MotionEvent;
@@ -23,12 +22,15 @@
import io.pslab.R;
import io.pslab.communication.ScienceLab;
import io.pslab.fragment.LALogicLinesFragment;
+import io.pslab.models.LogicAnalyzerData;
+import io.pslab.others.LocalDataLog;
import io.pslab.others.MathUtils;
import io.pslab.others.ScienceLabCommon;
import butterknife.BindView;
import butterknife.ButterKnife;
import io.pslab.others.SwipeGestureDetector;
+import io.realm.RealmResults;
/**
* Created by viveksb007 on 10/5/17.
@@ -56,6 +58,11 @@ public class LogicalAnalyzerActivity extends AppCompatActivity {
private GestureDetector gestureDetector;
private TextView showText;
private boolean btnLongpressed;
+ private final String KEY_LOG = "has_log";
+ private final String DATA_BLOCK = "data_block";
+ public boolean isPlayback = false;
+ public RealmResults recordedLAData;
+
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
@@ -124,6 +131,12 @@ public boolean onTouch(View v, MotionEvent event) {
return true;
}
});
+
+ if (getIntent().getExtras() != null && getIntent().getExtras().getBoolean(KEY_LOG)) {
+ recordedLAData = LocalDataLog.with()
+ .getBlockOfLARecords(getIntent().getExtras().getLong(DATA_BLOCK));
+ isPlayback = true;
+ }
}
@Override
diff --git a/app/src/main/java/io/pslab/activity/MainActivity.java b/app/src/main/java/io/pslab/activity/MainActivity.java
index 53f7109c0..ba056b789 100644
--- a/app/src/main/java/io/pslab/activity/MainActivity.java
+++ b/app/src/main/java/io/pslab/activity/MainActivity.java
@@ -24,6 +24,7 @@
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
+import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
@@ -41,6 +42,7 @@
import io.pslab.communication.CommunicationHandler;
import io.pslab.fragment.AboutUsFragment;
import io.pslab.fragment.BluetoothScanFragment;
+import io.pslab.fragment.ESPFragment;
import io.pslab.fragment.FAQFragment;
import io.pslab.fragment.HomeFragment;
import io.pslab.fragment.InstrumentsFragment;
@@ -406,13 +408,43 @@ private void attemptToConnectPSLab() {
initialisationDialog.dismiss();
Toast.makeText(this, getString(R.string.device_not_found), Toast.LENGTH_SHORT).show();
AlertDialog dialog = new AlertDialog.Builder(MainActivity.this)
- .setMessage(getResources().getString(R.string.bluetooth_scan_dialog))
+ .setMessage(getResources().getString(R.string.bluetooth_wifi_scan_dialog))
.setPositiveButton(getResources().getString(R.string.bluetooth_scan_text), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
- BluetoothScanFragment bluetoothScanFragment = new BluetoothScanFragment();
- bluetoothScanFragment.show(getSupportFragmentManager(), "bluetooth");
- bluetoothScanFragment.setCancelable(true);
+ AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(MainActivity.this);
+ LayoutInflater inflater = MainActivity.this.getLayoutInflater();
+ View dialogView = inflater.inflate(R.layout.bluetooth_wifi_dialog_layout, null);
+ dialogBuilder.setNegativeButton(getResources().getString(R.string.cancel), new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialogInterface, int i) {
+ dialog.cancel();
+ }
+ });
+
+ dialogView.findViewById(R.id.bluetooth_btn).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ BluetoothScanFragment bluetoothScanFragment = new BluetoothScanFragment();
+ bluetoothScanFragment.show(getSupportFragmentManager(), "bluetooth");
+ bluetoothScanFragment.setCancelable(true);
+ dialog.cancel();
+ }
+ });
+
+ dialogView.findViewById(R.id.wifi_btn).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ ESPFragment espFragment = new ESPFragment();
+ espFragment.show(getSupportFragmentManager(), "wifi");
+ espFragment.setCancelable(true);
+ dialog.cancel();
+ }
+ });
+
+ dialogBuilder.setView(dialogView)
+ .create()
+ .show();
}
})
.setNegativeButton(getResources().getString(R.string.cancel), new DialogInterface.OnClickListener() {
@@ -420,8 +452,7 @@ public void onClick(DialogInterface dialog, int which) {
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
- })
- .create();
+ }).create();
dialog.show();
}
}
diff --git a/app/src/main/java/io/pslab/activity/OscilloscopeActivity.java b/app/src/main/java/io/pslab/activity/OscilloscopeActivity.java
index 95b2dac40..87e831f7d 100644
--- a/app/src/main/java/io/pslab/activity/OscilloscopeActivity.java
+++ b/app/src/main/java/io/pslab/activity/OscilloscopeActivity.java
@@ -230,10 +230,10 @@ public void onClick(View v) {
mainLayout = findViewById(R.id.oscilloscope_mail_layout);
channelIndexMap = new HashMap<>();
- channelIndexMap.put(CHANNEL.CH1.toString(), 0);
- channelIndexMap.put(CHANNEL.CH2.toString(), 1);
- channelIndexMap.put(CHANNEL.CH3.toString(), 2);
- channelIndexMap.put(CHANNEL.MIC.toString(), 3);
+ channelIndexMap.put(CHANNEL.CH1.toString(), 1);
+ channelIndexMap.put(CHANNEL.CH2.toString(), 2);
+ channelIndexMap.put(CHANNEL.CH3.toString(), 3);
+ channelIndexMap.put(CHANNEL.MIC.toString(), 4);
realm = LocalDataLog.with().getRealm();
gpsLogger = new GPSLogger(this,
@@ -967,15 +967,15 @@ protected Void doInBackground(String... channels) {
ArrayList yDataString = new ArrayList<>();
String[] xDataString = null;
maxAmp = 0;
+ scienceLab.captureTraces(4, samples, timeGap, channel, isTriggerSelected, null);
+ Thread.sleep((long)(samples*timeGap*1e-3));
for (int i = 0; i < noOfChannels; i++) {
entries.add(new ArrayList<>());
channel = channels[i];
HashMap data;
if (triggerChannel.equals(channel))
scienceLab.configureTrigger(channelIndexMap.get(channel), channel, trigger, null, null);
- scienceLab.captureTraces(1, samples, timeGap, channel, isTriggerSelected, null);
- data = scienceLab.fetchTrace(1);
- Thread.sleep((long) (1000 * 10 * 1e-3));
+ data = scienceLab.fetchTrace(channelIndexMap.get(channel));
xData = data.get("x");
yData = data.get("y");
int n = Math.min(xData.length, yData.length);
diff --git a/app/src/main/java/io/pslab/adapters/SensorLoggerListAdapter.java b/app/src/main/java/io/pslab/adapters/SensorLoggerListAdapter.java
index 64bd68402..5a0473609 100644
--- a/app/src/main/java/io/pslab/adapters/SensorLoggerListAdapter.java
+++ b/app/src/main/java/io/pslab/adapters/SensorLoggerListAdapter.java
@@ -26,7 +26,9 @@
import io.pslab.activity.AccelerometerActivity;
import io.pslab.activity.BarometerActivity;
import io.pslab.activity.CompassActivity;
+import io.pslab.activity.GasSensorActivity;
import io.pslab.activity.GyroscopeActivity;
+import io.pslab.activity.LogicalAnalyzerActivity;
import io.pslab.activity.LuxMeterActivity;
import io.pslab.activity.MapsActivity;
import io.pslab.activity.MultimeterActivity;
@@ -37,8 +39,10 @@
import io.pslab.activity.WaveGeneratorActivity;
import io.pslab.models.AccelerometerData;
import io.pslab.models.BaroData;
+import io.pslab.models.GasSensorData;
import io.pslab.models.GyroData;
import io.pslab.models.CompassData;
+import io.pslab.models.LogicAnalyzerData;
import io.pslab.models.LuxData;
import io.pslab.models.MultimeterData;
import io.pslab.models.OscilloscopeData;
@@ -125,6 +129,14 @@ public void onBindViewHolder(@NonNull final ViewHolder holder, int position) {
holder.sensor.setText(R.string.multimeter);
holder.tileIcon.setImageDrawable(context.getResources().getDrawable(R.drawable.tile_icon_multimeter));
break;
+ case PSLabSensor.LOGIC_ANALYZER:
+ holder.sensor.setText(R.string.logical_analyzer);
+ holder.tileIcon.setImageDrawable(context.getResources().getDrawable(R.drawable.tile_icon_logic_analyzer));
+ break;
+ case PSLabSensor.GAS_SENSOR:
+ holder.sensor.setText(R.string.gas_sensor);
+ holder.tileIcon.setImageDrawable(context.getResources().getDrawable(R.drawable.robotic_arm));
+ break;
default:
break;
}
@@ -205,6 +217,16 @@ private void handleCardViewClick(SensorDataBlock block) {
multimeter.putExtra(KEY_LOG, true);
multimeter.putExtra(DATA_BLOCK, block.getBlock());
context.startActivity(multimeter);
+ } else if (block.getSensorType().equalsIgnoreCase(context.getResources().getString(R.string.logical_analyzer))) {
+ Intent laIntent = new Intent(context, LogicalAnalyzerActivity.class);
+ laIntent.putExtra(KEY_LOG, true);
+ laIntent.putExtra(DATA_BLOCK, block.getBlock());
+ context.startActivity(laIntent);
+ } else if (block.getSensorType().equalsIgnoreCase(context.getResources().getString(R.string.gas_sensor))) {
+ Intent gasSensorIntent = new Intent(context, GasSensorActivity.class);
+ gasSensorIntent.putExtra(KEY_LOG, true);
+ gasSensorIntent.putExtra(DATA_BLOCK, block.getBlock());
+ context.startActivity(gasSensorIntent);
}
}
@@ -244,6 +266,10 @@ public void onClick(DialogInterface dialog, int whichButton) {
LocalDataLog.with().clearBlockOfPowerRecords(block.getBlock());
} else if (block.getSensorType().equalsIgnoreCase(PSLabSensor.MULTIMETER)) {
LocalDataLog.with().clearBlockOfMultimeterRecords(block.getBlock());
+ } else if (block.getSensorType().equalsIgnoreCase(PSLabSensor.LOGIC_ANALYZER)) {
+ LocalDataLog.with().clearBlockOfLARecords(block.getBlock());
+ } else if (block.getSensorType().equalsIgnoreCase(PSLabSensor.GAS_SENSOR)) {
+ LocalDataLog.with().clearBlockOfGasSensorRecords(block.getBlock());
}
LocalDataLog.with().clearSensorBlock(block.getBlock());
dialog.dismiss();
@@ -287,6 +313,7 @@ private void populateMapData(SensorDataBlock block) {
JSONObject i = new JSONObject();
i.put("date", CSVLogger.FILE_NAME_FORMAT.format(d.getTime()));
i.put("data", d.getBaro());
+ i.put("altitude", d.getAltitude());
i.put("lon", d.getLon());
i.put("lat", d.getLat());
if (d.getLat() != 0.0 && d.getLon() != 0.0) array.put(i);
@@ -461,6 +488,41 @@ private void populateMapData(SensorDataBlock block) {
}
}
setMapDataToIntent(array);
+ } else if (block.getSensorType().equalsIgnoreCase(PSLabSensor.LOGIC_ANALYZER)) {
+ RealmResults data = LocalDataLog.with().getBlockOfLARecords(block.getBlock());
+ JSONArray array = new JSONArray();
+ for (LogicAnalyzerData d : data) {
+ try {
+ JSONObject i = new JSONObject();
+ i.put("date", CSVLogger.FILE_NAME_FORMAT.format(d.getTime()));
+ i.put("channel", d.getChannel());
+ i.put("channel_mode", d.getChannelMode());
+ i.put("xaxis", d.getDataX());
+ i.put("yaxis", d.getDataY());
+ i.put("lat", d.getLat());
+ i.put("lon", d.getLon());
+ if (d.getLat() != 0.0 && d.getLon() != 0.0) array.put(i);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ }
+ setMapDataToIntent(array);
+ } else if (block.getSensorType().equalsIgnoreCase(PSLabSensor.GAS_SENSOR)) {
+ RealmResults data = LocalDataLog.with().getBlockOfGasSensorRecords(block.getBlock());
+ JSONArray array = new JSONArray();
+ for (GasSensorData d : data) {
+ try {
+ JSONObject i = new JSONObject();
+ i.put("date", CSVLogger.FILE_NAME_FORMAT.format(d.getTime()));
+ i.put("ppmValue", d.getPpmValue());
+ 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/BaroMeterDataFragment.java b/app/src/main/java/io/pslab/fragment/BaroMeterDataFragment.java
index 0ad02a6a5..1e557c8f5 100644
--- a/app/src/main/java/io/pslab/fragment/BaroMeterDataFragment.java
+++ b/app/src/main/java/io/pslab/fragment/BaroMeterDataFragment.java
@@ -29,6 +29,7 @@
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.data.LineDataSet;
+import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;
import java.io.File;
import java.io.FileNotFoundException;
@@ -36,6 +37,7 @@
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
+import java.util.List;
import java.util.Locale;
import java.util.Timer;
import java.util.TimerTask;
@@ -87,21 +89,26 @@ private enum BARO_SENSOR {INBUILT_SENSOR, BMP180_SENSOR}
LineChart mChart;
@BindView(R.id.baro_meter)
PointerSpeedometer baroMeter;
+ @BindView(R.id.alti_value)
+ TextView altiValue;
private Timer graphTimer;
private SensorManager sensorManager;
private Sensor sensor;
private long startTime, block;
- private ArrayList entries;
+ private ArrayList pressureEntries;
+ private ArrayList altitudeEntries;
private ArrayList recordedBaroArray;
private BaroData sensorData;
private float currentMin = 2;
private float currentMax = 0.5f;
private YAxis y;
+ private YAxis y2;
private Unbinder unbinder;
private long previousTimeElapsed = (System.currentTimeMillis() - startTime) / updatePeriod;
private BarometerActivity baroSensor;
private View rootView;
+ private String csvHeader = "Timestamp,DateTime,Pressure,Altitude,Latitude,Longitude";
public static BaroMeterDataFragment newInstance() {
return new BaroMeterDataFragment();
@@ -117,7 +124,8 @@ public static void setParameters(float highLimit, int updatePeriod, String type)
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
startTime = System.currentTimeMillis();
- entries = new ArrayList<>();
+ pressureEntries = new ArrayList<>();
+ altitudeEntries = new ArrayList<>();
baroSensor = (BarometerActivity) getActivity();
}
@@ -149,7 +157,8 @@ public void onResume() {
count = 0;
currentMin = 2;
currentMax = 0.5f;
- entries.clear();
+ pressureEntries.clear();
+ altitudeEntries.clear();
mChart.clear();
mChart.invalidate();
initiateBaroSensor(sensorType);
@@ -181,7 +190,9 @@ private void plotAllRecordedData() {
currentMin = d.getBaro();
}
Entry entry = new Entry((float) (d.getTime() - d.getBlock()) / 1000, d.getBaro());
- entries.add(entry);
+ pressureEntries.add(entry);
+ altitudeEntries.add(new Entry((float) (d.getTime() - d.getBlock()) / 1000, d.getAltitude()));
+ altiValue.setText(String.format(Locale.getDefault(), PSLabSensor.BAROMETER_DATA_FORMAT, d.getAltitude()));
baroMeter.setWithTremble(false);
baroMeter.setSpeedAt(d.getBaro());
sum += entry.getY();
@@ -189,15 +200,27 @@ private void plotAllRecordedData() {
y.setAxisMaximum(currentMax);
y.setAxisMinimum(currentMin);
y.setLabelCount(10);
+ y2.setAxisMaximum(getAltitude(currentMax));
+ y2.setAxisMinimum(getAltitude(currentMin));
+ y2.setLabelCount(10);
statMax.setText(String.format(Locale.getDefault(), PSLabSensor.BAROMETER_DATA_FORMAT, currentMax));
statMin.setText(String.format(Locale.getDefault(), PSLabSensor.BAROMETER_DATA_FORMAT, currentMin));
statMean.setText(String.format(Locale.getDefault(), PSLabSensor.BAROMETER_DATA_FORMAT, (sum / recordedBaroArray.size())));
- LineDataSet dataSet = new LineDataSet(entries, getString(R.string.baro_unit));
+ List dataSets = new ArrayList<>();
+ LineDataSet dataSet = new LineDataSet(pressureEntries, getString(R.string.baro_unit));
dataSet.setDrawCircles(false);
dataSet.setDrawValues(false);
dataSet.setLineWidth(2);
- LineData data = new LineData(dataSet);
+ dataSets.add(dataSet);
+
+ dataSet = new LineDataSet(altitudeEntries, getString(R.string.alti_unit));
+ dataSet.setDrawCircles(false);
+ dataSet.setDrawValues(false);
+ dataSet.setLineWidth(2);
+ dataSet.setColor(Color.YELLOW);
+ dataSets.add(dataSet);
+ LineData data = new LineData(dataSets);
mChart.setData(data);
mChart.notifyDataSetChanged();
@@ -251,20 +274,34 @@ public void run() {
y.setAxisMaximum(currentMax);
y.setAxisMinimum(currentMin);
y.setLabelCount(10);
+ y2.setAxisMaximum(getAltitude(currentMax));
+ y2.setAxisMinimum(getAltitude(currentMin));
+ y2.setLabelCount(10);
baroMeter.setWithTremble(false);
baroMeter.setSpeedAt(d.getBaro());
Entry entry = new Entry((float) (d.getTime() - d.getBlock()) / 1000, d.getBaro());
- entries.add(entry);
+ pressureEntries.add(entry);
+ altitudeEntries.add(new Entry((float) (d.getTime() - d.getBlock()) / 1000, d.getAltitude()));
count++;
sum += entry.getY();
statMean.setText(DataFormatter.formatDouble((sum / count), PSLabSensor.BAROMETER_DATA_FORMAT));
+ altiValue.setText(String.format(Locale.getDefault(), PSLabSensor.BAROMETER_DATA_FORMAT, d.getAltitude()));
- LineDataSet dataSet = new LineDataSet(entries, getString(R.string.baro_unit));
+ List dataSets = new ArrayList<>();
+ LineDataSet dataSet = new LineDataSet(pressureEntries, getString(R.string.baro_unit));
dataSet.setDrawCircles(false);
dataSet.setDrawValues(false);
dataSet.setLineWidth(2);
- LineData data = new LineData(dataSet);
+ dataSets.add(dataSet);
+
+ dataSet = new LineDataSet(altitudeEntries, getString(R.string.alti_unit));
+ dataSet.setDrawCircles(false);
+ dataSet.setDrawValues(false);
+ dataSet.setLineWidth(2);
+ dataSet.setColor(Color.YELLOW);
+ dataSets.add(dataSet);
+ LineData data = new LineData(dataSets);
mChart.setData(data);
mChart.notifyDataSetChanged();
@@ -309,7 +346,7 @@ public void stopData() {
graphTimer = null;
}
recordedBaroArray.clear();
- entries.clear();
+ pressureEntries.clear();
plotAllRecordedData();
baroSensor.startedPlay = false;
baroSensor.playingData = false;
@@ -320,11 +357,12 @@ public void stopData() {
public void saveGraph() {
baroSensor.csvLogger.prepareLogFile();
baroSensor.csvLogger.writeMetaData(getResources().getString(R.string.baro_meter));
- baroSensor.csvLogger.writeCSVFile("Timestamp,DateTime,Readings,Latitude,Longitude");
+ baroSensor.csvLogger.writeCSVFile(csvHeader);
for (BaroData baroData : baroSensor.recordedBaroData) {
baroSensor.csvLogger.writeCSVFile(baroData.getTime() + ","
+ CSVLogger.FILE_NAME_FORMAT.format(new Date(baroData.getTime())) + ","
+ baroData.getBaro() + ","
+ + baroData.getAltitude() + ","
+ baroData.getLat() + ","
+ baroData.getLon());
}
@@ -343,7 +381,7 @@ private void setupInstruments() {
baroMeter.setMaxSpeed(PreferenceManager.getDefaultSharedPreferences(getActivity()).getFloat(baroSensor.BAROMETER_LIMIT, 2));
XAxis x = mChart.getXAxis();
this.y = mChart.getAxisLeft();
- YAxis y2 = mChart.getAxisRight();
+ this.y2 = mChart.getAxisRight();
mChart.setTouchEnabled(true);
mChart.setHighlightPerDragEnabled(true);
@@ -372,8 +410,11 @@ private void setupInstruments() {
y.setDrawGridLines(true);
y.setLabelCount(10);
- y2.setDrawGridLines(false);
- y2.setMaxWidth(0);
+ y2.setTextColor(Color.WHITE);
+ y2.setAxisMinimum(getAltitude(currentMin));
+ y2.setAxisMaximum(getAltitude(currentMax));
+ y2.setDrawGridLines(true);
+ y2.setLabelCount(10);
}
@Override
@@ -416,7 +457,7 @@ private void writeLogToFile(long timestamp, float sensorReading) {
if (getActivity() != null && baroSensor.isRecording) {
if (baroSensor.writeHeaderToFile) {
baroSensor.csvLogger.prepareLogFile();
- baroSensor.csvLogger.writeCSVFile("Timestamp,DateTime,Readings,Latitude,Longitude");
+ baroSensor.csvLogger.writeCSVFile(csvHeader);
block = timestamp;
baroSensor.recordSensorDataBlockID(new SensorDataBlock(timestamp, baroSensor.getSensorName()));
baroSensor.writeHeaderToFile = !baroSensor.writeHeaderToFile;
@@ -425,13 +466,13 @@ private void writeLogToFile(long timestamp, float sensorReading) {
String dateTime = CSVLogger.FILE_NAME_FORMAT.format(new Date(timestamp));
Location location = baroSensor.gpsLogger.getDeviceLocation();
baroSensor.csvLogger.writeCSVFile(timestamp + "," + dateTime + ","
- + sensorReading + "," + location.getLatitude() + "," + location.getLongitude());
- sensorData = new BaroData(timestamp, block, baroValue, location.getLatitude(), location.getLongitude());
+ + sensorReading + "," + getAltitude(sensorReading) + "," + location.getLatitude() + "," + location.getLongitude());
+ sensorData = new BaroData(timestamp, block, baroValue, getAltitude(baroValue), location.getLatitude(), location.getLongitude());
} else {
String dateTime = CSVLogger.FILE_NAME_FORMAT.format(new Date(timestamp));
baroSensor.csvLogger.writeCSVFile(timestamp + "," + dateTime + ","
- + sensorReading + ",0.0,0.0");
- sensorData = new BaroData(timestamp, block, baroValue, 0.0, 0.0);
+ + sensorReading + "," + getAltitude(sensorReading) + ",0.0,0.0");
+ sensorData = new BaroData(timestamp, block, baroValue, getAltitude(baroValue), 0.0, 0.0);
}
baroSensor.recordSensorData(sensorData);
} else {
@@ -451,6 +492,9 @@ private void visualizeData() {
y.setAxisMaximum(currentMax);
y.setAxisMinimum(currentMin);
y.setLabelCount(10);
+ y2.setAxisMaximum(getAltitude(currentMax));
+ y2.setAxisMinimum(getAltitude(currentMin));
+ y2.setLabelCount(10);
if (baroValue >= 0) {
baroMeter.setWithTremble(false);
baroMeter.setSpeedAt(baroValue);
@@ -465,16 +509,28 @@ private void visualizeData() {
Entry entry = new Entry((float) timeElapsed, baroValue);
Long currentTime = System.currentTimeMillis();
writeLogToFile(currentTime, baroValue);
- entries.add(entry);
+ pressureEntries.add(entry);
+ altitudeEntries.add(new Entry((float) timeElapsed, getAltitude(baroValue)));
count++;
sum += entry.getY();
statMean.setText(DataFormatter.formatDouble((sum / count), PSLabSensor.BAROMETER_DATA_FORMAT));
- LineDataSet dataSet = new LineDataSet(entries, getString(R.string.baro_unit));
+ altiValue.setText(String.format(Locale.getDefault(), PSLabSensor.BAROMETER_DATA_FORMAT, getAltitude(baroValue)));
+
+ List dataSets = new ArrayList<>();
+ LineDataSet dataSet = new LineDataSet(pressureEntries, getString(R.string.baro_unit));
dataSet.setDrawCircles(false);
dataSet.setDrawValues(false);
dataSet.setLineWidth(2);
- LineData data = new LineData(dataSet);
+ dataSets.add(dataSet);
+
+ dataSet = new LineDataSet(altitudeEntries, getString(R.string.alti_unit));
+ dataSet.setDrawCircles(false);
+ dataSet.setDrawValues(false);
+ dataSet.setLineWidth(2);
+ dataSet.setColor(Color.YELLOW);
+ dataSets.add(dataSet);
+ LineData data = new LineData(dataSets);
mChart.setData(data);
mChart.notifyDataSetChanged();
@@ -512,9 +568,11 @@ private void resetInstrumentData() {
statMax.setText(DataFormatter.formatDouble(0, DataFormatter.LOW_PRECISION_FORMAT));
statMin.setText(DataFormatter.formatDouble(0, DataFormatter.LOW_PRECISION_FORMAT));
statMean.setText(DataFormatter.formatDouble(0, DataFormatter.LOW_PRECISION_FORMAT));
+ altiValue.setText(DataFormatter.formatDouble(0, DataFormatter.LOW_PRECISION_FORMAT));
baroMeter.setSpeedAt(0);
baroMeter.setWithTremble(false);
- entries.clear();
+ pressureEntries.clear();
+ altitudeEntries.clear();
}
private void initiateBaroSensor(int type) {
@@ -564,4 +622,12 @@ private void initiateBaroSensor(int type) {
break;
}
}
+
+ private float getAltitude(float pressure) {
+ if (pressure <= 0.0) {
+ return 0;
+ } else {
+ return (float) (44330 * (1 - Math.pow(pressure, 1.0 / 5.255)));
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/io/pslab/fragment/ESPFragment.java b/app/src/main/java/io/pslab/fragment/ESPFragment.java
new file mode 100644
index 000000000..00ac88e71
--- /dev/null
+++ b/app/src/main/java/io/pslab/fragment/ESPFragment.java
@@ -0,0 +1,99 @@
+package io.pslab.fragment;
+
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v4.app.DialogFragment;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.ProgressBar;
+import android.widget.Toast;
+
+import java.io.IOException;
+
+import io.pslab.R;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
+
+public class ESPFragment extends DialogFragment {
+ private String espIPAddress = "";
+ private ProgressBar espConnectProgressBar;
+ private Button espConnectBtn;
+
+ @Override
+ public void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ }
+
+ @Nullable
+ @Override
+ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
+ View rootView = inflater.inflate(R.layout.fragment_esp, container, false);
+ EditText espIPEditText = rootView.findViewById(R.id.esp_ip_edit_text);
+ espConnectBtn = rootView.findViewById(R.id.esp_connect_btn);
+ espConnectProgressBar = rootView.findViewById(R.id.esp_connect_progressbar);
+ espConnectBtn.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ espIPAddress = espIPEditText.getText().toString();
+ if (espIPAddress.length() == 0) {
+ Toast.makeText(getContext(), getResources().getString(R.string.incorrect_IP_address_message), Toast.LENGTH_SHORT).show();
+ } else {
+ new ESPTask().execute();
+ }
+ }
+ });
+ return rootView;
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ ViewGroup.LayoutParams params = getDialog().getWindow().getAttributes();
+ params.height = ViewGroup.LayoutParams.WRAP_CONTENT;
+ params.width = ViewGroup.LayoutParams.MATCH_PARENT;
+ getDialog().getWindow().setAttributes((android.view.WindowManager.LayoutParams) params);
+ }
+
+ private class ESPTask extends AsyncTask {
+
+ @Override
+ protected void onPreExecute() {
+ espConnectBtn.setVisibility(View.GONE);
+ espConnectProgressBar.setVisibility(View.VISIBLE);
+ }
+
+ @Override
+ protected String doInBackground(Void... voids) {
+ String result = "";
+ try {
+ OkHttpClient client = new OkHttpClient();
+ Request request = new Request.Builder()
+ .url("http://" + espIPAddress)
+ .build();
+ Response response = client.newCall(request).execute();
+ result = response.body().string();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return result;
+ }
+
+ @Override
+ protected void onPostExecute(String result) {
+ espConnectProgressBar.setVisibility(View.GONE);
+ espConnectBtn.setVisibility(View.VISIBLE);
+ if (result.length() == 0) {
+ Toast.makeText(getContext(), getResources().getString(R.string.incorrect_IP_address_message), Toast.LENGTH_SHORT).show();
+ } else {
+ Log.v("Response", result);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/pslab/fragment/GasSensorDataFragment.java b/app/src/main/java/io/pslab/fragment/GasSensorDataFragment.java
new file mode 100644
index 000000000..b5a1aba6c
--- /dev/null
+++ b/app/src/main/java/io/pslab/fragment/GasSensorDataFragment.java
@@ -0,0 +1,418 @@
+package io.pslab.fragment;
+
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.location.Location;
+import android.os.Bundle;
+import android.os.Environment;
+import android.os.Handler;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.github.anastr.speedviewlib.PointerSpeedometer;
+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.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+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.DataFormatter;
+import io.pslab.R;
+import io.pslab.activity.GasSensorActivity;
+import io.pslab.communication.ScienceLab;
+import io.pslab.models.GasSensorData;
+import io.pslab.models.SensorDataBlock;
+import io.pslab.others.CSVLogger;
+import io.pslab.others.ScienceLabCommon;
+
+import static io.pslab.others.CSVLogger.CSV_DIRECTORY;
+
+public class GasSensorDataFragment extends Fragment {
+
+ @BindView(R.id.gas_sensor_value)
+ TextView gasValue;
+ @BindView(R.id.label_gas_sensor)
+ TextView sensorLabel;
+ @BindView(R.id.chart_gas_sensor)
+ LineChart mChart;
+ @BindView(R.id.gas_sensor)
+ PointerSpeedometer gasSensorMeter;
+ private GasSensorActivity gasSensorActivity;
+ private View rootView;
+ private Unbinder unbinder;
+ private ScienceLab scienceLab;
+ private YAxis y;
+ private Timer graphTimer;
+ private ArrayList entries;
+ private long updatePeriod = 1000;
+ private long startTime;
+ private long timeElapsed;
+ private long previousTimeElapsed = (System.currentTimeMillis() - startTime) / updatePeriod;
+ private long block;
+ private GasSensorData sensorData;
+ private boolean returningFromPause = false;
+ private int turns = 0;
+ private ArrayList recordedGasSensorArray;
+
+
+ public static GasSensorDataFragment newInstance() {
+ return new GasSensorDataFragment();
+ }
+
+ @Override
+ public void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ startTime = System.currentTimeMillis();
+ gasSensorActivity = (GasSensorActivity) getActivity();
+ }
+
+ @Nullable
+ @Override
+ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
+ rootView = inflater.inflate(R.layout.fragment_gas_sensor, container, false);
+ unbinder = ButterKnife.bind(this, rootView);
+ scienceLab = ScienceLabCommon.scienceLab;
+ entries = new ArrayList<>();
+ setupInstruments();
+ return rootView;
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ if (gasSensorActivity.playingData) {
+ sensorLabel.setText(getResources().getString(R.string.baro_meter));
+ recordedGasSensorArray = new ArrayList<>();
+ resetInstrumentData();
+ playRecordedData();
+ } else if (gasSensorActivity.viewingData) {
+ sensorLabel.setText(getResources().getString(R.string.baro_meter));
+ recordedGasSensorArray = new ArrayList<>();
+ resetInstrumentData();
+ plotAllRecordedData();
+ } else if (!gasSensorActivity.isRecording) {
+ updateGraphs();
+ entries.clear();
+ mChart.clear();
+ mChart.invalidate();
+ } else if (returningFromPause) {
+ updateGraphs();
+ }
+ }
+
+ @Override
+ public void onDestroyView() {
+ super.onDestroyView();
+ if (graphTimer != null) {
+ graphTimer.cancel();
+ }
+ unbinder.unbind();
+ }
+
+ private void plotAllRecordedData() {
+ recordedGasSensorArray.addAll(gasSensorActivity.recordedGasSensorData);
+ if (recordedGasSensorArray.size() != 0) {
+ for (GasSensorData d : recordedGasSensorArray) {
+ Entry entry = new Entry((float) (d.getTime() - d.getBlock()) / 1000, d.getPpmValue());
+ entries.add(entry);
+ gasSensorMeter.setWithTremble(false);
+ gasSensorMeter.setSpeedAt(d.getPpmValue());
+ gasValue.setText(String.valueOf(String.format("%.2f", d.getPpmValue())));
+ }
+ y.setAxisMaximum(1024);
+ y.setAxisMinimum(0);
+ y.setLabelCount(10);
+
+ LineDataSet dataSet = new LineDataSet(entries, getString(R.string.baro_unit));
+ dataSet.setDrawCircles(false);
+ dataSet.setDrawValues(false);
+ dataSet.setLineWidth(2);
+ LineData data = new LineData(dataSet);
+
+ mChart.setData(data);
+ mChart.notifyDataSetChanged();
+ mChart.setVisibleXRangeMaximum(80);
+ mChart.moveViewToX(data.getEntryCount());
+ mChart.invalidate();
+ }
+ }
+
+ private void playRecordedData() {
+ recordedGasSensorArray.addAll(gasSensorActivity.recordedGasSensorData);
+ try {
+ if (recordedGasSensorArray.size() > 1) {
+ GasSensorData i = recordedGasSensorArray.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() {
+ if (gasSensorActivity.playingData) {
+ try {
+ GasSensorData d = recordedGasSensorArray.get(turns);
+ turns++;
+ gasValue.setText(String.valueOf(String.format("%.2f", d.getPpmValue())));
+ y.setAxisMaximum(1024);
+ y.setAxisMinimum(0);
+ y.setLabelCount(10);
+ gasSensorMeter.setWithTremble(false);
+ gasSensorMeter.setSpeedAt(d.getPpmValue());
+
+ Entry entry = new Entry((float) (d.getTime() - d.getBlock()) / 1000, d.getPpmValue());
+ entries.add(entry);
+
+ LineDataSet dataSet = new LineDataSet(entries, getString(R.string.baro_unit));
+ dataSet.setDrawCircles(false);
+ dataSet.setDrawValues(false);
+ dataSet.setLineWidth(2);
+ LineData data = new LineData(dataSet);
+
+ mChart.setData(data);
+ mChart.notifyDataSetChanged();
+ mChart.setVisibleXRangeMaximum(80);
+ mChart.moveViewToX(data.getEntryCount());
+ mChart.invalidate();
+ } catch (IndexOutOfBoundsException e) {
+ graphTimer.cancel();
+ graphTimer = null;
+ turns = 0;
+ gasSensorActivity.playingData = false;
+ gasSensorActivity.startedPlay = false;
+ gasSensorActivity.invalidateOptionsMenu();
+ }
+ }
+ }
+ });
+ }
+ }, 0, timeGap);
+ }
+
+ public void playData() {
+ resetInstrumentData();
+ gasSensorActivity.startedPlay = true;
+ try {
+ if (recordedGasSensorArray.size() > 1) {
+ GasSensorData i = recordedGasSensorArray.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();
+ }
+ }
+
+ public void stopData() {
+ if (graphTimer != null) {
+ graphTimer.cancel();
+ graphTimer = null;
+ }
+ recordedGasSensorArray.clear();
+ entries.clear();
+ plotAllRecordedData();
+ gasSensorActivity.startedPlay = false;
+ gasSensorActivity.playingData = false;
+ turns = 0;
+ gasSensorActivity.invalidateOptionsMenu();
+ }
+
+ public void saveGraph() {
+ gasSensorActivity.csvLogger.prepareLogFile();
+ gasSensorActivity.csvLogger.writeMetaData(getResources().getString(R.string.gas_sensor));
+ gasSensorActivity.csvLogger.writeCSVFile("Timestamp,DateTime,ppmValue,Latitude,Longitude");
+ for (GasSensorData baroData : gasSensorActivity.recordedGasSensorData) {
+ gasSensorActivity.csvLogger.writeCSVFile(baroData.getTime() + ","
+ + CSVLogger.FILE_NAME_FORMAT.format(new Date(baroData.getTime())) + ","
+ + baroData.getPpmValue() + ","
+ + baroData.getLat() + ","
+ + baroData.getLon());
+ }
+ View view = rootView.findViewById(R.id.gas_sensor_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 + gasSensorActivity.getSensorName() +
+ File.separator + CSVLogger.FILE_NAME_FORMAT.format(new Date()) + "_graph.jpg"));
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ if (graphTimer != null) {
+ returningFromPause = true;
+ graphTimer.cancel();
+ graphTimer = null;
+ if (gasSensorActivity.playingData) {
+ gasSensorActivity.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) {
+ }
+ }
+ });
+ }
+ }, 0, 1000);
+ }
+
+ private void writeLogToFile(long timestamp, float ppmValue) {
+ if (getActivity() != null && gasSensorActivity.isRecording) {
+ if (gasSensorActivity.writeHeaderToFile) {
+ gasSensorActivity.csvLogger.prepareLogFile();
+ gasSensorActivity.csvLogger.writeCSVFile("Timestamp,DateTime,ppmValue,Latitude,Longitude");
+ block = timestamp;
+ gasSensorActivity.recordSensorDataBlockID(new SensorDataBlock(timestamp, gasSensorActivity.getSensorName()));
+ gasSensorActivity.writeHeaderToFile = !gasSensorActivity.writeHeaderToFile;
+ }
+ if (gasSensorActivity.addLocation && gasSensorActivity.gpsLogger.isGPSEnabled()) {
+ String dateTime = CSVLogger.FILE_NAME_FORMAT.format(new Date(timestamp));
+ Location location = gasSensorActivity.gpsLogger.getDeviceLocation();
+ gasSensorActivity.csvLogger.writeCSVFile(timestamp + "," + dateTime + ","
+ + ppmValue + "," + location.getLatitude() + "," + location.getLongitude());
+ sensorData = new GasSensorData(timestamp, block, ppmValue, location.getLatitude(), location.getLongitude());
+ } else {
+ String dateTime = CSVLogger.FILE_NAME_FORMAT.format(new Date(timestamp));
+ gasSensorActivity.csvLogger.writeCSVFile(timestamp + "," + dateTime + ","
+ + ppmValue + ",0.0,0.0");
+ sensorData = new GasSensorData(timestamp, block, ppmValue, 0.0, 0.0);
+ }
+ gasSensorActivity.recordSensorData(sensorData);
+ } else {
+ gasSensorActivity.writeHeaderToFile = true;
+ }
+ }
+
+ private void visualizeData() {
+ if (scienceLab.isConnected()) {
+ double volt = scienceLab.getVoltage("CH1", 1);
+ double ppmValue = (volt / 3.3) * 1024.0;
+ gasValue.setText(String.valueOf(String.format("%.2f", ppmValue)));
+ gasSensorMeter.setWithTremble(false);
+ gasSensorMeter.setSpeedAt((float) ppmValue);
+ timeElapsed = ((System.currentTimeMillis() - startTime) / updatePeriod);
+ if (timeElapsed != previousTimeElapsed) {
+ previousTimeElapsed = timeElapsed;
+ Entry entry = new Entry((float) timeElapsed, (float) ppmValue);
+ entries.add(entry);
+ writeLogToFile(System.currentTimeMillis(), (float) ppmValue);
+ LineDataSet dataSet = new LineDataSet(entries, getString(R.string.gas_sensor_unit));
+ dataSet.setDrawCircles(false);
+ dataSet.setDrawValues(false);
+ dataSet.setLineWidth(2);
+ LineData data = new LineData(dataSet);
+
+ mChart.setData(data);
+ mChart.notifyDataSetChanged();
+ mChart.setVisibleXRangeMaximum(80);
+ mChart.moveViewToX(data.getEntryCount());
+ mChart.invalidate();
+ }
+ } else {
+ Toast.makeText(getContext(), R.string.not_connected, Toast.LENGTH_SHORT).show();
+ }
+ }
+
+ private void setupInstruments() {
+ gasSensorMeter.setMaxSpeed(1024);
+ XAxis x = mChart.getXAxis();
+ this.y = mChart.getAxisLeft();
+ YAxis y2 = mChart.getAxisRight();
+
+ mChart.setTouchEnabled(true);
+ mChart.setHighlightPerDragEnabled(true);
+ mChart.setDragEnabled(true);
+ mChart.setScaleEnabled(true);
+ mChart.setDrawGridBackground(false);
+ mChart.setPinchZoom(true);
+ mChart.setScaleYEnabled(true);
+ mChart.setBackgroundColor(Color.BLACK);
+ mChart.getDescription().setEnabled(false);
+
+ LineData data = new LineData();
+ mChart.setData(data);
+
+ Legend l = mChart.getLegend();
+ l.setForm(Legend.LegendForm.LINE);
+ l.setTextColor(Color.WHITE);
+
+ x.setTextColor(Color.WHITE);
+ x.setDrawGridLines(true);
+ x.setAvoidFirstLastClipping(true);
+
+ y.setTextColor(Color.WHITE);
+ y.setAxisMaximum(1024);
+ y.setAxisMinimum(0);
+ y.setDrawGridLines(true);
+ y.setLabelCount(10);
+
+ y2.setDrawGridLines(false);
+ y2.setMaxWidth(0);
+ }
+
+ private void resetInstrumentData() {
+ startTime = System.currentTimeMillis();
+ gasValue.setText(DataFormatter.formatDouble(0, DataFormatter.LOW_PRECISION_FORMAT));
+ gasSensorMeter.setSpeedAt(0);
+ gasSensorMeter.setWithTremble(false);
+ entries.clear();
+ }
+}
diff --git a/app/src/main/java/io/pslab/fragment/InstrumentsFragment.java b/app/src/main/java/io/pslab/fragment/InstrumentsFragment.java
index 830d84061..37d3daf8c 100644
--- a/app/src/main/java/io/pslab/fragment/InstrumentsFragment.java
+++ b/app/src/main/java/io/pslab/fragment/InstrumentsFragment.java
@@ -18,6 +18,7 @@
import io.pslab.activity.AccelerometerActivity;
import io.pslab.activity.BarometerActivity;
import io.pslab.activity.CompassActivity;
+import io.pslab.activity.GasSensorActivity;
import io.pslab.activity.GyroscopeActivity;
import io.pslab.activity.LogicalAnalyzerActivity;
import io.pslab.activity.LuxMeterActivity;
@@ -116,6 +117,10 @@ public void onItemClick(ApplicationItem item) {
intent = new Intent(context, RoboticArmActivity.class);
startActivity(intent);
break;
+ case "Gas Sensor":
+ intent = new Intent(context, GasSensorActivity.class);
+ startActivity(intent);
+ break;
default:
break;
}
@@ -161,7 +166,8 @@ protected Void doInBackground(Void... params) {
R.string.compass_description,
R.string.gyroscope_description,
R.string.thermometer_desc,
- R.string.robotic_arm_descriptoin
+ R.string.robotic_arm_description,
+ R.string.gas_sensor_description
};
@@ -202,7 +208,10 @@ protected Void doInBackground(Void... params) {
getResources().getString(R.string.thermometer), R.drawable.thermometer_logo, getResources().getString(descriptions[11])
));
applicationItemList.add(new ApplicationItem(
- getResources().getString(R.string.robotic_arm), R.drawable.robotic_arm, getResources().getString(descriptions[11])
+ getResources().getString(R.string.robotic_arm), R.drawable.robotic_arm, getResources().getString(descriptions[12])
+ ));
+ applicationItemList.add(new ApplicationItem(
+ getResources().getString(R.string.gas_sensor), R.drawable.robotic_arm, getResources().getString(descriptions[13])
));
return null;
}
diff --git a/app/src/main/java/io/pslab/fragment/LALogicLinesFragment.java b/app/src/main/java/io/pslab/fragment/LALogicLinesFragment.java
index 3e1e385a8..a59656ac5 100644
--- a/app/src/main/java/io/pslab/fragment/LALogicLinesFragment.java
+++ b/app/src/main/java/io/pslab/fragment/LALogicLinesFragment.java
@@ -1,22 +1,21 @@
package io.pslab.fragment;
import android.app.Activity;
-import android.content.SharedPreferences;
+import android.content.Context;
+import android.content.Intent;
import android.graphics.Color;
+import android.location.Location;
+import android.location.LocationManager;
import android.os.AsyncTask;
import android.os.Bundle;
-import android.os.Handler;
-import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
-import android.support.design.widget.BottomSheetBehavior;
+import android.support.design.widget.Snackbar;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.util.DisplayMetrics;
import android.util.Log;
-import android.view.GestureDetector;
import android.view.LayoutInflater;
-import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
@@ -40,25 +39,32 @@
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;
import com.github.mikephil.charting.listener.OnChartValueSelectedListener;
-import io.pslab.DataFormatter;
-import io.pslab.R;
-import io.pslab.activity.LogicalAnalyzerActivity;
-import io.pslab.communication.ScienceLab;
-import io.pslab.communication.digitalChannel.DigitalChannel;
-import io.pslab.others.LogicAnalyzerAxisFormatter;
-import io.pslab.others.MathUtils;
-import io.pslab.others.ScienceLabCommon;
-import io.pslab.others.SwipeGestureDetector;
-
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Date;
+import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import butterknife.ButterKnife;
import in.goodiebag.carouselpicker.CarouselPicker;
-
-import static android.content.Context.MODE_PRIVATE;
+import io.pslab.DataFormatter;
+import io.pslab.R;
+import io.pslab.activity.DataLoggerActivity;
+import io.pslab.activity.LogicalAnalyzerActivity;
+import io.pslab.communication.ScienceLab;
+import io.pslab.communication.digitalChannel.DigitalChannel;
+import io.pslab.models.LogicAnalyzerData;
+import io.pslab.models.SensorDataBlock;
+import io.pslab.others.CSVLogger;
+import io.pslab.others.CustomSnackBar;
+import io.pslab.others.GPSLogger;
+import io.pslab.others.LocalDataLog;
+import io.pslab.others.LogicAnalyzerAxisFormatter;
+import io.pslab.others.ScienceLabCommon;
+import io.realm.Realm;
+import io.realm.RealmObject;
+import io.realm.RealmResults;
/**
* Created by viveksb007 on 9/6/17.
@@ -102,6 +108,18 @@ public class LALogicLinesFragment extends Fragment {
private TextView tvTimeUnit, xCoordinateText;
private ImageView ledImageView;
private Runnable logicAnalysis;
+ private Realm realm;
+ private ImageView recordButton;
+ private GPSLogger gpsLogger;
+ private CSVLogger csvLogger;
+ private ArrayList recordXAxis;
+ private ArrayList recordYAxis;
+ private ArrayList recordChannelMode;
+ private String[] channels = new String[]{"ID1", "ID2", "ID3", "ID4"};
+ private HashMap channelMap;
+ private String csvHeader = "Timestamp,DateTime,Channel,ChannelMode,xData,yData,lat,lon";
+ private ArrayList channelSelectSpinners;
+ private ArrayList edgeSelectSpinners;
public static LALogicLinesFragment newInstance(Activity activity) {
LALogicLinesFragment laLogicLinesFragment = new LALogicLinesFragment();
@@ -114,7 +132,14 @@ public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ButterKnife.bind(getActivity());
scienceLab = ScienceLabCommon.scienceLab;
-
+ realm = LocalDataLog.with().getRealm();
+ gpsLogger = new GPSLogger(getContext(), (LocationManager) getContext().getSystemService(Context.LOCATION_SERVICE));
+ csvLogger = new CSVLogger(getString(R.string.logical_analyzer));
+ recordXAxis = new ArrayList<>();
+ recordYAxis = new ArrayList<>();
+ recordChannelMode = new ArrayList<>();
+ channelSelectSpinners = new ArrayList<>();
+ edgeSelectSpinners = new ArrayList<>();
logicAnalysis = new Runnable() {
@Override
public void run() {
@@ -149,7 +174,6 @@ public void run() {
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.logic_analyzer_logic_lines, container, false);
-
// LED Indicator
ledImageView = v.findViewById(R.id.imageView_led_la);
@@ -157,6 +181,52 @@ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
tvTimeUnit = v.findViewById(R.id.la_tv_time_unit);
tvTimeUnit.setText(getString(R.string.time_unit_la));
+ //recordButton
+
+ recordButton = v.findViewById(R.id.la_record_button);
+ recordButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ long block = System.currentTimeMillis();
+ double lat;
+ double lon;
+ if (gpsLogger.isGPSEnabled()) {
+ Location location = gpsLogger.getDeviceLocation();
+ if (location != null) {
+ lat = location.getLatitude();
+ lon = location.getLongitude();
+ } else {
+ lat = 0.0;
+ lon = 0.0;
+ }
+ } else {
+ lat = 0.0;
+ lon = 0.0;
+ }
+ csvLogger.prepareLogFile();
+ csvLogger.writeMetaData(getContext().getResources().getString(R.string.logical_analyzer));
+ csvLogger.writeCSVFile(csvHeader);
+ recordSensorDataBlockID(new SensorDataBlock(block, getResources().getString(R.string.logical_analyzer)));
+ long timestamp = System.currentTimeMillis();
+ String timeData = timestamp + "," + CSVLogger.FILE_NAME_FORMAT.format(new Date(timestamp));
+ String locationData = lat + "," + lon;
+ for (int i = 0; i < recordXAxis.size(); i++) {
+ recordSensorData(new LogicAnalyzerData(timestamp + i, block, channels[i], recordChannelMode.get(i), recordXAxis.get(i), recordYAxis.get(i), lat, lon));
+ String data = timeData + "," + channels[i] + "," + recordChannelMode.get(i) + "," + recordXAxis.get(i) + "," + recordYAxis.get(i) + "," + locationData;
+ csvLogger.writeCSVFile(data);
+ }
+ CustomSnackBar.showSnackBar(v,
+ getString(R.string.csv_store_text) + " " + csvLogger.getCurrentFilePath()
+ , getString(R.string.open), new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getContext(), DataLoggerActivity.class);
+ intent.putExtra(DataLoggerActivity.CALLER_ACTIVITY, getResources().getString(R.string.logical_analyzer));
+ startActivity(intent);
+ }
+ }, Snackbar.LENGTH_SHORT);
+ }
+ });
// Carousel View
carouselPicker = v.findViewById(R.id.carouselPicker);
llChannel1 = v.findViewById(R.id.ll_chart_channel_1);
@@ -177,7 +247,20 @@ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
edgeSelectSpinner4 = v.findViewById(R.id.edge_select_spinner_4);
analyze_button = v.findViewById(R.id.analyze_button);
channelMode = 1;
-
+ channelSelectSpinners.add(channelSelectSpinner1);
+ channelSelectSpinners.add(channelSelectSpinner2);
+ channelSelectSpinners.add(channelSelectSpinner3);
+ channelSelectSpinners.add(channelSelectSpinner4);
+
+ edgeSelectSpinners.add(edgeSelectSpinner1);
+ edgeSelectSpinners.add(edgeSelectSpinner2);
+ edgeSelectSpinners.add(edgeSelectSpinner3);
+ edgeSelectSpinners.add(edgeSelectSpinner4);
+ channelMap = new HashMap<>();
+ channelMap.put(channels[0], 0);
+ channelMap.put(channels[1], 1);
+ channelMap.put(channels[2], 2);
+ channelMap.put(channels[3], 3);
// Axis Indicator
xCoordinateText = v.findViewById(R.id.x_coordinate_text);
xCoordinateText.setText("Time: 0.0 mS");
@@ -200,9 +283,67 @@ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
setCarouselPicker();
setAdapters();
+ LogicalAnalyzerActivity laActivity = (LogicalAnalyzerActivity)getActivity();
+ if (laActivity.isPlayback) {
+ setPlayBackData(laActivity.recordedLAData);
+ }
return v;
}
+ private void setPlayBackData(RealmResults data) {
+ analyze_button.setVisibility(View.GONE);
+ recordButton.setVisibility(View.GONE);
+ currentChannel = 0;
+ setViewVisibility(data.size() - 1);
+ channelNames.clear();
+ disableSpinners();
+ carouselPicker.setCurrentItem(data.size() -1);
+ for (int i = 0; i < data.size(); i ++) {
+ LogicAnalyzerData laData = data.get(i);
+ channelNames.add(laData.getChannel());
+ edgeSelectSpinners.get(i).setSelection(laData.getChannelMode() - 1);
+ channelSelectSpinners.get(i).setSelection(channelMap.get(laData.getChannel()));
+ String[] xPoints = laData.getDataX().split(" ");
+ String[] yPoints = laData.getDataY().split(" ");
+ int n = Math.min(xPoints.length, yPoints.length);
+ double[] xaxis = new double[n];
+ double[] yaxis = new double[n];
+ for (int j = 0; j < n; j ++) {
+ xaxis[j] = Double.valueOf(xPoints[j]);
+ yaxis[j] = Double.valueOf(yPoints[j]);
+ }
+ switch (laData.getChannelMode()) {
+ case 1:
+ singleChannelEveryEdge(xaxis, yaxis);
+ break;
+ case 4:
+ singleChannelFourthRisingEdge(xaxis);
+ break;
+ case 3:
+ singleChannelRisingEdges(xaxis, yaxis);
+ break;
+ case 2:
+ singleChannelFallingEdges(xaxis, yaxis);
+ break;
+ default:
+ singleChannelOtherEdges(xaxis, yaxis);
+ break;
+ }
+ currentChannel ++;
+ }
+ logicLinesChart.setData(new LineData(dataSets));
+ logicLinesChart.invalidate();
+
+ YAxis left = logicLinesChart.getAxisLeft();
+ left.setValueFormatter(new LogicAnalyzerAxisFormatter(channelNames));
+ left.setTextColor(Color.WHITE);
+ left.setGranularity(1f);
+ left.setTextSize(12f);
+ logicLinesChart.getAxisRight().setDrawLabels(false);
+ logicLinesChart.getDescription().setEnabled(false);
+ logicLinesChart.setScaleYEnabled(false);
+ }
+
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
@@ -222,66 +363,7 @@ public void onPageSelected(int position) {
@Override
public void onPageScrollStateChanged(int state) {
if (state == 0) {
- switch (carouselPicker.getCurrentItem()) {
- case 0:
- channelMode = 1;
- setAdapters();
- llChannel1.setVisibility(View.VISIBLE);
- llChannel2.setVisibility(View.GONE);
- llChannel3.setVisibility(View.GONE);
- llChannel4.setVisibility(View.GONE);
- channelSelectSpinner1.setEnabled(true);
- break;
- case 1:
- channelMode = 2;
- setAdapterForTwoChannelMode();
- llChannel1.setVisibility(View.VISIBLE);
- llChannel2.setVisibility(View.VISIBLE);
- llChannel3.setVisibility(View.GONE);
- llChannel4.setVisibility(View.GONE);
- channelSelectSpinner1.setEnabled(true);
- channelSelectSpinner2.setEnabled(true);
- break;
- case 2:
- channelMode = 3;
- setAdapters();
- llChannel1.setVisibility(View.VISIBLE);
- llChannel2.setVisibility(View.VISIBLE);
- llChannel3.setVisibility(View.VISIBLE);
- llChannel4.setVisibility(View.GONE);
- channelSelectSpinner1.setSelection(0);
- channelSelectSpinner2.setSelection(1);
- channelSelectSpinner3.setSelection(2);
- channelSelectSpinner1.setEnabled(false);
- channelSelectSpinner2.setEnabled(false);
- channelSelectSpinner3.setEnabled(false);
- break;
- case 3:
- channelMode = 4;
- setAdapters();
- llChannel1.setVisibility(View.VISIBLE);
- llChannel2.setVisibility(View.VISIBLE);
- llChannel3.setVisibility(View.VISIBLE);
- llChannel4.setVisibility(View.VISIBLE);
- channelSelectSpinner1.setSelection(0);
- channelSelectSpinner2.setSelection(1);
- channelSelectSpinner3.setSelection(2);
- channelSelectSpinner4.setSelection(3);
- channelSelectSpinner1.setEnabled(false);
- channelSelectSpinner2.setEnabled(false);
- channelSelectSpinner3.setEnabled(false);
- channelSelectSpinner4.setEnabled(false);
- break;
- default:
- channelMode = 1;
- setAdapters();
- llChannel1.setVisibility(View.VISIBLE);
- llChannel2.setVisibility(View.GONE);
- llChannel3.setVisibility(View.GONE);
- llChannel4.setVisibility(View.GONE);
- channelSelectSpinner1.setEnabled(true);
- break;
- }
+ setViewVisibility(carouselPicker.getCurrentItem());
}
}
});
@@ -464,6 +546,80 @@ public void onNothingSelected() {
});
}
+ private void disableSpinners() {
+ channelSelectSpinner1.setEnabled(false);
+ channelSelectSpinner2.setEnabled(false);
+ channelSelectSpinner3.setEnabled(false);
+ channelSelectSpinner4.setEnabled(false);
+ edgeSelectSpinner1.setEnabled(false);
+ edgeSelectSpinner2.setEnabled(false);
+ edgeSelectSpinner3.setEnabled(false);
+ edgeSelectSpinner4.setEnabled(false);
+ carouselPicker.setEnabled(false);
+ }
+
+ private void setViewVisibility(int mode) {
+ switch (mode) {
+ case 0:
+ channelMode = 1;
+ setAdapters();
+ llChannel1.setVisibility(View.VISIBLE);
+ llChannel2.setVisibility(View.GONE);
+ llChannel3.setVisibility(View.GONE);
+ llChannel4.setVisibility(View.GONE);
+ channelSelectSpinner1.setEnabled(true);
+ break;
+ case 1:
+ channelMode = 2;
+ setAdapterForTwoChannelMode();
+ llChannel1.setVisibility(View.VISIBLE);
+ llChannel2.setVisibility(View.VISIBLE);
+ llChannel3.setVisibility(View.GONE);
+ llChannel4.setVisibility(View.GONE);
+ channelSelectSpinner1.setEnabled(true);
+ channelSelectSpinner2.setEnabled(true);
+ break;
+ case 2:
+ channelMode = 3;
+ setAdapters();
+ llChannel1.setVisibility(View.VISIBLE);
+ llChannel2.setVisibility(View.VISIBLE);
+ llChannel3.setVisibility(View.VISIBLE);
+ llChannel4.setVisibility(View.GONE);
+ channelSelectSpinner1.setSelection(0);
+ channelSelectSpinner2.setSelection(1);
+ channelSelectSpinner3.setSelection(2);
+ channelSelectSpinner1.setEnabled(true);
+ channelSelectSpinner2.setEnabled(true);
+ channelSelectSpinner3.setEnabled(true);
+ break;
+ case 3:
+ channelMode = 4;
+ setAdapters();
+ llChannel1.setVisibility(View.VISIBLE);
+ llChannel2.setVisibility(View.VISIBLE);
+ llChannel3.setVisibility(View.VISIBLE);
+ llChannel4.setVisibility(View.VISIBLE);
+ channelSelectSpinner1.setSelection(0);
+ channelSelectSpinner2.setSelection(1);
+ channelSelectSpinner3.setSelection(2);
+ channelSelectSpinner4.setSelection(3);
+ channelSelectSpinner1.setEnabled(true);
+ channelSelectSpinner2.setEnabled(true);
+ channelSelectSpinner3.setEnabled(true);
+ channelSelectSpinner4.setEnabled(true);
+ break;
+ default:
+ channelMode = 1;
+ setAdapters();
+ llChannel1.setVisibility(View.VISIBLE);
+ llChannel2.setVisibility(View.GONE);
+ llChannel3.setVisibility(View.GONE);
+ llChannel4.setVisibility(View.GONE);
+ channelSelectSpinner1.setEnabled(true);
+ break;
+ }
+ }
/**
* Plots every edge of a digital pulse for one channel at a time
*
@@ -508,10 +664,10 @@ private void singleChannelEveryEdge(double[] xData, double[] yData) {
tempInput.add(new Entry(xaxis.get(i), yaxis.get(i) + 2 * currentChannel));
tempInput.add(new Entry(xaxis.get(i), yaxis.get(i + 1) + 2 * currentChannel));
}
- tempInput.add(new Entry(xaxis.get(xaxis.size() - 1), yaxis.get(xaxis.size() - 1)));
}
+ tempInput.add(new Entry(xaxis.get(xaxis.size() - 1), yaxis.get(xaxis.size() - 1) + 2 * currentChannel));
} else {
- tempInput.add(new Entry(xaxis.get(0), yaxis.get(0)));
+ tempInput.add(new Entry(xaxis.get(0), yaxis.get(0) + 2 * currentChannel));
}
setLineDataSet();
@@ -655,8 +811,8 @@ private void setAdapterForTwoChannelMode() {
final String[] channels = getResources().getStringArray(R.array.channel_choices);
final String[] edges = getResources().getStringArray(R.array.edge_choices);
- final List channel_one_list = new ArrayList<>( Arrays.asList(channels));
- final List channel_two_list = new ArrayList<>( Arrays.asList(channels));
+ final List channel_one_list = new ArrayList<>(Arrays.asList(channels));
+ final List channel_two_list = new ArrayList<>(Arrays.asList(channels));
final ArrayAdapter channel_one_adapter = new ArrayAdapter<>(getContext(), R.layout.modified_spinner_dropdown_list, channel_one_list);
final ArrayAdapter channel_two_adapter = new ArrayAdapter<>(getContext(), R.layout.modified_spinner_dropdown_list, channel_two_list);
@@ -673,8 +829,8 @@ private void setAdapterForTwoChannelMode() {
public void onItemSelected(AdapterView> parent, View view, int position, long id) {
String selection = channelSelectSpinner1.getItemAtPosition(position).toString();
channel_two_list.clear();
- for(int i = 0; i < channels.length; i++) {
- if(!channels[i].equals(selection)) {
+ for (int i = 0; i < channels.length; i++) {
+ if (!channels[i].equals(selection)) {
channel_two_list.add(channels[i]);
}
}
@@ -692,8 +848,8 @@ public void onNothingSelected(AdapterView> parent) {
public void onItemSelected(AdapterView> parent, View view, int position, long id) {
String selection = channelSelectSpinner2.getItemAtPosition(position).toString();
channel_one_list.clear();
- for(int i = 0; i < channels.length; i++) {
- if(!channels[i].equals(selection)) {
+ for (int i = 0; i < channels.length; i++) {
+ if (!channels[i].equals(selection)) {
channel_one_list.add(channels[i]);
}
}
@@ -756,6 +912,7 @@ public void onStop() {
/**
* Used to delay a thread by some given time in milliseconds
+ *
* @param delay Time to delay in milliseconds
*/
@@ -767,6 +924,32 @@ public void delayThread(long delay) {
}
}
+ private void storeAxisValues(double[] xaxis, double[] yaxis, int mode) {
+ StringBuilder stringBuilder1 = new StringBuilder();
+ StringBuilder stringBuilder2 = new StringBuilder();
+ for (int i = 0; i < xaxis.length; i++) {
+ stringBuilder1.append(DataFormatter.formatDouble(xaxis[i], DataFormatter.LOW_PRECISION_FORMAT));
+ stringBuilder2.append(DataFormatter.formatDouble(yaxis[i], DataFormatter.LOW_PRECISION_FORMAT));
+ stringBuilder1.append(" ");
+ stringBuilder2.append(" ");
+ }
+ recordXAxis.add(stringBuilder1.toString());
+ recordYAxis.add(stringBuilder2.toString());
+ recordChannelMode.add(mode);
+ }
+
+ public void recordSensorDataBlockID(SensorDataBlock block) {
+ realm.beginTransaction();
+ realm.copyToRealm(block);
+ realm.commitTransaction();
+ }
+
+ public void recordSensorData(RealmObject sensorData) {
+ realm.beginTransaction();
+ realm.copyToRealm((LogicAnalyzerData) sensorData);
+ realm.commitTransaction();
+ }
+
private class CaptureOne extends AsyncTask {
private String edgeOption = "";
private boolean holder;
@@ -774,6 +957,8 @@ private class CaptureOne extends AsyncTask {
@Override
protected Void doInBackground(String... params) {
try {
+ channels[0] = params[0];
+
int channelNumber = scienceLab.calculateDigitalChannel(params[0]);
digitalChannel = scienceLab.getDigitalChannel(channelNumber);
edgeOption = params[1];
@@ -801,7 +986,7 @@ protected Void doInBackground(String... params) {
scienceLab.startOneChannelLA(params[0], digitalChannel.mode, params[0], 3);
delayThread(1000);
LinkedHashMap data = scienceLab.getLAInitialStates();
- delayThread(500);
+ delayThread(1000);
holder = scienceLab.fetchLAChannel(channelNumber, data);
} catch (NullPointerException e) {
@@ -830,6 +1015,10 @@ protected void onPostExecute(Void aVoid) {
Log.v("x Axis", stringBuilder1.toString());
Log.v("y Axis", stringBuilder2.toString());
+ recordXAxis.clear();
+ recordXAxis.add(stringBuilder1.toString());
+ recordYAxis.add(stringBuilder2.toString());
+ recordChannelMode.add(digitalChannel.mode);
// Plot the fetched data
switch (edgeOption) {
case "EVERY EDGE":
@@ -886,6 +1075,9 @@ private class CaptureTwo extends AsyncTask, ArrayList,
@Override
protected final Void doInBackground(ArrayList... arrayLists) {
try {
+ channels[0] = arrayLists[0].get(0);
+ channels[1] = arrayLists[0].get(1);
+
int channelNumber1 = scienceLab.calculateDigitalChannel(arrayLists[0].get(0));
int channelNumber2 = scienceLab.calculateDigitalChannel(arrayLists[0].get(1));
@@ -926,9 +1118,9 @@ protected final Void doInBackground(ArrayList... arrayLists) {
scienceLab.startTwoChannelLA(arrayLists[0], modes, 67, null, null, null);
delayThread(1000);
LinkedHashMap data = scienceLab.getLAInitialStates();
- delayThread(500);
+ delayThread(1000);
holder1 = scienceLab.fetchLAChannel(channelNumber1, data);
- delayThread(500);
+ delayThread(1000);
holder2 = scienceLab.fetchLAChannel(channelNumber2, data);
} catch (NullPointerException e) {
@@ -951,8 +1143,12 @@ protected void onPostExecute(Void aVoid) {
yaxis.add(digitalChannelArray.get(0).getYAxis());
yaxis.add(digitalChannelArray.get(1).getYAxis());
+ recordXAxis.clear();
+ recordYAxis.clear();
+ recordChannelMode.clear();
// Plot the fetched data
for (int i = 0; i < channelMode; i++) {
+ storeAxisValues(xaxis.get(i), yaxis.get(i), digitalChannelArray.get(i).mode);
switch (edgeOption[i]) {
case "EVERY EDGE":
singleChannelEveryEdge(xaxis.get(i), yaxis.get(i));
@@ -1009,6 +1205,10 @@ private class CaptureThree extends AsyncTask, ArrayList... arrayLists) {
try {
+ channels[0] = arrayLists[0].get(0);
+ channels[1] = arrayLists[0].get(1);
+ channels[2] = arrayLists[0].get(2);
+
int channelNumber1 = scienceLab.calculateDigitalChannel(arrayLists[0].get(0));
int channelNumber2 = scienceLab.calculateDigitalChannel(arrayLists[0].get(1));
int channelNumber3 = scienceLab.calculateDigitalChannel(arrayLists[0].get(2));
@@ -1052,11 +1252,11 @@ protected final Void doInBackground(ArrayList... arrayLists) {
scienceLab.startThreeChannelLA(modes, null, null);
delayThread(1000);
LinkedHashMap data = scienceLab.getLAInitialStates();
- delayThread(500);
+ delayThread(1000);
holder1 = scienceLab.fetchLAChannel(channelNumber1, data);
- delayThread(500);
+ delayThread(1000);
holder2 = scienceLab.fetchLAChannel(channelNumber2, data);
- delayThread(500);
+ delayThread(1000);
holder3 = scienceLab.fetchLAChannel(channelNumber3, data);
} catch (NullPointerException e) {
@@ -1081,8 +1281,12 @@ protected void onPostExecute(Void aVoid) {
yaxis.add(digitalChannelArray.get(1).getYAxis());
yaxis.add(digitalChannelArray.get(2).getYAxis());
+ recordXAxis.clear();
+ recordYAxis.clear();
+ recordChannelMode.clear();
// Plot the fetched data
for (int i = 0; i < channelMode; i++) {
+ storeAxisValues(xaxis.get(i), yaxis.get(i), digitalChannelArray.get(i).mode);
switch (edgeOption[i]) {
case "EVERY EDGE":
singleChannelEveryEdge(xaxis.get(i), yaxis.get(i));
@@ -1138,6 +1342,11 @@ private class CaptureFour extends AsyncTask, ArrayList
@Override
protected Void doInBackground(ArrayList... arrayLists) {
try {
+ channels[0] = arrayLists[0].get(0);
+ channels[1] = arrayLists[0].get(1);
+ channels[2] = arrayLists[0].get(2);
+ channels[3] = arrayLists[0].get(3);
+
int channelNumber1 = scienceLab.calculateDigitalChannel(arrayLists[0].get(0));
int channelNumber2 = scienceLab.calculateDigitalChannel(arrayLists[0].get(1));
int channelNumber3 = scienceLab.calculateDigitalChannel(arrayLists[0].get(2));
@@ -1188,13 +1397,13 @@ protected Void doInBackground(ArrayList... arrayLists) {
scienceLab.startFourChannelLA(null, null, modes, null, triggerChannel);
delayThread(1000);
LinkedHashMap data = scienceLab.getLAInitialStates();
- delayThread(500);
+ delayThread(1000);
holder1 = scienceLab.fetchLAChannel(channelNumber1, data);
- delayThread(500);
+ delayThread(1000);
holder2 = scienceLab.fetchLAChannel(channelNumber2, data);
- delayThread(500);
+ delayThread(1000);
holder3 = scienceLab.fetchLAChannel(channelNumber3, data);
- delayThread(500);
+ delayThread(1000);
holder4 = scienceLab.fetchLAChannel(channelNumber4, data);
} catch (NullPointerException e) {
@@ -1221,8 +1430,12 @@ protected void onPostExecute(Void aVoid) {
yaxis.add(digitalChannelArray.get(2).getYAxis());
yaxis.add(digitalChannelArray.get(3).getYAxis());
+ recordXAxis.clear();
+ recordYAxis.clear();
+ recordChannelMode.clear();
// Plot the fetched data
for (int i = 0; i < channelMode; i++) {
+ storeAxisValues(xaxis.get(i), yaxis.get(i), digitalChannelArray.get(i).mode);
switch (edgeOption[i]) {
case "EVERY EDGE":
singleChannelEveryEdge(xaxis.get(i), yaxis.get(i));
diff --git a/app/src/main/java/io/pslab/interfaces/sensorloggers/GasSensorRecordables.java b/app/src/main/java/io/pslab/interfaces/sensorloggers/GasSensorRecordables.java
new file mode 100644
index 000000000..5ceb00a89
--- /dev/null
+++ b/app/src/main/java/io/pslab/interfaces/sensorloggers/GasSensorRecordables.java
@@ -0,0 +1,12 @@
+package io.pslab.interfaces.sensorloggers;
+
+import io.pslab.models.GasSensorData;
+import io.realm.RealmResults;
+
+public interface GasSensorRecordables {
+ GasSensorData getGasSensorData(long timeStamp);
+ void clearAllGasSensorRecords();
+ void clearBlockOfGasSensorRecords(long block);
+ RealmResults getAllGasSensorRecords();
+ RealmResults getBlockOfGasSensorRecords(long block);
+}
diff --git a/app/src/main/java/io/pslab/interfaces/sensorloggers/LogicAnalyzerRecordables.java b/app/src/main/java/io/pslab/interfaces/sensorloggers/LogicAnalyzerRecordables.java
new file mode 100644
index 000000000..266e68af1
--- /dev/null
+++ b/app/src/main/java/io/pslab/interfaces/sensorloggers/LogicAnalyzerRecordables.java
@@ -0,0 +1,12 @@
+package io.pslab.interfaces.sensorloggers;
+
+import io.pslab.models.LogicAnalyzerData;
+import io.realm.RealmResults;
+
+public interface LogicAnalyzerRecordables {
+ LogicAnalyzerData getLAData(long timeStamp);
+ void clearAllLARecords();
+ void clearBlockOfLARecords(long block);
+ RealmResults getAllLARecords();
+ RealmResults getBlockOfLARecords(long block);
+}
diff --git a/app/src/main/java/io/pslab/models/BaroData.java b/app/src/main/java/io/pslab/models/BaroData.java
index 2d2c3d745..d8b5e69a1 100644
--- a/app/src/main/java/io/pslab/models/BaroData.java
+++ b/app/src/main/java/io/pslab/models/BaroData.java
@@ -13,14 +13,16 @@ public class BaroData extends RealmObject {
private long time;
private long block;
private float baro;
+ private float altitude;
private double lat, lon;
public BaroData() {/**/}
- public BaroData(long time, long block, float baro, double lat, double lon) {
+ public BaroData(long time, long block, float baro, float altitude, double lat, double lon) {
this.time = time;
this.block = block;
this.baro = baro;
+ this.altitude = altitude;
this.lat = lat;
this.lon = lon;
}
@@ -49,6 +51,14 @@ public void setBaro(float baro) {
this.baro = baro;
}
+ public float getAltitude() {
+ return altitude;
+ }
+
+ public void setAltitude(float altitude) {
+ this.altitude = altitude;
+ }
+
public double getLat() {
return lat;
}
@@ -67,6 +77,6 @@ public void setLon(double lon) {
@Override
public String toString() {
- return "Block - " + block + ", Time - " + time + ", Baro - " + baro + ", Lat - " + lat + ", Lon - " + lon;
+ return "Block - " + block + ", Time - " + time + ", Baro - " + baro + ", Altitude - " + altitude + ", Lat - " + lat + ", Lon - " + lon;
}
}
\ No newline at end of file
diff --git a/app/src/main/java/io/pslab/models/GasSensorData.java b/app/src/main/java/io/pslab/models/GasSensorData.java
new file mode 100644
index 000000000..7613d23ce
--- /dev/null
+++ b/app/src/main/java/io/pslab/models/GasSensorData.java
@@ -0,0 +1,68 @@
+package io.pslab.models;
+
+import io.realm.RealmObject;
+import io.realm.annotations.PrimaryKey;
+
+public class GasSensorData extends RealmObject {
+
+ @PrimaryKey
+ private long time;
+ private long block;
+ private float ppmValue;
+ private double lat, lon;
+
+ public GasSensorData() {/**/}
+
+ public GasSensorData(long time, long block, float ppmValue, double lat, double lon) {
+ this.time = time;
+ this.block = block;
+ this.ppmValue = ppmValue;
+ 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 getPpmValue() {
+ return ppmValue;
+ }
+
+ public void setPpmValue(float ppmValue) {
+ this.ppmValue = ppmValue;
+ }
+
+ 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 + ", PPM value - " + ppmValue + ", Lat - " + lat + ", Lon - " + lon;
+ }
+}
diff --git a/app/src/main/java/io/pslab/models/LogicAnalyzerData.java b/app/src/main/java/io/pslab/models/LogicAnalyzerData.java
new file mode 100644
index 000000000..7f00bdf11
--- /dev/null
+++ b/app/src/main/java/io/pslab/models/LogicAnalyzerData.java
@@ -0,0 +1,95 @@
+package io.pslab.models;
+
+import io.realm.RealmObject;
+import io.realm.annotations.PrimaryKey;
+
+public class LogicAnalyzerData extends RealmObject {
+ @PrimaryKey
+ private long time;
+ private long block;
+ private String dataX, dataY, channel;
+ private double lat, lon;
+ private int channelMode;
+
+ public LogicAnalyzerData() {/**/}
+
+ public LogicAnalyzerData(long time, long block, String channel, int channelMode, String dataX, String dataY, double lat, double lon) {
+ this.time = time;
+ this.block = block;
+ this.channel = channel;
+ this.channelMode = channelMode;
+ this.dataX = dataX;
+ this.dataY = dataY;
+ this.lat = lat;
+ this.lon = lon;
+ }
+
+ public long getBlock() {
+ return block;
+ }
+
+ public void setBlock(long block) {
+ this.block = block;
+ }
+
+ public long getTime() {
+ return time;
+ }
+
+ public void setTime(long time) {
+ this.time = time;
+ }
+
+ public String getChannel() {
+ return channel;
+ }
+
+ public void setChannel(String channel) {
+ this.channel = channel;
+ }
+
+ public int getChannelMode() {
+ return channelMode;
+ }
+
+ public void setChannelMode(int channelMode) {
+ this.channelMode = channelMode;
+ }
+
+ public String getDataY() {
+ return dataY;
+ }
+
+ public void setDataY(String dataY) {
+ this.dataY = dataY;
+ }
+
+ public String getDataX() {
+ return dataX;
+ }
+
+ public void setDataX(String dataX) {
+ this.dataX = dataX;
+ }
+
+ public double getLon() {
+ return lon;
+ }
+
+ public void setLon(double lon) {
+ this.lon = lon;
+ }
+
+ public double getLat() {
+ return lat;
+ }
+
+ public void setLat(double lat) {
+ this.lat = lat;
+ }
+
+ @Override
+ public String toString() {
+ return "Block - " + block + ", Time - " + time + ", Channel - " + channel + ", ChannelMode - " + channelMode + ", dataX - " + dataX + ", dataY - " + dataY + ", 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 12def913c..32a107baf 100644
--- a/app/src/main/java/io/pslab/models/PSLabSensor.java
+++ b/app/src/main/java/io/pslab/models/PSLabSensor.java
@@ -45,6 +45,7 @@
import io.pslab.fragment.AccelerometerDataFragment;
import io.pslab.fragment.BaroMeterDataFragment;
import io.pslab.fragment.CompassDataFragment;
+import io.pslab.fragment.GasSensorDataFragment;
import io.pslab.fragment.GyroscopeDataFragment;
import io.pslab.fragment.LuxMeterDataFragment;
import io.pslab.fragment.ThermometerDataFragment;
@@ -111,6 +112,8 @@ public abstract class PSLabSensor extends AppCompatActivity {
public static final String OSCILLOSCOPE = "Oscilloscope";
public static final String POWER_SOURCE = "Power Source";
public static final String MULTIMETER = "Multimeter";
+ public static final String LOGIC_ANALYZER = "Logic Analyzer";
+ public static final String GAS_SENSOR = "Gas Sensor";
@BindView(R.id.sensor_toolbar)
Toolbar sensorToolBar;
@@ -345,6 +348,9 @@ public boolean onOptionsItemSelected(MenuItem item) {
} else if (getSensorFragment() instanceof ThermometerDataFragment){
((ThermometerDataFragment) getSupportFragmentManager()
.findFragmentByTag(getSensorName())).playData();
+ } else if (getSensorFragment() instanceof GasSensorDataFragment){
+ ((GasSensorDataFragment) getSupportFragmentManager()
+ .findFragmentByTag(getSensorName())).playData();
}
}
invalidateOptionsMenu();
@@ -368,6 +374,9 @@ public boolean onOptionsItemSelected(MenuItem item) {
} else if (getSensorFragment() instanceof ThermometerDataFragment){
((ThermometerDataFragment) getSupportFragmentManager()
.findFragmentByTag(getSensorName())).stopData();
+ } else if (getSensorFragment() instanceof GasSensorDataFragment){
+ ((GasSensorDataFragment) getSupportFragmentManager()
+ .findFragmentByTag(getSensorName())).stopData();
}
break;
case R.id.show_map:
@@ -412,8 +421,11 @@ public boolean onOptionsItemSelected(MenuItem item) {
} else if (getSensorFragment() instanceof ThermometerDataFragment) {
((ThermometerDataFragment) getSupportFragmentManager()
.findFragmentByTag(getSensorName())).saveGraph();
+ } else if (getSensorFragment() instanceof GasSensorDataFragment){
+ ((GasSensorDataFragment) getSupportFragmentManager()
+ .findFragmentByTag(getSensorName())).saveGraph();
}
- break;
+ break;
case android.R.id.home:
this.finish();
break;
diff --git a/app/src/main/java/io/pslab/others/LocalDataLog.java b/app/src/main/java/io/pslab/others/LocalDataLog.java
index 90929b6c0..51089115e 100644
--- a/app/src/main/java/io/pslab/others/LocalDataLog.java
+++ b/app/src/main/java/io/pslab/others/LocalDataLog.java
@@ -3,7 +3,9 @@
import io.pslab.interfaces.sensorloggers.AccelerometerRecordables;
import io.pslab.interfaces.sensorloggers.BaroMeterRecordables;
import io.pslab.interfaces.sensorloggers.CompassRecordables;
+import io.pslab.interfaces.sensorloggers.GasSensorRecordables;
import io.pslab.interfaces.sensorloggers.GyroscopeRecordables;
+import io.pslab.interfaces.sensorloggers.LogicAnalyzerRecordables;
import io.pslab.interfaces.sensorloggers.LuxMeterRecordables;
import io.pslab.interfaces.sensorloggers.MultimeterRecordables;
import io.pslab.interfaces.sensorloggers.OscilloscopeRecordables;
@@ -15,7 +17,9 @@
import io.pslab.models.AccelerometerData;
import io.pslab.models.BaroData;
import io.pslab.models.CompassData;
+import io.pslab.models.GasSensorData;
import io.pslab.models.GyroData;
+import io.pslab.models.LogicAnalyzerData;
import io.pslab.models.LuxData;
import io.pslab.models.MultimeterData;
import io.pslab.models.OscilloscopeData;
@@ -32,7 +36,7 @@
* Created by Padmal on 11/5/18.
*/
-public class LocalDataLog implements LuxMeterRecordables, BaroMeterRecordables, SensorRecordables, CompassRecordables, AccelerometerRecordables, GyroscopeRecordables, ThermometerRecordables, ServoRecordables, WaveGeneratorRecordables, OscilloscopeRecordables, PowerSourceRecordables, MultimeterRecordables {
+public class LocalDataLog implements LuxMeterRecordables, BaroMeterRecordables, SensorRecordables, CompassRecordables, AccelerometerRecordables, GyroscopeRecordables, ThermometerRecordables, ServoRecordables, WaveGeneratorRecordables, OscilloscopeRecordables, PowerSourceRecordables, MultimeterRecordables, LogicAnalyzerRecordables, GasSensorRecordables {
private static LocalDataLog instance;
private final Realm realm;
@@ -499,4 +503,80 @@ public RealmResults getBlockOfMultimeterRecords(long block) {
.equalTo("block", block)
.findAll();
}
+
+ /***********************************************************************************************
+ * Logic Analyzer Section
+ ***********************************************************************************************/
+
+ @Override
+ public LogicAnalyzerData getLAData(long timeStamp) {
+ return realm.where(LogicAnalyzerData.class)
+ .equalTo("time", timeStamp)
+ .findFirst();
+ }
+
+ @Override
+ public void clearAllLARecords() {
+ realm.beginTransaction();
+ realm.delete(LogicAnalyzerData.class);
+ realm.commitTransaction();
+ }
+
+ @Override
+ public void clearBlockOfLARecords(long block) {
+ realm.beginTransaction();
+ RealmResults data = getBlockOfLARecords(block);
+ data.deleteAllFromRealm();
+ realm.commitTransaction();
+ }
+
+ @Override
+ public RealmResults getAllLARecords() {
+ return realm.where(LogicAnalyzerData.class).findAll();
+ }
+
+ @Override
+ public RealmResults getBlockOfLARecords(long block) {
+ return realm.where(LogicAnalyzerData.class)
+ .equalTo("block", block)
+ .findAll();
+ }
+
+ /***********************************************************************************************
+ * Gas Sensor Section
+ ***********************************************************************************************/
+
+ @Override
+ public GasSensorData getGasSensorData(long timeStamp) {
+ return realm.where(GasSensorData.class)
+ .equalTo("time", timeStamp)
+ .findFirst();
+ }
+
+ @Override
+ public void clearAllGasSensorRecords() {
+ realm.beginTransaction();
+ realm.delete(GasSensorData.class);
+ realm.commitTransaction();
+ }
+
+ @Override
+ public void clearBlockOfGasSensorRecords(long block) {
+ realm.beginTransaction();
+ RealmResults data = getBlockOfGasSensorRecords(block);
+ data.deleteAllFromRealm();
+ realm.commitTransaction();
+ }
+
+ @Override
+ public RealmResults getAllGasSensorRecords() {
+ return realm.where(GasSensorData.class).findAll();
+ }
+
+ @Override
+ public RealmResults getBlockOfGasSensorRecords(long block) {
+ return realm.where(GasSensorData.class)
+ .equalTo("block", block)
+ .findAll();
+ }
}
diff --git a/app/src/main/res/drawable/ic_bluetooth.xml b/app/src/main/res/drawable/ic_bluetooth.xml
new file mode 100644
index 000000000..d1432adac
--- /dev/null
+++ b/app/src/main/res/drawable/ic_bluetooth.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_wifi.xml b/app/src/main/res/drawable/ic_wifi.xml
new file mode 100644
index 000000000..aff45f329
--- /dev/null
+++ b/app/src/main/res/drawable/ic_wifi.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/app/src/main/res/layout-land/logic_analyzer_logic_lines.xml b/app/src/main/res/layout-land/logic_analyzer_logic_lines.xml
index a0d9c161c..a371cd2ee 100644
--- a/app/src/main/res/layout-land/logic_analyzer_logic_lines.xml
+++ b/app/src/main/res/layout-land/logic_analyzer_logic_lines.xml
@@ -21,14 +21,29 @@
android:gravity="center"
android:orientation="vertical">
-
+ android:orientation="horizontal">
+
+
+
+
+
@@ -95,8 +110,8 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/heading"
- android:layout_marginBottom="@dimen/carousel_margin_bottom"
android:layout_marginTop="@dimen/carousel_margin_top"
+ android:layout_marginBottom="@dimen/carousel_margin_bottom"
android:background="@drawable/carousel_view_background"
app:items_visible="three" />
@@ -104,9 +119,9 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/carouselPicker"
- android:layout_marginBottom="@dimen/chart_layout_margin_bottom"
android:layout_marginEnd="@dimen/recycler_view_margin_end"
- android:layout_marginRight="@dimen/recycler_view_margin_end">
+ android:layout_marginRight="@dimen/recycler_view_margin_end"
+ android:layout_marginBottom="@dimen/chart_layout_margin_bottom">
+ android:paddingBottom="@dimen/ll_padding_bottom">
+ android:paddingBottom="@dimen/ll_padding_bottom">
+ android:paddingBottom="@dimen/ll_padding_bottom">
+ android:paddingBottom="@dimen/ll_padding_bottom">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/fragment_barometer_data.xml b/app/src/main/res/layout/fragment_barometer_data.xml
index 0c72f6b3d..9ea474c00 100644
--- a/app/src/main/res/layout/fragment_barometer_data.xml
+++ b/app/src/main/res/layout/fragment_barometer_data.xml
@@ -57,6 +57,17 @@
android:id="@+id/baro_avg"
style="@style/baro_meter_stat_display" />
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/fragment_gas_sensor.xml b/app/src/main/res/layout/fragment_gas_sensor.xml
new file mode 100644
index 000000000..766e96651
--- /dev/null
+++ b/app/src/main/res/layout/fragment_gas_sensor.xml
@@ -0,0 +1,119 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
index 5f89c6df1..d90da235d 100644
--- a/app/src/main/res/values/dimens.xml
+++ b/app/src/main/res/values/dimens.xml
@@ -282,6 +282,12 @@
16sp
8sp
16sp
+ 10dp
+
+ 16sp
+
+ 5dp
+ 15dp
4dp
30dp
@@ -328,6 +334,9 @@
30dp
36sp
+ 30dp
+ 50dp
+
10dp
20dp
22dp
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index ffbaac2e9..127724456 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -18,12 +18,16 @@
Pin Layout Front
Pin Layout Back
Bluetooth Connection
- USB device not found. Do you want to scan for Bluetooth Connection?
-
+ USB device not found. Do you want to scan for Bluetooth or Wifi connection?
+ Bluetooth
+ WiFi
Scan
Stop
Scanned Devices
Your phone does not support bluetooth
+ Please enter valid IP address
+ Enter IP address of ESP module
+ Connect
Oscilloscope
Multimeter
@@ -845,10 +849,15 @@
Device does not have a barometer
+ Gas Sensor
+ Air quality sensor for detecting a wide range of gases, including NH3, NOx, alcohol, benzene, smoke and CO2
+ Gas Contents (PPM)
+ PPM
+
Robotic Arm
A robotic arm is a type of mechanical arm, usually programmable, with similar functions to a human arm.
Your arm\'s job is to move your hand from place to place. Similarly, the robotic arm\'s job is to move an end effector from place to place. You can outfit robotic arms with all sorts of end effectors, which are suited to a particular application. One common end effector is a simplified version of the hand, which can grasp and carry different objects.
- Controls servos of a robotic arm
+ Controls servos of a robotic arm
Servo 1
Servo 2
Servo 3
@@ -889,8 +898,10 @@
Delete All Data
Are You Sure?
Barometer
+ m
atm
Avg (atm)
+ Altitude (m)
Min (atm)
Max (atm)
Measures the atmospheric pressure
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index 641af0fbd..ccde34c4c 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -88,6 +88,28 @@
- 15sp
+
+
+
+