package com.example.communication;
import androidx.appcompat.app.AppCompatActivity;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.widget.TextView;
import androidx.core.content.ContextCompat;
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 com.github.mikephil.charting.interfaces.datasets.ILineDataSet;
public class MainActivity extends AppCompatActivity implements UdpReceiver.OnMessageReceivedListener {
private static final String TAG = "MainActivity";
private TextView messageTextView;
private UdpReceiver udpReceiver;
private LineChart chart;
private final int count = 0;
private LineDataSet dataSet;
private float lastX = 0;
private static final String SERVER_IP = "0.0.0.0"; // Replace with your tablet IP
private static final int SERVER_PORT = 8888;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
messageTextView = findViewById(R.id.messageTextView);
chart = findViewById(R.id.chart);
// enable description text
chart.getDescription().setEnabled(true);
chart.getDescription().setText("Beats Per Minute");
// enable touch gestures
chart.setTouchEnabled(true);
// enable scaling and dragging
chart.setDragEnabled(true);
chart.setScaleEnabled(true);
// if disabled, scaling can be done on x- and y-axis separately
chart.setPinchZoom(true);
// set an empty data set
chart.setData(new LineData());
// create data set and assign to dataSet variable
dataSet = createSet();
// add dataSet to chart
chart.getData().addDataSet(dataSet);
// customize x-axis
XAxis x = chart.getXAxis();
x.setAxisMinimum(0);
x.setAxisMaximum(dataSet.getEntryCount()); // to increase the max
x.setDrawGridLines(false);
x.setDrawLabels(false);
// customize left y-axis
YAxis leftAxis = chart.getAxisLeft();
leftAxis.setAxisMinimum(0);
leftAxis.setAxisMaximum(220);
leftAxis.setDrawGridLines(true);
leftAxis.setDrawZeroLine(true);
leftAxis.setZeroLineColor(Color.GRAY);
leftAxis.setGranularityEnabled(true);
// customize right y-axis
chart.getAxisRight().setEnabled(false);
// customize legend
Legend legend = chart.getLegend();
legend.setForm(Legend.LegendForm.LINE);
// add gradient fill to line chart
Drawable drawable = ContextCompat.getDrawable(this, R.drawable.gradient_fill);
chart.setBackground(drawable);
// Refresh the chart
chart.invalidate();
udpReceiver = new UdpReceiver(this);
udpReceiver.startReceiver(SERVER_IP, SERVER_PORT);
}
@Override
protected void onDestroy() {
super.onDestroy();
udpReceiver.stopReceiver();
}
private void addEntry(final float bpm) {
runOnUiThread(new Runnable() {
@Override
public void run() {
LineData data = chart.getData();
if (data == null) {
data = new LineData();
chart.setData(data);
}
ILineDataSet set = data.getDataSetByIndex(0);
if (set == null) {
set = createSet();
data.addDataSet(set);
}
// Add the new entry to the chart
data.addEntry(new Entry(set.getEntryCount(), bpm), 0);
// Set the X-axis range based on the number of entries in the chart
chart.setVisibleXRangeMaximum(dataSet.getEntryCount()); //to change max
chart.setVisibleXRangeMinimum(20);
chart.moveViewToX(data.getEntryCount() - 1);
// Notify the chart that the data has changed
data.notifyDataChanged();
chart.notifyDataSetChanged();
}
});
}
private LineDataSet createSet() {
LineDataSet set = new LineDataSet(null, "Beats Per Minute");
set.setLineWidth(2f);
set.setDrawCircles(false);
set.setDrawValues(false);
set.setColor(Color.WHITE);
set.setMode(LineDataSet.Mode.LINEAR);
return set;
}
@Override
public void onMessageReceived(String message) {
//String[] data = message.split(",");
String[] data = new String[2];
data[0] = "";
data[1] = "";
if (message.contains(",")) {
data = message.split(",");
}
int irValue = 0;
float beatsPerMinute = 0;
int beatAvg = 0;
for (String item : data) {
if (item.startsWith("IR=")) {
irValue = Integer.parseInt(item.substring(3));
} else if (item.startsWith("BPM=")) {
beatsPerMinute = Float.parseFloat(item.substring(4));
if (beatsPerMinute >= 60 && beatsPerMinute <= 100) {
addEntry(beatsPerMinute);
}
}
/*
} else if (item.startsWith("Avg BPM=")) {
beatAvg = Integer.parseInt(item.substring(4));
}
*/
final int finalIrValue = irValue;
final float finalBeatsPerMinute = beatsPerMinute;
final int finalBeatAvg = beatAvg;
runOnUiThread(() -> {
messageTextView.setText("IR Value: " + finalIrValue +
"\nBeats Per Minute: " + finalBeatsPerMinute +
"\nBeat Average: " + finalBeatAvg);
// Add the new data to the chart
LineData chartData = chart.getData();
if (chartData != null) {
ILineDataSet set = chartData.getDataSetByIndex(0);
if (set == null) {
set = createSet();
chartData.addDataSet(set);
}
chartData.addEntry(new Entry(set.getEntryCount(), finalBeatsPerMinute), 0);
// Limit the number of visible entries
int maxVisibleEntries = 10;
if (chartData.getEntryCount() > maxVisibleEntries) {
chartData.removeEntry(0, 0);
}
// Notify chart that data has changed
chartData.notifyDataChanged();
chart.notifyDataSetChanged();
chart.setVisibleXRangeMaximum(maxVisibleEntries);
chart.moveViewToX(chartData.getEntryCount() - 1);
}
});
}
}
}
For the code above, I am using MPandroid to display the real time data using UDP from a heart rate sensor on a line chart, the app is receiving the BPM but not displaying. The chart is visible, but the BPM (Beats Per Minute) line on the chart is not shown, but the data has been received successfully on the UDP channel, but missing the line on the chart to display the BPM value. What would've been the issue?