diff --git a/app/src/main/java/uk/org/openseizuredetector/FragmentHrAlg.java b/app/src/main/java/uk/org/openseizuredetector/FragmentHrAlg.java new file mode 100644 index 0000000..836457a --- /dev/null +++ b/app/src/main/java/uk/org/openseizuredetector/FragmentHrAlg.java @@ -0,0 +1,57 @@ +package uk.org.openseizuredetector; + +import android.graphics.Color; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ProgressBar; +import android.widget.TextView; + +import com.github.mikephil.charting.charts.BarChart; +import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.data.BarData; +import com.github.mikephil.charting.data.BarDataSet; +import com.github.mikephil.charting.data.BarEntry; +import com.github.mikephil.charting.utils.ValueFormatter; + +import java.text.DecimalFormat; +import java.util.ArrayList; + +public class FragmentHrAlg extends FragmentSdDataViewer { + String TAG = "FragmentOsdAlg"; + public FragmentHrAlg() { + // Required empty public constructor + } + + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + // Inflate the layout for this fragment + return inflater.inflate(R.layout.fragment_osdalg, container, false); + } + + @Override + protected void updateUi() { + Log.d(TAG,"updateUi()"); + TextView tv; + tv = (TextView)mRootView.findViewById(R.id.fragment_osdalg_tv1); + if (mConnection.mBound) { + tv.setText("Bound to Server"); + } else { + tv.setText("****NOT BOUND TO SERVER***"); + return; + } + + + } +} diff --git a/app/src/main/java/uk/org/openseizuredetector/FragmentOsdAlg.java b/app/src/main/java/uk/org/openseizuredetector/FragmentOsdAlg.java index 6bd7b85..efaf2ad 100644 --- a/app/src/main/java/uk/org/openseizuredetector/FragmentOsdAlg.java +++ b/app/src/main/java/uk/org/openseizuredetector/FragmentOsdAlg.java @@ -1,11 +1,30 @@ package uk.org.openseizuredetector; +import android.graphics.Color; +import android.graphics.drawable.Drawable; import android.os.Bundle; +import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.ProgressBar; +import android.widget.TextView; + +import androidx.core.content.res.ResourcesCompat; + +import com.github.mikephil.charting.charts.BarChart; +import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.data.BarData; +import com.github.mikephil.charting.data.BarDataSet; +import com.github.mikephil.charting.data.BarEntry; +import com.github.mikephil.charting.utils.ValueFormatter; + +import java.text.DecimalFormat; +import java.util.ArrayList; public class FragmentOsdAlg extends FragmentSdDataViewer { + String TAG = "FragmentOsdAlg"; public FragmentOsdAlg() { // Required empty public constructor } @@ -22,4 +41,156 @@ public class FragmentOsdAlg extends FragmentSdDataViewer { // Inflate the layout for this fragment return inflater.inflate(R.layout.fragment_osdalg, container, false); } + + @Override + protected void updateUi() { + Log.d(TAG,"updateUi()"); + TextView tv; + tv = (TextView)mRootView.findViewById(R.id.fragment_osdalg_tv1); + if (mConnection.mBound) { + tv.setText("Bound to Server"); + } else { + tv.setText("****NOT BOUND TO SERVER***"); + return; + } + + + ///////////////////////////////////////////////////// + // Set ProgressBars to show margin to alarm. + long powerPc; + if (mConnection.mSdServer.mSdData.alarmThresh != 0) + powerPc = mConnection.mSdServer.mSdData.roiPower * 100 / + mConnection.mSdServer.mSdData.alarmThresh; + else + powerPc = 0; + + long specPc; + if (mConnection.mSdServer.mSdData.specPower != 0 && + mConnection.mSdServer.mSdData.alarmRatioThresh != 0) + specPc = 100 * (mConnection.mSdServer.mSdData.roiPower * 10 / + mConnection.mSdServer.mSdData.specPower) / + mConnection.mSdServer.mSdData.alarmRatioThresh; + else + specPc = 0; + + long specRatio; + if (mConnection.mSdServer.mSdData.specPower != 0) { + specRatio = 10 * mConnection.mSdServer.mSdData.roiPower / + mConnection.mSdServer.mSdData.specPower; + } else + specRatio = 0; + + ((TextView)mRootView.findViewById(R.id.powerTv)).setText(getString(R.string.PowerEquals) + mConnection.mSdServer.mSdData.roiPower + + " (" + getString(R.string.Threshold) + "=" + mConnection.mSdServer.mSdData.alarmThresh + ")"); + + ProgressBar pb; + Drawable pbDrawable; + pb = ((ProgressBar) mRootView.findViewById(R.id.powerProgressBar)); + pb.setMax(100); + pb.setProgress((int) powerPc); + pbDrawable = mRootView.getResources().getDrawable(R.drawable.progress_bar_blue); + if (powerPc > 75) + pbDrawable = mRootView.getResources().getDrawable(R.drawable.progress_bar_yellow); + if (powerPc > 100) + pbDrawable = mRootView.getResources().getDrawable(R.drawable.progress_bar_red); + pb.setProgressDrawable(pbDrawable); + + ((TextView)mRootView.findViewById(R.id.spectrumTv)).setText(getString(R.string.SpectrumRatioEquals) + specRatio + + " (" + getString(R.string.Threshold) + "=" + mConnection.mSdServer.mSdData.alarmRatioThresh + ")"); + + pb = ((ProgressBar) mRootView.findViewById(R.id.spectrumProgressBar)); + pb.setMax(100); + pb.setProgress((int) specPc); + pbDrawable = mRootView.getResources().getDrawable(R.drawable.progress_bar_blue); + if (specPc > 75) + pbDrawable = mRootView.getResources().getDrawable(R.drawable.progress_bar_yellow); + if (specPc > 100) + pbDrawable = mRootView.getResources().getDrawable(R.drawable.progress_bar_red); + pb.setProgressDrawable(pbDrawable); + + //////////////////////////////////////////////////////////// + // Produce graph + BarChart mChart = (BarChart) mRootView.findViewById(R.id.chart1); + mChart.setDrawBarShadow(false); + mChart.setNoDataTextDescription("You need to provide data for the chart."); + mChart.setDescription(""); + + // X and Y Values + ArrayList xVals = new ArrayList(); + ArrayList yBarVals = new ArrayList(); + for (int i = 0; i < 10; i++) { + xVals.add(i + "-" + (i + 1) + " Hz"); + if (mConnection.mSdServer != null) { + yBarVals.add(new BarEntry(mConnection.mSdServer.mSdData.simpleSpec[i], i)); + } else { + yBarVals.add(new BarEntry(i, i)); + } + } + + // create a dataset and give it a type + BarDataSet barDataSet = new BarDataSet(yBarVals, "Spectrum"); + try { + int[] barColours = new int[10]; + for (int i = 0; i < 10; i++) { + if ((i < mConnection.mSdServer.mSdData.alarmFreqMin) || + (i > mConnection.mSdServer.mSdData.alarmFreqMax)) { + barColours[i] = Color.GRAY; + } else { + barColours[i] = Color.RED; + } + } + barDataSet.setColors(barColours); + } catch (NullPointerException e) { + Log.e(TAG, "Null pointer exception setting bar colours"); + } + barDataSet.setBarSpacePercent(20f); + barDataSet.setBarShadowColor(Color.WHITE); + BarData barData = new BarData(xVals, barDataSet); + barData.setValueFormatter(new ValueFormatter() { + @Override + public String getFormattedValue(float v) { + DecimalFormat format = new DecimalFormat("####"); + return format.format(v); + } + }); + mChart.setData(barData); + + // format the axes + XAxis xAxis = mChart.getXAxis(); + xAxis.setPosition(XAxis.XAxisPosition.BOTTOM); + xAxis.setTextSize(10f); + xAxis.setDrawAxisLine(true); + xAxis.setDrawLabels(true); + // Note: the default text colour is BLACK, so does not show up on black background!!! + // This took a lot of finding.... + xAxis.setTextColor(Color.WHITE); + xAxis.setDrawGridLines(false); + + YAxis yAxis = mChart.getAxisLeft(); + yAxis.setAxisMinValue(0f); + yAxis.setAxisMaxValue(3000f); + yAxis.setDrawGridLines(true); + yAxis.setDrawLabels(true); + yAxis.setTextColor(Color.WHITE); + yAxis.setValueFormatter(new ValueFormatter() { + @Override + public String getFormattedValue(float v) { + DecimalFormat format = new DecimalFormat("#####"); + return format.format(v); + } + }); + + YAxis yAxis2 = mChart.getAxisRight(); + yAxis2.setDrawGridLines(false); + + try { + mChart.getLegend().setEnabled(false); + } catch (NullPointerException e) { + Log.e(TAG, "Null Pointer Exception setting legend"); + } + + mChart.invalidate(); + + + } } diff --git a/app/src/main/java/uk/org/openseizuredetector/FragmentSdDataViewer.java b/app/src/main/java/uk/org/openseizuredetector/FragmentSdDataViewer.java index d363ea7..020cd29 100644 --- a/app/src/main/java/uk/org/openseizuredetector/FragmentSdDataViewer.java +++ b/app/src/main/java/uk/org/openseizuredetector/FragmentSdDataViewer.java @@ -1,19 +1,29 @@ package uk.org.openseizuredetector; +import android.content.Context; import android.os.Bundle; import androidx.fragment.app.Fragment; +import android.os.Handler; +import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.TextView; + +import java.util.Timer; +import java.util.TimerTask; + -/** - * A simple {@link Fragment} subclass. - * Use the {@link FragmentSdDataViewer#newInstance} factory method to - * create an instance of this fragment. - */ public class FragmentSdDataViewer extends Fragment { + String TAG = "FragmentSdDataViewer"; + Context mContext; + OsdUtil mUtil; + SdServiceConnection mConnection; + final Handler updateUiHandler = new Handler(); + Timer mUiTimer; + protected View mRootView; public FragmentSdDataViewer() { @@ -23,7 +33,14 @@ public class FragmentSdDataViewer extends Fragment { @Override public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + Log.i(TAG,"onCreate()"); + mContext = getContext(); + mUtil = new OsdUtil(mContext, updateUiHandler); + mConnection = new SdServiceConnection(mContext); + + } @Override @@ -32,4 +49,78 @@ public class FragmentSdDataViewer extends Fragment { // Inflate the layout for this fragment return inflater.inflate(R.layout.fragment_sd_data_viewer, container, false); } + + @Override + public void onViewCreated(View view, Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + mRootView = view; + } + + @Override + public void onStart() { + super.onStart(); + Log.i(TAG, "onStart()"); + if (mUtil.isServerRunning()) { + Log.i(TAG, "onStart() - Binding to Server"); + mUtil.bindToServer(mContext, mConnection); + } else { + Log.i(TAG, "onStart() - Server Not Running"); + } + } + + @Override + public void onResume() { + super.onResume(); + Log.i(TAG, "onResume()"); + mUiTimer = new Timer(); + mUiTimer.schedule(new TimerTask() { + @Override + public void run() { + updateUiOnUiThread(); + } + }, 0, 1000); + } + + @Override + public void onPause() { + super.onPause(); + Log.i(TAG, "onPause()"); + mUiTimer.cancel(); + } + + @Override + public void onStop() { + super.onStop(); + Log.i(TAG, "onStop()"); + mUtil.unbindFromServer(mContext, mConnection); + } + + /** + * If we don't use this .post() trick, we get errors about the wrong thread trying to + * update the user interface views... + */ + private void updateUiOnUiThread() { + updateUiHandler.post(new Runnable(){ + @Override + public void run() { + updateUi(); + } + }); + } + + /** + * The subclasses should override this to draw their own UI. + */ + protected void updateUi() { + Log.d(TAG,"updateUi()"); + TextView tv; + tv = (TextView)mRootView.findViewById(R.id.fragment_sddata_viewer_tv1); + if (mConnection.mBound) { + tv.setText("Bound to Server"); + } else { + tv.setText("****NOT BOUND TO SERVER***"); + } + + } + } \ No newline at end of file diff --git a/app/src/main/java/uk/org/openseizuredetector/MainActivity2.java b/app/src/main/java/uk/org/openseizuredetector/MainActivity2.java index 3cfaf72..1f47389 100644 --- a/app/src/main/java/uk/org/openseizuredetector/MainActivity2.java +++ b/app/src/main/java/uk/org/openseizuredetector/MainActivity2.java @@ -1,20 +1,72 @@ package uk.org.openseizuredetector; import androidx.appcompat.app.AppCompatActivity; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentActivity; +import androidx.viewpager2.adapter.FragmentStateAdapter; +import androidx.viewpager2.widget.ViewPager2; import android.os.Bundle; +import android.util.Log; public class MainActivity2 extends AppCompatActivity { - + private String TAG = "MainActivity2"; + private ViewPager2 mFragmentPager; + private FragmentStateAdapter mFragmentStateAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main2); if (savedInstanceState == null) { - getSupportFragmentManager().beginTransaction() - .setReorderingAllowed(true) - .add(R.id.fragment_container_view, FragmentOsdAlg.class, null) - .commit(); + // Instantiate a ViewPager2 and a PagerAdapter. + mFragmentPager = findViewById(R.id.fragment_pager); + mFragmentStateAdapter = new ScreenSlideFragmentPagerAdapter(this); + mFragmentPager.setAdapter(mFragmentStateAdapter); + //getSupportFragmentManager().beginTransaction() + // .setReorderingAllowed(true) + // .add(R.id.fragment_container_view, FragmentOsdAlg.class, null) + // .commit(); + } + } + + @Override + public void onBackPressed() { + if (mFragmentPager.getCurrentItem() == 0) { + // If the user is currently looking at the first step, allow the system to handle the + // Back button. This calls finish() on this activity and pops the back stack. + super.onBackPressed(); + } else { + // Otherwise, select the previous step. + mFragmentPager.setCurrentItem(mFragmentPager.getCurrentItem() - 1); + } + } + + /** + * A simple pager adapter that represents 5 ScreenSlidePageFragment objects, in + * sequence. + */ + private class ScreenSlideFragmentPagerAdapter extends FragmentStateAdapter { + private String TAG = "ScreenSlideFragmentPagerAdapter"; + public ScreenSlideFragmentPagerAdapter(FragmentActivity fa) { + super(fa); + } + + @Override + public Fragment createFragment(int position) { + switch(position) { + case 0: + return new FragmentOsdAlg(); + case 1: + return new FragmentHrAlg(); + default: + Log.e(TAG,"createFragment() - invalid Position "+position); + return null; + } + } + + @Override + public int getItemCount() { + return 2; } } } \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main2.xml b/app/src/main/res/layout/activity_main2.xml index e724743..845910d 100644 --- a/app/src/main/res/layout/activity_main2.xml +++ b/app/src/main/res/layout/activity_main2.xml @@ -6,11 +6,16 @@ android:layout_height="match_parent" tools:context=".MainActivity2"> - - + --> + \ No newline at end of file diff --git a/app/src/main/res/layout/default_error_activity.xml b/app/src/main/res/layout/default_error_activity.xml index be73d5d..3e356d1 100644 --- a/app/src/main/res/layout/default_error_activity.xml +++ b/app/src/main/res/layout/default_error_activity.xml @@ -34,7 +34,8 @@ android:layout_height="wrap_content" android:layout_marginTop="16dp" android:text="View Error Log" - android:textColor="#212121"/> + android:textColor="#212121" + android:visibility="gone"/>