From d034932fd706c0064568167aad6f7bb9218d08f1 Mon Sep 17 00:00:00 2001 From: Gyeonghwan Hong Date: Mon, 6 Nov 2017 06:01:46 +0900 Subject: [PATCH] Update SensorViewer and MotionClassifier (Android-side) * Update UI of SensorViewer * Update UI of MotionClassifier * Fix bugs on MotionClassifier --- Ant-Manager/AndroidManifest.xml | 2 +- .../res/layout/activity_motion_classifier.xml | 289 +++++++----------- .../res/layout/activity_sensor_viewer.xml | 37 +-- .../view/BasicSensorViewerActivity.java | 61 ---- .../view/MotionClassifierActivity.java | 271 +++++++++++++++- .../view/SensorViewerActivity.java | 24 +- .../view/main/SensorViewerMainIcon.java | 6 +- 7 files changed, 396 insertions(+), 294 deletions(-) delete mode 100644 Ant-Manager/src/com/ant/ant_manager/view/BasicSensorViewerActivity.java diff --git a/Ant-Manager/AndroidManifest.xml b/Ant-Manager/AndroidManifest.xml index 4a0a6880..f1851b1c 100755 --- a/Ant-Manager/AndroidManifest.xml +++ b/Ant-Manager/AndroidManifest.xml @@ -55,8 +55,8 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="fill_parent" + android:layout_height="match_parent" + + tools:context="com.ant.graphtest.MainActivity"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Ant-Manager/res/layout/activity_sensor_viewer.xml b/Ant-Manager/res/layout/activity_sensor_viewer.xml index 5738805c..d56e1eb8 100644 --- a/Ant-Manager/res/layout/activity_sensor_viewer.xml +++ b/Ant-Manager/res/layout/activity_sensor_viewer.xml @@ -20,20 +20,19 @@ android:orientation="vertical"> + android:layout_marginLeft="0dp" /> @@ -44,15 +43,14 @@ android:orientation="vertical" > - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import android.os.Bundle; -import android.view.MenuItem; - -import com.ant.ant_manager.R; - -public class BasicSensorViewerActivity extends SensorViewerActivity { - @Override - protected void onCreate(Bundle savedInstanceState) { - setContentView(R.layout.activity_sensor_viewer); - super.onCreate(savedInstanceState); - } - - @Override - protected void onDestroy() { - super.onDestroy(); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - return super.onOptionsItemSelected(item); - } - - @Override - public void onResume() { - super.onResume(); - } - - @Override - public void onBackPressed() { - super.onBackPressed(); - } - - @Override - public void onPause() { - super.onPause(); - } - - @Override - public void onMessageFromTarget(String listenerName, String message) { - // Not implemented - } -} \ No newline at end of file diff --git a/Ant-Manager/src/com/ant/ant_manager/view/MotionClassifierActivity.java b/Ant-Manager/src/com/ant/ant_manager/view/MotionClassifierActivity.java index f4560703..7fc6b8cf 100644 --- a/Ant-Manager/src/com/ant/ant_manager/view/MotionClassifierActivity.java +++ b/Ant-Manager/src/com/ant/ant_manager/view/MotionClassifierActivity.java @@ -17,32 +17,157 @@ * limitations under the License. */ +import android.annotation.SuppressLint; +import android.app.ActionBar; +import android.app.Activity; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.ServiceConnection; +import android.graphics.Color; import android.os.Bundle; +import android.os.Handler; +import android.os.IBinder; +import android.util.Log; import android.view.MenuItem; import android.widget.TextView; import com.ant.ant_manager.R; +import com.ant.ant_manager.controller.ANTControllerBroadcastReceiver; +import com.ant.ant_manager.controller.ANTControllerService; +import com.jjoe64.graphview.GraphView; +import com.jjoe64.graphview.series.DataPoint; +import com.jjoe64.graphview.series.LineGraphSeries; + +import java.util.ArrayList; + +public class MotionClassifierActivity extends Activity { + // ANTControllerService + private ANTControllerService mControllerServiceStub = null; + private PrivateControllerBroadcastReceiver mControllerBroadcastReceiver; + + // Intent + public static final String INTENT_KEY_APP_ID = "appId"; + + private int mAppId; + + private final Handler mHandler = new Handler(); + + private Runnable mTimer2; + + private LineGraphSeries mSeries2; + private double graph2LastXValue = 5d; + + ArrayList mSensorDataList = new ArrayList<>(); + int numSensors = 3; + String[] mSensorNameList = {"Accelerometer X", "Accelerometer Y", "Accelerometer Z"}; + int[] mSensorGraphViewList = {R.id.accXGraphView, R.id.accYGraphView, R.id.accZGraphView}; + int[] mSensorTextViewList = {R.id.accXTextView, R.id.accYTextView, R.id.accZTextView}; + int[] mSensorGraphLineColor = {Color.RED, Color.BLUE, Color.WHITE}; + + private final String TAG = "SensorViewer"; + private boolean mIsUIReady = false; + + protected void initializeSensorDataList() { + for (int i = 0; i < numSensors; i++) { + String sensorName = this.mSensorNameList[i]; + GraphView sensorGraphView = (GraphView) findViewById(this.mSensorGraphViewList[i]); + TextView sensorTextView = (TextView) findViewById(this.mSensorTextViewList[i]); + SensorData newSensorData = new SensorData(-20, 20, sensorName, sensorGraphView, + sensorTextView); + this.mSensorDataList.add(newSensorData); + newSensorData.setGraphLineColor(this.mSensorGraphLineColor[i]); + } + } -public class MotionClassifierActivity extends SensorViewerActivity { @Override protected void onCreate(Bundle savedInstanceState) { - setContentView(R.layout.activity_motion_classifier); super.onCreate(savedInstanceState); + setContentView(R.layout.activity_motion_classifier); + + // Parameters + Intent intent = this.getIntent(); + this.mAppId = intent.getIntExtra(INTENT_KEY_APP_ID, -1); + if (this.mAppId < 0) { + Log.e(TAG, "Invalid application id!"); + this.finish(); + } + + ActionBar actionBar = getActionBar(); + actionBar.setTitle("Motion Classifier"); + actionBar.setDisplayHomeAsUpEnabled(true); + actionBar.setLogo(R.drawable.motionclassifier); + actionBar.setDisplayUseLogoEnabled(true); + + this.initializeSensorDataList(); } @Override protected void onDestroy() { super.onDestroy(); + + // Terminate JavaScript SensorViewer App + this.mControllerServiceStub.terminateAppOneWay(this.mAppId); + + // Disconnect Controller Service + this.disconnectControllerService(); } @Override public boolean onOptionsItemSelected(MenuItem item) { - return super.onOptionsItemSelected(item); + switch (item.getItemId()) { + case android.R.id.home: + this.finish(); + return true; + default: + return super.onOptionsItemSelected(item); + } + } + + public void onSensorViewerMessage(String message) { + String[] tokens = message.split("\\s+"); + if (tokens.length < 4) { + Log.e(TAG, "# of tokens is too small! : " + message); + return; + } + + if (this.mIsUIReady) { + String classified = tokens[0]; + TextView classifiedTextView = (TextView) findViewById(R.id.textViewClassified); + classifiedTextView.setText(classified); + for (int i = 0; i < this.numSensors; i++) { + Double sensorValue = Double.parseDouble(tokens[i + 1]); + SensorData sensorData = this.mSensorDataList.get(i); + sensorData.setCurrentValue(sensorValue); + sensorData.setEnabled(true); + } + } } @Override public void onResume() { super.onResume(); + + connectControllerService(); + + mTimer2 = new Runnable() { + @Override + public void run() { + graph2LastXValue += 1d; + for (int i = 0; i < numSensors; i++) { + SensorData sensorData = mSensorDataList.get(i); + Double sensorValue = sensorData.getCurrentValue(); + sensorData.appendData(new DataPoint(graph2LastXValue, sensorValue), true, + sensorData.getMax()); + } + mHandler.postDelayed(this, 200); + } + + }; + mHandler.postDelayed(mTimer2, 1000); + + this.mIsUIReady = true; } @Override @@ -53,13 +178,143 @@ public void onBackPressed() { @Override public void onPause() { super.onPause(); + mControllerServiceStub.terminateAppOneWay(this.mAppId); + mHandler.removeCallbacks(mTimer2); + this.mIsUIReady = false; } - @Override - public void onMessageFromTarget(String listenerName, String message) { - if (listenerName.compareTo("motionclassifier") == 0) { - TextView textViewClassified = (TextView) this.findViewById(R.id.textViewClassified); - textViewClassified.setText("Result: " + message); + private void connectControllerService() { + Intent serviceIntent = new Intent(this, ANTControllerService.class); + this.bindService(serviceIntent, this.mControllerServiceConnection, Context + .BIND_AUTO_CREATE); + } + + private void disconnectControllerService() { + if (this.mControllerServiceConnection != null) + this.unbindService(this.mControllerServiceConnection); + if (this.mControllerBroadcastReceiver != null) + this.unregisterReceiver(this.mControllerBroadcastReceiver); + } + + private ServiceConnection mControllerServiceConnection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName componentName, IBinder inputBinder) { + ANTControllerService.ControllerBinder serviceBinder = (ANTControllerService + .ControllerBinder) inputBinder; + mControllerServiceStub = serviceBinder.getService(); + + // Set BroadcastReceiver + IntentFilter broadcastIntentFilter = new IntentFilter(); + broadcastIntentFilter.addAction(ANTControllerBroadcastReceiver.ACTION); + mControllerBroadcastReceiver = new PrivateControllerBroadcastReceiver(); + registerReceiver(mControllerBroadcastReceiver, broadcastIntentFilter); + + // Initialize connection with camera viewer + mControllerServiceStub.launchAppOneWay(mAppId); + } + + @Override + public void onServiceDisconnected(ComponentName componentName) { + Log.d(TAG, "onServiceDisconnected()"); + unregisterReceiver(mControllerBroadcastReceiver); + mControllerServiceStub = null; + } + }; + + class PrivateControllerBroadcastReceiver extends ANTControllerBroadcastReceiver { + PrivateControllerBroadcastReceiver() { + this.setOnReceivedSensorDataListener(new OnReceivedDataFromTarget() { + @Override + public void onReceivedDataFromTarget(String listenerName, String data) { + Log.d(TAG, "Message coming for " + listenerName + ": " + data); + if (listenerName.compareToIgnoreCase("motionclassifier") == 0) { + onSensorViewerMessage(data); + } + } + }); + } + } + + class SensorData { + private int mMin; + private int mMax; + private double mCurrentValue; + private String mSensorName; + + private GraphView mGraphView; + private TextView mTextView; + + private LineGraphSeries mLineGraphSeries; + private int mUniqueColor; + private boolean mIsEnabled = false; + + SensorData(int min, int max, String sensorName, GraphView graphView, TextView textView) { + this.mMin = min; + this.mMax = max; + this.mGraphView = graphView; + this.mCurrentValue = 0.0; + this.mSensorName = sensorName; + this.mTextView = textView; + this.mTextView.setText(sensorName + "(Loading...)"); + mLineGraphSeries = new LineGraphSeries(); + + graphView.addSeries(mLineGraphSeries); + graphView.getViewport().setXAxisBoundsManual(false); + graphView.getViewport().setYAxisBoundsManual(true); + graphView.getViewport().setMinY(min); + graphView.getViewport().setMaxY(max); + + mLineGraphSeries.setThickness(5); + } + + void setCurrentValue(double newValue) { + this.mCurrentValue = newValue; + } + + double getCurrentValue() { + return this.mCurrentValue; + } + + void appendData(DataPoint dataPoint, boolean scrollToEnd, int maxDataPoints) { + mLineGraphSeries.appendData(dataPoint, scrollToEnd, maxDataPoints); + } + + int getMax() { + return this.mMax; + } + + String getSensorName() { + return this.mSensorName; + } + + void setTextViewColor(int color) { + mTextView.setTextColor(color); + } + + void setGraphLineColor(int color) { + this.mUniqueColor = color; + this.updateView(); + } + + void setEnabled(boolean isEnabled) { + this.mIsEnabled = isEnabled; + this.updateView(); + } + + private void updateView() { + runOnUiThread(new Runnable() { + @SuppressLint("SetTextI18n") + @Override + public void run() { + if (mIsEnabled) { + mLineGraphSeries.setColor(mUniqueColor); + mTextView.setText(getSensorName()); + } else { + mLineGraphSeries.setColor(Color.GRAY); + mTextView.setText(getSensorName() + " (Loading...)"); + } + } + }); } } } \ No newline at end of file diff --git a/Ant-Manager/src/com/ant/ant_manager/view/SensorViewerActivity.java b/Ant-Manager/src/com/ant/ant_manager/view/SensorViewerActivity.java index a6a8b5d4..412d5406 100644 --- a/Ant-Manager/src/com/ant/ant_manager/view/SensorViewerActivity.java +++ b/Ant-Manager/src/com/ant/ant_manager/view/SensorViewerActivity.java @@ -43,9 +43,7 @@ import java.util.ArrayList; -import static com.ant.ant_manager.R.drawable.sensor; - -abstract public class SensorViewerActivity extends Activity { +public class SensorViewerActivity extends Activity { // ANTControllerService private ANTControllerService mControllerServiceStub = null; private PrivateControllerBroadcastReceiver mControllerBroadcastReceiver; @@ -66,10 +64,12 @@ abstract public class SensorViewerActivity extends Activity { int numSensors = 7; String[] mSensorNameList = {"Touch", "Accelerometer", "Motion", "Sound", "Light", "Vibration", "Temperature"}; - int[] mSensorGraphViewList = {R.id.graph1, R.id.graph2, R.id.graph3, R.id.graph4, R.id - .graph5, R.id.graph6, R.id.graph7}; - int[] mSensorTextViewList = {R.id.textView11, R.id.textView22, R.id.textView33, R.id - .textView4, R.id.textView5, R.id.textView6, R.id.textView7}; + int[] mSensorGraphViewList = {R.id.touchSensorGraphView, R.id.accSensorGraphView, R.id + .motionSensorGraphView, R.id.soundSensorGraphView, R.id.lightSensorGraphView, R.id + .vibSensorGraphView, R.id.tempSensorGraphView}; + int[] mSensorTextViewList = {R.id.touchSensorTextView, R.id.accSensorTextView, R.id + .motionSensorTextView, R.id.soundSensorTextView, R.id.lightSensorTextView, R.id + .vibSensorTextView, R.id.tempSensorTextView}; int[] mSensorGraphLineColor = {Color.RED, Color.BLUE, Color.WHITE, Color.YELLOW, Color.WHITE, Color.BLUE, Color.YELLOW}; @@ -91,6 +91,7 @@ protected void initializeSensorDataList() { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + setContentView(R.layout.activity_sensor_viewer); // Parameters Intent intent = this.getIntent(); @@ -103,7 +104,7 @@ protected void onCreate(Bundle savedInstanceState) { ActionBar actionBar = getActionBar(); actionBar.setTitle("Sensor Viewer"); actionBar.setDisplayHomeAsUpEnabled(true); - actionBar.setLogo(sensor); + actionBar.setLogo(R.drawable.sensor); actionBar.setDisplayUseLogoEnabled(true); this.initializeSensorDataList(); @@ -131,8 +132,6 @@ public boolean onOptionsItemSelected(MenuItem item) { } } - abstract public void onMessageFromTarget(String listenerName, String message); - public void onSensorViewerMessage(String message) { String[] tokens = message.split("\\s+"); if (tokens.length < 7) { @@ -239,7 +238,6 @@ public void onReceivedDataFromTarget(String listenerName, String data) { if (listenerName.compareToIgnoreCase("sensorviewer") == 0) { onSensorViewerMessage(data); } - onMessageFromTarget(listenerName, data); } }); } @@ -265,7 +263,7 @@ class SensorData { this.mCurrentValue = 0.0; this.mSensorName = sensorName; this.mTextView = textView; - this.mTextView.setText(sensorName + "(Disconnected)"); + this.mTextView.setText(sensorName + "(Loading...)"); mLineGraphSeries = new LineGraphSeries(); graphView.addSeries(mLineGraphSeries); @@ -321,7 +319,7 @@ public void run() { mTextView.setText(getSensorName()); } else { mLineGraphSeries.setColor(Color.GRAY); - mTextView.setText(getSensorName() + " (Disconnected)"); + mTextView.setText(getSensorName() + " (Loading...)"); } } }); diff --git a/Ant-Manager/src/com/ant/ant_manager/view/main/SensorViewerMainIcon.java b/Ant-Manager/src/com/ant/ant_manager/view/main/SensorViewerMainIcon.java index 99714d8e..1c83f179 100644 --- a/Ant-Manager/src/com/ant/ant_manager/view/main/SensorViewerMainIcon.java +++ b/Ant-Manager/src/com/ant/ant_manager/view/main/SensorViewerMainIcon.java @@ -5,8 +5,8 @@ import android.widget.Toast; import com.ant.ant_manager.R; -import com.ant.ant_manager.view.BasicSensorViewerActivity; import com.ant.ant_manager.view.MainActivity; +import com.ant.ant_manager.view.SensorViewerActivity; /* Copyright (c) 2017 SKKU ESLAB, and contributors. All rights reserved. * @@ -40,8 +40,8 @@ public void onClick() { "connected", Toast.LENGTH_SHORT).show(); return; } - Intent intent = new Intent(this.mOwnerActivity, BasicSensorViewerActivity.class); - intent.putExtra(BasicSensorViewerActivity.INTENT_KEY_APP_ID, this.mAppId); + Intent intent = new Intent(this.mOwnerActivity, SensorViewerActivity.class); + intent.putExtra(SensorViewerActivity.INTENT_KEY_APP_ID, this.mAppId); mOwnerActivity.startActivity(intent); }