Creating Real-Time Graphs in Android App for Bluetooth Pulse Rate Sensor

10,256

The solution below configures your graph to achieve the basic layout and functionality you want. Note that I have bound a sample graph update to the clicking of the refresh button - you can bind a similar procedure to your interface with the actual pulse device. All you need is the time-bpm pair to be plotted to the x and y axes, respectively.

PulseActivity#onCreate

    // Local variable for simulating the sample time
    private int x = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_pulse);

        //Connect U.I Elements
        getPulseRate = (Button) findViewById(R.id.heartRateBtn);
        pulseRateView = (TextView) findViewById(R.id.pulseValueView);
        connectionStsView = (TextView) findViewById(R.id.connectionStsView);
        refreshButton = (Button) findViewById(R.id.refreshBtn);

        final GraphView graphView = new LineGraphView(
                this, // context
                "Pulse Rate Sensor" // heading
        );

        graphView.setVerticalLabels(new String[]{"high", "normal", "low"});

        graphView.setCustomLabelFormatter(new CustomLabelFormatter() {
            @Override
            public String formatLabel(double value, boolean isValueX) {
                if (isValueX) {
                    return null;
                } else {
                    if (value < 60) {
                        return "low";
                    } else if (value < 100) {
                        return "normal";
                    } else {
                        return "high";
                    }
                }
            }
        });

        // init heart rate series data
        rateSeries = new GraphViewSeries(new GraphView.GraphViewData[]{
        });
        graphView.addSeries(rateSeries);

        LinearLayout layout = (LinearLayout) findViewById(R.id.graph1);
        layout.addView(graphView);

        getPulseRate.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String setOutputMessage = "/bpm /";
                tx.setValue(setOutputMessage.getBytes(Charset.forName("UTF-8")));
                if (gatt.writeCharacteristic(tx)) {
                    writeConnectionData("Sent: " + setOutputMessage);
                } else {
                    writeConnectionData("Couldn't write TX characteristic!");
                }
            }
        });

        refreshButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //restartScan();
                rateSeries.appendData(new GraphView.GraphViewData(x += 3, new Random().nextInt(100)), false, 100);
                graphView.redrawAll();
            }
        });
    }

activity_pulse.xml

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="250dip"
        android:id="@+id/graph1"
        android:layout_marginLeft="5dp"
        android:layout_marginRight="5dp" />

    <LinearLayout
        android:id="@+id/rest"
        android:layout_width="fill_parent"
        android:layout_height="250dip"
        android:orientation="vertical">

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Refresh Connection"
            android:id="@+id/refreshBtn"
            android:layout_gravity="center_horizontal" />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Get Heart Rate"
            android:id="@+id/heartRateBtn"
            android:layout_gravity="center_horizontal" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Last Pulse Rate Value"
            android:id="@+id/pulsePlaceholderText"
            android:layout_gravity="center_horizontal" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceLarge"
            android:text="Large Text"
            android:id="@+id/pulseValueView"
            android:layout_gravity="center_horizontal" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceLarge"
            android:text="Connection Status"
            android:id="@+id/connectionStsView"
            android:layout_gravity="center_horizontal" />
    </LinearLayout>

</LinearLayout>
Share:
10,256
stefbmt
Author by

stefbmt

Specialist Trainee #publichealth 🇲🇹 | Futurist | Digital Marketer | #digitalhealth #socialmedia #pinksocks #family | @maphmorg @mdgeeks | #sayno #notobacco

Updated on June 04, 2022

Comments

  • stefbmt
    stefbmt almost 2 years

    I'm currently developing an Android Application which connects via Bluetooth Low Energy to an Arduino which has the nRF8001 Bluetooth Low Energy Module with a connect the SEN-11574 Pulse Rate Sensor available at Spark Fun ( https://www.sparkfun.com/products/11574 ).

    I have been trying to implement a graph which plots the data on the graph every time I tap on 'Get Heart Rate' button but I'm only managing the following:

    screenshot

    I've researched a number of different resources which include the following yet unfortunately they don't answer my question:

    1,2,3,4,5,6,7

    I am using the Android Graph View Library to try and solve my problem as it offers the best integration with Android Studio.

    I am struggling with three main things:

    1. Labelling the X and Y-Values properly
    2. Appending the Heart Rate Sensor Data to the Graph

    The full project is available at : Arduino Pulse Rate

    I seem to be struggling the most with these two sections of code:

         private void writeSensorData(final CharSequence text) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Log.e(LOG_TAG,text.toString());
                output=text.toString().trim();
    
                if (output.length() > 0 && output.length() <=3) {
                    pulseRateView.setText(output);
                    rateSeries.appendData(new GraphView.GraphViewData(graph2LastXValue,Double.parseDouble(output)),AutoScrollX,maxDataCount);
                }
                else {
                    return;
                }
            }
        });
    }
    
         @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_pulse);
    
        //Connect U.I Elements
        getPulseRate = (Button)findViewById(R.id.heartRateBtn);
        pulseRateView = (TextView) findViewById(R.id.pulseValueView);
        connectionStsView = (TextView) findViewById(R.id.connectionStsView);
        refreshButton = (Button) findViewById(R.id.refreshBtn);
    
        // init heart rate series data
        rateSeries = new GraphViewSeries(new GraphView.GraphViewData[] {
        });
    
        GraphView graphView = new LineGraphView(this, "Pulse Rate Sensor");
    
        graphView.addSeries(rateSeries);
        graphView.setScrollable(true);
        graphView.setScalable(true);
    
        LinearLayout layout = (LinearLayout) findViewById(R.id.graph1);
        layout.addView(graphView);
    
        getPulseRate.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String setOutputMessage = "/bpm /";
                tx.setValue(setOutputMessage.getBytes(Charset.forName("UTF-8")));
                if (gatt.writeCharacteristic(tx)) {
                    writeConnectionData("Sent: " + setOutputMessage);
                } else {
                    writeConnectionData("Couldn't write TX characteristic!");
                }
            }
        });
    
        refreshButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                restartScan();
            }
        });
    }
    

    Would appreciate any help and thank you for your time.