Xamarin Forms C# Digital Dashboard App - Not Receiving Real Data for RPM and Speed from OBD-II ELM327

54 Views Asked by At

I'm currently working on a Xamarin Forms C# app for a digital dashboard that aims to read real-time data from an OBD-II ELM327 device. I'm facing an issue where the app is not receiving accurate data for RPM and Speed in km/h. My phone connects succesfuly with obd 2 device it starts retreiving data but this data for rpm and speed is kinda unreal like when car is not moving i got values aroun 60 til 100 kmph or even more same goes for rpm... i checked the commands they are fine protocol is fine i dont know from where problem can come from. my vehicle is using iso14230 kwp fast protocol

tried with different protocols and different commands and still no difference

ObdProtocol.cs
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using OBD.NET;
using OBD.NET.Common.Devices;
using OBD.NET.Common.Extensions;
using OBD.NET.Common.Logging;
using OBD.NET.Common.OBDData;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace App6
{
    public class ObdProtocol
    {
        public static int ParseValue(string data, string pid)
        {
            // Find the PID in the response
            int startIndex = data.IndexOf(pid);

            if (startIndex != -1)
            {
                // Extract the value
                int valueStartIndex = startIndex + pid.Length;
                string valueHex = data.Substring(valueStartIndex, 2);

                return Convert.ToInt32(valueHex, 16);
            }
            // Return a default or error value if the PID is not found
            return -1;
        }
        public static int ParseRPM(string data)
        {
            // Implement RPM parsing logic
            // Example: assuming data is in the format "41 0C 0A 1F", where 0C is RPM
            int startIndex = data.IndexOf("010C") + 6;
            string rpmHex = data.Substring(startIndex, 2) + data.Substring(startIndex + 3, 2);
            return Convert.ToInt32(rpmHex, 16) / 4; // RPM is usually in 1/4 RPM units
        }
        public static string ParseProtocol(string data)
        {
            int startIndex = data.IndexOf("DP");

            if (startIndex != -1)
            {
                int protocolStartIndex = startIndex + 2;
                string protocol = data.Substring(protocolStartIndex).Trim();

                return protocol;
            }

            return "Unknown"; // Set a default value or handle the case when protocol is not found
        }
    
    public static int ParseSpeed(string data)
        {
            // Implement speed parsing logic
            // Example: assuming data is in the format "41 0D 2A", where 0D is speed
            int startIndex = data.IndexOf("010D") + 6;
            string speedHex = data.Substring(startIndex, 2);
            return Convert.ToInt32(speedHex, 16);
        }
    }
} 

MainActivity.cs

using Android.App;
using Android.OS;
using Android.Widget;
using Android.Views;
using Java.Util;
using System;
using System.Threading;
using OBD.NET.Common.Devices;
using OBD.NET.Common.Extensions;
using OBD.NET.Common.Logging;
using OBD.NET.Common.OBDData;
using System.Timers;
using Xamarin.Essentials;
using System.Threading.Tasks;
using Android.Bluetooth;
using System.Reflection;
using In.UnicodeLabs.KdGaugeViewLib;



