OBD вход Java поток бесконечный цикл - PullRequest
0 голосов
/ 02 марта 2019

Пишу простой OBD коммуникатор.Я запускаю OBDSim (последняя версия) из cmd (с правами администратора) obdsim.exe -g gui_fltk -w COM5 (я обнаружил, что порт COM5 в настройках Windows Bluetooth.) Затем я запускаю свое приложение в режиме отладки в Android Studio.Я работаю в ОС Windows 7.

MainActivity.java

com.example.bluetoothchatapp;

import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.content.Intent;
import android.content.IntentFilter;
import android.widget.*;
import android.view.*;
import android.os.Build;
import android.os.Handler;
import android.os.Message;

import java.util.ArrayList;
import java.util.Set;


public class MainActivity extends AppCompatActivity implements         AdapterView.OnItemClickListener
{

private TextView txvAdapterInfo;
private ListView lstBondedList;

private TextView txtEngineRpm;

ArrayList<String> bondedDevList = new ArrayList<>();
ArrayAdapter<String> bondedAdapter;


private BluetoothAdapter mBAdapter;

private ArrayList<BluetoothDevice> mBDeviceList;

private BluetoothDevice mBDevice;

Client client;

final Handler mHandler = new Handler()
{
    public void handleMessage(Message msg)
    {
        Bundle b;

        b = msg.getData();

        txtEngineRpm.setText(String.valueOf(b.getInt("rpm")));

        super.handleMessage(msg);
    }
};


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

    txvAdapterInfo = findViewById(R.id.txvAdapterInfo);
    lstBondedList = findViewById(R.id.lstBondedList);

    bondedAdapter = new ArrayAdapter<String>(this,
            android.R.layout.simple_list_item_activated_1, bondedDevList);
    lstBondedList.setAdapter(bondedAdapter);

    lstBondedList.setOnItemClickListener(MainActivity.this);

    txtEngineRpm = findViewById(R.id.txtEngineRpm);
    txtSpeed = findViewById(R.id.txtSpeedLog);

    mBDeviceList = new ArrayList<>();

    initBluetoothAdapter();
}


@Override
protected void onDestroy()
{
    super.onDestroy();

    unregisterReceiver(mBroadCastReceiver);
}


@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l)
{
    mBAdapter.cancelDiscovery();

    if(Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR2 && i <= mBDeviceList.size())
    {
        mBDevice = mBDeviceList.get(i);

        client = new Client(mBDevice, mHandler);

        client.run();
    }
}

public int getBondedDevicesList()
{
    Set<BluetoothDevice> pairedDevices = mBAdapter.getBondedDevices();

    if(pairedDevices.size() > 0)
    {
        for(BluetoothDevice device : pairedDevices)
        {
            mBDeviceList.add(device);
            bondedDevList.add(device.getName());
            bondedAdapter.notifyDataSetChanged();
        }
    }

    return 1;
}



public int initBluetoothAdapter()
{
    mBAdapter = BluetoothAdapter.getDefaultAdapter();

    if(mBAdapter == null)
    {
        return -1;
    }

    if(!mBAdapter.isEnabled())
    {
        mBAdapter.enable();
    }

    String adapterMACAdress = mBAdapter.getAddress();
    String adapterName = mBAdapter.getName();

    txvAdapterInfo.setText(adapterMACAdress + " , " + adapterName);

    getBondedDevicesList();

    return 1;
}
}

Client.java

package com.example.bluetoothchatapp;

import android.bluetooth.BluetoothDevice;

import com.github.pires.obd.commands.SpeedCommand;
import com.github.pires.obd.commands.protocol.*;
import com.github.pires.obd.enums.ObdProtocols;
import com.github.pires.obd.commands.engine.*;
import android.bluetooth.BluetoothSocket;
import android.os.Handler;
import android.os.Message;
import android.os.Bundle;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.InterruptedException;
import java.lang.reflect.InvocationTargetException;
import java.util.UUID;

public class Client implements Runnable , OBDCommands
{
    private Handler clHandler_;

    private BluetoothDevice clbDevice_;
    private BluetoothSocket clientSocket_;
    private InputStream inputStream_;
    private OutputStream outputStream_;

    StringBuilder obdReadResult_;

    private Bundle transferBundle_;

    public Client(BluetoothDevice device, Handler handler)
    {
        clbDevice_ = device;
        clHandler_ = handler;

        transferBundle_ = new Bundle(1);
        obdReadResult_ = new StringBuilder();  
    }


    public void initOBDAdapter() throws InterruptedException
    {
        try
        {

            UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");

            try
            {
                clientSocket_ = clbDevice_.createInsecureRfcommSocketToServiceRecord(uuid);

            }
            catch (IOException  e)
            {
                e.printStackTrace();
            }

            try
            {
                clientSocket_.connect();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }

            InputStream tmpIn = null;
            OutputStream tmpOut = null;

            try
            {
                tmpIn = clientSocket_.getInputStream();
                tmpOut = clientSocket_.getOutputStream();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }

            inputStream_ = tmpIn;
            outputStream_ = tmpOut;

            synchronized (Client.class)
            {
                // String ATZ = "AT Z\r"; define in simple OBDCommands interface

                writeToOBD(ATZ.getBytes());
                readFromOBD();
            }
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }

    }

    public void writeToOBD(byte[] data) throws IOException
    {
        outputStream_.write(data);
        outputStream_.flush();

        try
        {
            Thread.sleep(200);
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
    }

    public void readFromOBD() throws IOException
    {
        try
        {
            obdReadResult_.setLength(0);

            byte data;

            while((data = (byte) inputStream_.read()) > -1)
            {
                char c = (char) data;
                if(c == '>')
                {
                    break;
                }

                obdReadResult_.append(c);
            }

        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }

    public void logEngine() throws  InterruptedException
    {
        try
        {  
            writeToOBD(ERPM.getBytes());
            readFromOBD();

        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }

    public void run()
    {
        try
        {
            initOBDAdapter();
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }

        while (true)
        {
            try
            {
                logEngine();
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }

            String tmpStrValue = obdReadResult_.toString().replaceAll("(\\r|\\n)", "");    

            int rpmValue = Integer.parseInt(tmpStrValue.substring(4, tmpStrValue.length()), 16) / 4;

            transferBundle_.putInt("rmp", rpmValue);

            Message msg = clHandler_.obtainMessage();

            msg.setData(transferBundle_);

            clHandler_.sendMessage(msg);
        }
    }
}

У меня странное замораживание.Когда я в первый раз отлаживаю приложение, оно работает нормально, но ВТОРОЙ запуск отладки помещает поток в бесконечный цикл в строке while((data = (byte) inputStream_.read()) > -1), т. Е. Каждый второй запуск останавливается* Я также видел, что когда все работает нормально, тогда значение mPort сокета всегда равно 4, но когда происходит сбой, значение mPort сокета равно 2.

PS Я попытался использовать clientSocket_ = (BluetoothSocket)clbDevice_.getClass().getMethod("createRfcommSocket", new Class[] {int.class}).invoke(clbDevice_,1);, но затем соединение с сокетом создает потокв бесконечный цикл.

Я также использовал OBDII Java API, но тот же результат.Простой вызов чтения входного потока EchoOffCommand помещает поток в бесконечный цикл.

Что я делаю неправильно?

...