Приложение OBD II в Visual Studio(C#) с Xamarin
Я работаю над приложением Android, которое получает данные от адаптера Bluetooth OBD II. Настройка соединения между приложением и адаптером работает, но когда я посылаю команды адаптеру, я не получаю правильных результатов. Это либо возвращает:
+ СОЕДИНЕНИЕ<
или команда, которую я только что отправил адаптеру.
Приложение написано в Visual Studio с использованием Xamarin для разработки под Android. Код показывает только упрощенную версию приложения и просто отправляет код для поддерживаемых PID между 01 -1f.
BluetoothAdapter myAdapter;
BluetoothSocket socket = null;
string rawData;
public BluetoothConnect()
{
myAdapter = BluetoothAdapter.DefaultAdapter;
if (myAdapter == null)
{
//Device has no Bluetooth
}
if (!myAdapter.IsEnabled)
{
myAdapter.Enable();
}
BluetoothDevice d = myAdapter.GetRemoteDevice("AA:BB:CC:11:22:33");
socket = d.CreateRfcommSocketToServiceRecord(UUID.FromString("00001101-0000-1000-8000-00805F9B34FB"));
socket.Connect();
byte[] cmd = Encoding.ASCII.GetBytes("AT D");
socket.OutputStream.Write(cmd, 0, cmd.Length);
ReadAnswer();
socket.OutputStream.Flush();
cmd = Encoding.ASCII.GetBytes("AT Z");
socket.OutputStream.Write(cmd, 0, cmd.Length);
socket.OutputStream.Flush();
cmd = Encoding.ASCII.GetBytes("AT E0");
socket.OutputStream.Write(cmd, 0, cmd.Length);
ReadAnswer();
socket.OutputStream.Flush();
cmd = Encoding.ASCII.GetBytes("AT L0");
socket.OutputStream.Write(cmd, 0, cmd.Length);
ReadAnswer();
socket.OutputStream.Flush();
cmd = Encoding.ASCII.GetBytes("AT S0");
socket.OutputStream.Write(cmd, 0, cmd.Length);
ReadAnswer();
socket.OutputStream.Flush();
cmd = Encoding.ASCII.GetBytes("AT H0");
socket.OutputStream.Write(cmd, 0, cmd.Length);
ReadAnswer();
socket.OutputStream.Flush();
cmd = Encoding.ASCII.GetBytes("AT SP 0");
socket.OutputStream.Write(cmd, 0, cmd.Length);
ReadAnswer();
socket.OutputStream.Flush();
cmd = Encoding.ASCII.GetBytes("0100");
socket.OutputStream.Write(cmd, 0, cmd.Length);
ReadAnswer();
}
private void ReadAnswer() {
try {
rawData = "";
int a = 0;
System.Text.StringBuilder b = new System.Text.StringBuilder();
char c;
while (((a = (byte)socket.InputStream.ReadByte()) > -1))
{
c = (char)a;
if (c == '>')
{
break;
}
b.Append(c);
}
rawData = b.ToString();
Log.Info("-----------------------------------", "RawData: " + rawData);
socket.InputStream.Flush();
}
catch(System.Exception e)
{
Log.Info("", "" + e.Message);
}
}
Я уже пробовал разные комбинации команд инициализации.
Я мог предположить, что проблема связана с моим методом чтения входного потока или с отправкой команд, но я не могу понять, что делать, так как я новичок в разработке Visual Studio, Xamarin и Android.
Надеюсь, вы, ребята, можете дать мне несколько предложений!
0 ответов
Сейчас слишком стар, но, может быть, кому-то нужно. Приведенный ниже код протестирован с ELM327, разработанным в Xamarin.
public void SendCommand( string command , Action<string> onDataRecevied )
{
if ( BthSocket.IsConnected )
{
byte[] cmd = Encoding.ASCII.GetBytes( command + " \r" );
BthSocket.OutputStream.Write( cmd , 0 , cmd.Length );
BthSocket.OutputStream.Flush();
ReadData( out string d );
if ( d != "" )
{
onDataRecevied( d );
}
}
}
и читать данные
public void ReadData( out string data )
{
StringBuilder res = new StringBuilder();
try
{
byte b = 0;
// read until '>' arrives OR end of stream reached
char c;
// -1 if the end of the stream is reached
while ( ( b = ( ( byte )BthSocket.InputStream.ReadByte() ) ) > -1 )
{
c = ( char )b;
if ( c == '>' ) // read until '>' arrives
{
break;
}
res.Append( c );
}
}
catch ( Exception e )
{
System.Console.WriteLine( e.ToString() );
}
data = res.ToString().Replace( "SEARCHING" , "" );
/*
* Data may have echo or informative text like "INIT BUS..." or similar.
* The response ends with two carriage return characters. So we need to take
* everything from the last carriage return before those two (trimmed above).
*/
data = data.Replace( "\\s" , "" );
}
и для инициализации устройства ниже приведены команды
obd2.SendCommand( "AT Z" , ( obj ) => { LogMessage( txtData , obj ); } );
obd2.SendCommand( "AT E0" , ( obj ) => { LogMessage( txtData , obj ); } );
obd2.SendCommand( "AT E0" , ( obj ) => { LogMessage( txtData , obj ); } );
obd2.SendCommand( "AT L0" , ( obj ) => { LogMessage( txtData , obj ); } );
obd2.SendCommand( "AT S0" , ( obj ) => { LogMessage( txtData , obj ); } );
obd2.SendCommand( "ATD" , ( obj ) => { LogMessage( txtData , obj ); } );
obd2.SendCommand( "AT SP 6" , ( obj ) => { LogMessage( txtData , obj ); } );
obd2.SendCommand( "AT H0" , ( obj ) => { LogMessage( txtData , obj ); } );
obd2.SendCommand( "AT 1" , ( obj ) => { LogMessage( txtData , obj ); } );
obd2.SendCommand( "ATST 96" , ( obj ) => { LogMessage( txtData , obj ); } );
obd2.SendCommand( "AT H1" , ( obj ) => { LogMessage( txtData , obj ); } );
obd2.SendCommand( "AT H0" , ( obj ) => { LogMessage( txtData , obj ); } );
эта строка data = res.ToString().Replace( "SEARCHING", ""); Представьте себе следующий ответ 41 0c 00 0d. ELM отправляет строки! Итак, ELM ставит пробелы между каждым "байтом". И обратите внимание на то, что я поместил слово byte в кавычки, потому что 41 - это на самом деле два байта (два символа) в сокете. Итак, мы должны сделать еще немного обработки.
Надеюсь это поможет.