namespace App6
{
    [Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true)]
    public class MainActivity : Activity
    {
        private TextView rpmLabel;
        private TextView speedLabel;
        private ObdManager obdManager;
        private BluetoothSocket btnSocket;
        private TextView obdInfoLabel;
        private Button requestButton;
        private TextView obdProtocolLabel;

        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);
            SetContentView(Resource.Layout.activity_main);

            rpmLabel = FindViewById<TextView>(Resource.Id.rpmLabel);
            speedLabel = FindViewById<TextView>(Resource.Id.speedLabel);
            obdInfoLabel = FindViewById<TextView>(Resource.Id.obdInfoLabel);
            obdProtocolLabel = FindViewById<TextView>(Resource.Id.obdProtocolLabel);

            InitializeBluetooth();

            obdManager = new ObdManager(btnSocket);

            // Set up a timer to periodically request and update RPM and speed (every 0.1 seconds)
            System.Timers.Timer updateTimer = new System.Timers.Timer(500);
            updateTimer.Elapsed += OnUpdateTimerElapsed;
            updateTimer.Start();
        }


        private void OnUpdateTimerElapsed(object sender, ElapsedEventArgs e)
        {
            // Request RPM
            obdManager.SendCommand("010C", OnRPMReceived);

            // Request speed
            obdManager.SendCommand("010D", OnSpeedReceived);

            // Request protocol
            obdManager.SendCommand("AT DP", OnProtocolReceived);
        }

        private void OnRPMReceived(string data)
        {
            try
            {
                int rpmValue = ObdProtocol.ParseRPM(data);
                UpdateRPMUI(rpmValue);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error parsing RPM data: {ex.Message}");
            }
        }

        private void OnSpeedReceived(string data)
        {
            try
            {
                int speedValue = ObdProtocol.ParseSpeed(data);
                UpdateSpeedUI(speedValue);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error parsing Speed data: {ex.Message}");
            }
        }

        private void OnProtocolReceived(string data)
        {
            try
            {
                // Parse and display the received OBD2 protocol information
                string protocol = ObdProtocol.ParseProtocol(data);

                // Update the obdInfoLabel
                UpdateObdInfoLabel($"Protocol: {protocol}");

                // Update the obdProtocolLabel
                UpdateObdProtocolLabel($"Protocol: {protocol}");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error parsing OBD2 protocol data: {ex.Message}");
            }
        }

        private void UpdateRPMUI(int rpmValue)
        {
            RunOnUiThread(() => rpmLabel.Text = $"RPM: {rpmValue} RPM");
        }

        private void UpdateSpeedUI(int speedValue)
        {
            RunOnUiThread(() => speedLabel.Text = $"Speed: {speedValue} km/h");
        }

        private void UpdateObdInfoLabel(string info)
        {
            RunOnUiThread(() =>
            {
                obdInfoLabel.Text = $"OBD Info: {info}";
            });
        }

        private void UpdateObdProtocolLabel(string info)
        {
            RunOnUiThread(() =>
            {
                obdProtocolLabel.Text = info;
            });
        }

        private void InitializeBluetooth()
        {
            BluetoothAdapter bluetoothAdapter = BluetoothAdapter.DefaultAdapter;

            if (bluetoothAdapter == null)
            {
                return;
            }

            if (!bluetoothAdapter.IsEnabled)
            {
                Android.Content.Intent enableBtIntent = new Android.Content.Intent(BluetoothAdapter.ActionRequestEnable);
                StartActivityForResult(enableBtIntent, requestCode: 1);
                return;
            }

            BluetoothDevice obdDevice = FindOBDIIBluetoothDevice("00:1D:A5:68:98:8A");

            if (obdDevice != null)
            {
                try
                {
                    UUID sppUuid = UUID.FromString("00001101-0000-1000-8000-00805F9B34FB");
                    btnSocket = obdDevice.CreateRfcommSocketToServiceRecord(sppUuid);
                    btnSocket.Connect();

                    // Connection successful, show a message to the user
                    MainThread.BeginInvokeOnMainThread(() =>
                    {
                        Toast.MakeText(this, $"Bluetooth connection to {obdDevice.Name} established.", ToastLength.Long).Show();
                    });

                    // Set the protocol to "AUTO" after connection
                    obdManager.SendCommand("AT SP 0", data => { });

                    // Request protocol information after the connection is successful
                    obdManager.SendCommand("AT DP", OnProtocolReceived);
                }
                catch (Exception ex)
                {
                    // Connection failed, show a message to the user
                    MainThread.BeginInvokeOnMainThread(() =>
                    {
                        Toast.MakeText(this, $"Bluetooth connection error: {ex.Message}", ToastLength.Long).Show();
                    });
                }
            }
            else
            {
                // Device not found, show a message to the user
                MainThread.BeginInvokeOnMainThread(() =>
                {
                    Toast.MakeText(this, "Bluetooth device not found.", ToastLength.Long).Show();
                });
            }
        }

        private BluetoothDevice FindOBDIIBluetoothDevice(string deviceAddress)
        {
            BluetoothAdapter bluetoothAdapter = BluetoothAdapter.DefaultAdapter;

            if (bluetoothAdapter == null || !bluetoothAdapter.IsEnabled)
            {
                return null;
            }

            foreach (BluetoothDevice device in bluetoothAdapter.BondedDevices)
            {
                if (device.Address == deviceAddress)
                {
                    return device;
                }
            }

            // If not found among bonded devices, try discovering new devices
            if (bluetoothAdapter.IsDiscovering)
            {
                bluetoothAdapter.CancelDiscovery();
            }

            bluetoothAdapter.StartDiscovery();

            // Wait for discovery to complete (you might want to implement a BroadcastReceiver for better handling)
            System.Threading.Thread.Sleep(5000); // Adjust this timeout as needed

            foreach (BluetoothDevice device in bluetoothAdapter.BondedDevices)
            {
                if (device.Address == deviceAddress)
                {
                    return device;
                }
            }

            return null;
        }
    }
}

ObdManager class is designed to facilitate communication with an OBD device through a Bluetooth socket. ObdManager.cs

using Android.App;
using Android.Bluetooth;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace App6
{
    public class ObdManager
    {
        private readonly BluetoothSocket _btnSocket;

        public ObdManager(BluetoothSocket btnSocket)
        {
            _btnSocket = btnSocket;
        }

        public void SendCommand(string command, Action<string> onDataReceived)
        {
            if (_btnSocket.IsConnected)
            {
                byte[] cmd = Encoding.ASCII.GetBytes(command + "\r");
                _btnSocket.OutputStream.Write(cmd, 0, cmd.Length);
                _btnSocket.OutputStream.Flush();

                ReadData(out string data);
                if (!string.IsNullOrEmpty(data))
                {
                    onDataReceived?.Invoke(data);
                }
            }
        }

        public void ReadData(out string data)
        {
            StringBuilder res = new StringBuilder();

            try
            {
                int b = 0;
                char c;

                while ((b = (byte)_btnSocket.InputStream.ReadByte()) > -1)
                {
                    c = (char)b;
                    if (c == '>')
                    {
                        break;
                    }
                    res.Append(c);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }

            data = res.ToString().Replace("SEARCHING", "");

            data = data.Replace("\\s", "");
        }
    }
}

i really dont know from where the problem can come from

0

There are 0 best solutions below