Android蓝牙与全站仪蓝牙仪器数据交互

来源:互联网 发布:java 文件md5 编辑:程序博客网 时间:2024/05/01 16:54
因项目需要,需要与全站仪蓝牙进行数据交互,公司的这台全站仪本身不带蓝牙,买的蓝牙适配器连接到设备上,因为也搞了挺长时间,把具体过程写一下。

一.设置蓝牙适配器

首先要搞定蓝牙适配器与全站仪之间的连接,保证设备能够铜鼓欧蓝牙发送出去,二者其中一些参数要保持一致。

  1. 蓝牙连接到电脑,进行必要的参数设置,需要一根转接线。
  2. 下载一个串口助手,我用的Serial Port Utility
  3. 需要看蓝牙适配器的说明书,我买的这个最好设置成COM2端口,在设备管理器里设置,不会自行百度。
  4. 设置完成之后通过串口助手设置参数与设备的参数一直,比如说波特率、数据位、校验位、停止位等,适配器需要与设备保持一致。软件很简单,通过AT指令可以更改。
  5. 设置完成之后,进入下一步

二.写蓝牙程序

1.蓝牙service

public class BluetoothService {    // Debugging    private static final String TAG = "BluetoothChatService";    private static final boolean D = true;    // Name for the SDP record when creating server socket    private static final String NAME = "BluetoothChat";    // Unique UUID for this application    private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");    // Member fields    private final BluetoothAdapter mAdapter;    private final Handler mHandler;    private AcceptThread mAcceptThread;    private ConnectThread mConnectThread;    private ConnectedThread mConnectedThread;    private int mState;    // Constants that indicate the current connection state    public static final int STATE_NONE = 0; // we're doing nothing    public static final int STATE_LISTEN = 1; // now listening for incoming                                                // connections    public static final int STATE_CONNECTING = 2; // now initiating an outgoing                                                    // connection    public static final int STATE_CONNECTED = 3; // now connected to a remote                                                    // device    /**     * Constructor. Prepares a new BluetoothChat session.     *      * @param context     *            The UI Activity Context     * @param handler     *            A Handler to send messages back to the UI Activity     */    public BluetoothService(Context context, Handler handler) {        mAdapter = BluetoothAdapter.getDefaultAdapter();        mState = STATE_NONE;        mHandler = handler;    }    /**     * Set the current state of the chat connection     *      * @param state     *            An integer defining the current connection state     */    private synchronized void setState(int state) {        if (D)            Log.d(TAG, "setState() " + mState + " -> " + state);        mState = state;        // Give the new state to the Handler so the UI Activity can update        mHandler.obtainMessage(MeasureActivity.MESSAGE_STATE_CHANGE, state, -1).sendToTarget();    }    /**     * Return the current connection state.     */    public synchronized int getState() {        return mState;    }    /**     * Start the chat service. Specifically start AcceptThread to begin a     * session in listening (server) mode. Called by the Activity onResume()     */    public synchronized void start() {        if (D)            Log.d(TAG, "start");        // Cancel any thread attempting to make a connection        if (mConnectThread != null) {            mConnectThread.cancel();            mConnectThread = null;        }        // Cancel any thread currently running a connection        if (mConnectedThread != null) {            mConnectedThread.cancel();            mConnectedThread = null;        }        // Start the thread to listen on a BluetoothServerSocket        if (mAcceptThread == null) {            mAcceptThread = new AcceptThread();            mAcceptThread.start();        }        setState(STATE_LISTEN);    }    /**     * Start the ConnectThread to initiate a connection to a remote device.     *      * @param device     *            The BluetoothDevice to connect     */    public synchronized void connect(BluetoothDevice device) {        if (D)            Log.d(TAG, "connect to: " + device);        // Cancel any thread attempting to make a connection        if (mState == STATE_CONNECTING) {            if (mConnectThread != null) {                mConnectThread.cancel();                mConnectThread = null;            }        }        // Cancel any thread currently running a connection        if (mConnectedThread != null) {            mConnectedThread.cancel();            mConnectedThread = null;        }        // Start the thread to connect with the given device        mConnectThread = new ConnectThread(device);        mConnectThread.start();        setState(STATE_CONNECTING);    }    /**     * Start the ConnectedThread to begin managing a Bluetooth connection     *      * @param socket     *            The BluetoothSocket on which the connection was made     * @param device     *            The BluetoothDevice that has been connected     */    public synchronized void connected(BluetoothSocket socket, BluetoothDevice device) {        if (D)            Log.d(TAG, "connected");        // Cancel the thread that completed the connection        if (mConnectThread != null) {            mConnectThread.cancel();            mConnectThread = null;        }        // Cancel any thread currently running a connection        if (mConnectedThread != null) {            mConnectedThread.cancel();            mConnectedThread = null;        }        // Cancel the accept thread because we only want to connect to one        // device        if (mAcceptThread != null) {            mAcceptThread.cancel();            mAcceptThread = null;        }        // Start the thread to manage the connection and perform transmissions        mConnectedThread = new ConnectedThread(socket);        mConnectedThread.start();        // Send the name of the connected device back to the UI Activity        Message msg = mHandler.obtainMessage(MeasureActivity.MESSAGE_DEVICE_NAME);        Bundle bundle = new Bundle();        bundle.putString(MeasureActivity.DEVICE_NAME, device.getName());        msg.setData(bundle);        mHandler.sendMessage(msg);        setState(STATE_CONNECTED);    }    /**     * Stop all threads     */    public synchronized void stop() {        if (D)            Log.d(TAG, "stop");        if (mConnectThread != null) {            mConnectThread.cancel();            mConnectThread = null;        }        if (mConnectedThread != null) {            mConnectedThread.cancel();            mConnectedThread = null;        }        if (mAcceptThread != null) {            mAcceptThread.cancel();            mAcceptThread = null;        }        setState(STATE_NONE);    }    /**     * Write to the ConnectedThread in an unsynchronized manner     *      * @param out     *            The bytes to write     * @see ConnectedThread#write(byte[])     */    public void write(byte[] out) {        // Create temporary object        ConnectedThread r;        // Synchronize a copy of the ConnectedThread        synchronized (this) {            if (mState != STATE_CONNECTED)                return;            r = mConnectedThread;        }        // Perform the write unsynchronized        r.write(out);    }    /**     * Indicate that the connection attempt failed and notify the UI Activity.     */    private void connectionFailed() {        setState(STATE_LISTEN);        // Send a failure message back to the Activity        Message msg = mHandler.obtainMessage(MeasureActivity.MESSAGE_TOAST);        Bundle bundle = new Bundle();        bundle.putString(MeasureActivity.TOAST, "不能连接到设备");        msg.setData(bundle);        mHandler.sendMessage(msg);    }    /**     * Indicate that the connection was lost and notify the UI Activity.     */    private void connectionLost() {        setState(STATE_LISTEN);        // Send a failure message back to the Activity        Message msg = mHandler.obtainMessage(MeasureActivity.MESSAGE_TOAST);        Bundle bundle = new Bundle();        bundle.putString(MeasureActivity.TOAST, "连接断开");        msg.setData(bundle);        mHandler.sendMessage(msg);    }    /**     * This thread runs while listening for incoming connections. It behaves     * like a server-side client. It runs until a connection is accepted (or     * until cancelled).     */    private class AcceptThread extends Thread {        // The local server socket        private final BluetoothServerSocket mmServerSocket;        public AcceptThread() {            BluetoothServerSocket tmp = null;            // Create a new listening server socket            try {                tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);            } catch (IOException e) {                Log.e(TAG, "listen() failed", e);            }            mmServerSocket = tmp;        }        public void run() {            if (D)                Log.d(TAG, "BEGIN mAcceptThread" + this);            setName("AcceptThread");            BluetoothSocket socket = null;            // Listen to the server socket if we're not connected            while (mState != STATE_CONNECTED) {                try {                    // This is a blocking call and will only return on a                    // successful connection or an exception                    socket = mmServerSocket.accept();                } catch (IOException e) {                    Log.e(TAG, "accept() failed", e);                    break;                }                // If a connection was accepted                if (socket != null) {                    synchronized (BluetoothService.this) {                        switch (mState) {                        case STATE_LISTEN:                        case STATE_CONNECTING:                            // Situation normal. Start the connected thread.                            connected(socket, socket.getRemoteDevice());                            break;                        case STATE_NONE:                        case STATE_CONNECTED:                            // Either not ready or already connected. Terminate                            // new socket.                            try {                                socket.close();                            } catch (IOException e) {                                Log.e(TAG, "Could not close unwanted socket", e);                            }                            break;                        }                    }                }            }            if (D)                Log.i(TAG, "END mAcceptThread");        }        public void cancel() {            if (D)                Log.d(TAG, "cancel " + this);            try {                mmServerSocket.close();            } catch (IOException e) {                Log.e(TAG, "close() of server failed", e);            }        }    }    /**     * This thread runs while attempting to make an outgoing connection with a     * device. It runs straight through; the connection either succeeds or     * fails.     */    private class ConnectThread extends Thread {        private final BluetoothSocket mmSocket;        private final BluetoothDevice mmDevice;        public ConnectThread(BluetoothDevice device) {            mmDevice = device;            BluetoothSocket tmp = null;            // Get a BluetoothSocket for a connection with the            // given BluetoothDevice            try {                tmp = device.createRfcommSocketToServiceRecord(MY_UUID);            } catch (IOException e) {                Log.e(TAG, "create() failed", e);            }            mmSocket = tmp;        }        public void run() {            Log.i(TAG, "BEGIN mConnectThread");            setName("ConnectThread");            // Always cancel discovery because it will slow down a connection            mAdapter.cancelDiscovery();            // Make a connection to the BluetoothSocket            try {                // This is a blocking call and will only return on a                // successful connection or an exception                mmSocket.connect();            } catch (IOException e) {                connectionFailed();                // Close the socket                try {                    mmSocket.close();                } catch (IOException e2) {                    Log.e(TAG, "unable to close() socket during connection failure", e2);                }                // Start the service over to restart listening mode                BluetoothService.this.start();                return;            }            // Reset the ConnectThread because we're done            synchronized (BluetoothService.this) {                mConnectThread = null;            }            // Start the connected thread            connected(mmSocket, mmDevice);        }        public void cancel() {            try {                mmSocket.close();            } catch (IOException e) {                Log.e(TAG, "close() of connect socket failed", e);            }        }    }    /**     * This thread runs during a connection with a remote device. It handles all     * incoming and outgoing transmissions.     */    private class ConnectedThread extends Thread {        private final BluetoothSocket mmSocket;        private final InputStream mmInStream;        private final OutputStream mmOutStream;        public ConnectedThread(BluetoothSocket socket) {            Log.d(TAG, "create ConnectedThread");            mmSocket = socket;            InputStream tmpIn = null;            OutputStream tmpOut = null;            // Get the BluetoothSocket input and output streams            try {                tmpIn = socket.getInputStream();                tmpOut = socket.getOutputStream();            } catch (IOException e) {                Log.e(TAG, "temp sockets not created", e);            }            mmInStream = tmpIn;            mmOutStream = tmpOut;        }        public void run() {            Log.i(TAG, "BEGIN mConnectedThread");            byte[] buffer = new byte[1024 * 4];            int bytes;            // StringBuilder receivedMsg = new StringBuilder();            // // Keep listening to the InputStream while connected            while (true) {                try {                    // Read from the InputStream                    bytes = mmInStream.read(buffer);                    // Send the obtained bytes to the UI Activity                    mHandler.obtainMessage(MeasureActivity.MESSAGE_READ, bytes, -1, buffer).sendToTarget();                } catch (Exception e) {                    Log.e(TAG, "disconnected", e);                    connectionLost();                    break;                }            }        }        /**         * Write to the connected OutStream.         *          * @param buffer         *            The bytes to write         */        public void write(byte[] buffer) {            try {                mmOutStream.write(buffer);                // Share the sent message back to the UI Activity                mHandler.obtainMessage(MeasureActivity.MESSAGE_WRITE, -1, -1, buffer).sendToTarget();            } catch (IOException e) {                Log.e(TAG, "Exception during write", e);            }        }        public void cancel() {            try {                mmSocket.close();            } catch (IOException e) {                Log.e(TAG, "close() of connect socket failed", e);            }        }    }}

2.设备列表Activity

public class DeviceListActivity extends Activity {    // Debugging    private static final String TAG = "DeviceListActivity";    private static final boolean D = true;    // Return Intent extra    public static String EXTRA_DEVICE_ADDRESS = "device_address";    // Member fields    private BluetoothAdapter mBtAdapter;    private ArrayAdapter<String> mPairedDevicesArrayAdapter;    private ArrayAdapter<String> mNewDevicesArrayAdapter;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        // Setup the window        requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);        setContentView(R.layout.device_list);        // Set result CANCELED incase the user backs out        setResult(Activity.RESULT_CANCELED);        // Initialize the button to perform device discovery        Button scanButton = (Button) findViewById(R.id.button_scan);        scanButton.setOnClickListener(new OnClickListener() {            public void onClick(View v) {                doDiscovery();                v.setVisibility(View.GONE);            }        });        // Initialize array adapters. One for already paired devices and        // one for newly discovered devices        mPairedDevicesArrayAdapter = new ArrayAdapter<String>(this, R.layout.device_name);        mNewDevicesArrayAdapter = new ArrayAdapter<String>(this, R.layout.device_name);        // Find and set up the ListView for paired devices        ListView pairedListView = (ListView) findViewById(R.id.paired_devices);        pairedListView.setAdapter(mPairedDevicesArrayAdapter);        pairedListView.setOnItemClickListener(mDeviceClickListener);        // Find and set up the ListView for newly discovered devices        ListView newDevicesListView = (ListView) findViewById(R.id.new_devices);        newDevicesListView.setAdapter(mNewDevicesArrayAdapter);        newDevicesListView.setOnItemClickListener(mDeviceClickListener);        // Register for broadcasts when a device is discovered        IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);        this.registerReceiver(mReceiver, filter);        // Register for broadcasts when discovery has finished        filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);        this.registerReceiver(mReceiver, filter);        // Get the local Bluetooth adapter        mBtAdapter = BluetoothAdapter.getDefaultAdapter();        // Get a set of currently paired devices        Set<BluetoothDevice> pairedDevices = mBtAdapter.getBondedDevices();        // If there are paired devices, add each one to the ArrayAdapter        if (pairedDevices.size() > 0) {            findViewById(R.id.title_paired_devices).setVisibility(View.VISIBLE);            for (BluetoothDevice device : pairedDevices) {                mPairedDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress());            }        } else {            String noDevices = getResources().getText(R.string.none_paired).toString();            mPairedDevicesArrayAdapter.add(noDevices);        }    }    @Override    protected void onDestroy() {        super.onDestroy();        // Make sure we're not doing discovery anymore        if (mBtAdapter != null) {            mBtAdapter.cancelDiscovery();        }        // Unregister broadcast listeners        this.unregisterReceiver(mReceiver);    }    /**     * Start device discover with the BluetoothAdapter     */    private void doDiscovery() {        if (D)            Log.d(TAG, "doDiscovery()");        // Indicate scanning in the title        setProgressBarIndeterminateVisibility(true);        setTitle(R.string.scanning);        // Turn on sub-title for new devices        findViewById(R.id.title_new_devices).setVisibility(View.VISIBLE);        // If we're already discovering, stop it        if (mBtAdapter.isDiscovering()) {            mBtAdapter.cancelDiscovery();        }        // Request discover from BluetoothAdapter        mBtAdapter.startDiscovery();    }    // The on-click listener for all devices in the ListViews    private OnItemClickListener mDeviceClickListener = new OnItemClickListener() {        public void onItemClick(AdapterView<?> av, View v, int arg2, long arg3) {            // Cancel discovery because it's costly and we're about to connect            mBtAdapter.cancelDiscovery();            // Get the device MAC address, which is the last 17 chars in the            // View            String info = ((TextView) v).getText().toString();            String address = info.substring(info.length() - 17);            // Create the result Intent and include the MAC address            Intent intent = new Intent();            intent.putExtra(EXTRA_DEVICE_ADDRESS, address);            // Set result and finish this Activity            setResult(Activity.RESULT_OK, intent);            finish();        }    };    // The BroadcastReceiver that listens for discovered devices and    // changes the title when discovery is finished    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {        @Override        public void onReceive(Context context, Intent intent) {            String action = intent.getAction();            // When discovery finds a device            if (BluetoothDevice.ACTION_FOUND.equals(action)) {                // Get the BluetoothDevice object from the Intent                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);                // If it's already paired, skip it, because it's been listed                // already                if (device.getBondState() != BluetoothDevice.BOND_BONDED) {                    mNewDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress());                }                // When discovery is finished, change the Activity title            } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {                setProgressBarIndeterminateVisibility(false);                setTitle(R.string.select_device);                if (mNewDevicesArrayAdapter.getCount() == 0) {                    String noDevices = getResources().getText(R.string.none_found).toString();                    mNewDevicesArrayAdapter.add(noDevices);                }            }        }    };}

3.当前activity处理

@Override    public void onStart() {        super.onStart();        // If BT is not on, request that it be enabled.        // setupChat() will then be called during onActivityResult        if (!mBluetoothAdapter.isEnabled()) {            Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);            startActivityForResult(enableIntent, REQUEST_ENABLE_BT);            // Otherwise, setup the chat session        } else {            if (mChatService == null)                setupChat();        }    }    @Override    public synchronized void onResume() {        super.onResume();        if (mChatService != null) {            // Only if the state is STATE_NONE, do we know that we haven't            // started already            if (mChatService.getState() == BluetoothService.STATE_NONE) {                // Start the Bluetooth chat services                mChatService.start();            }        }    }    private void setupChat() {        mChatService = new BluetoothService(this, mHandler);    }    @Override    public synchronized void onPause() {        super.onPause();    }    @Override    public void onStop() {        super.onStop();    }    @Override    public void onDestroy() {        super.onDestroy();        // Stop the Bluetooth chat services        if (mChatService != null)            mChatService.stop();    }    byte END1 = 10;    byte END2 = 13;    byte END3 = 26;    // The Handler that gets information back from the BluetoothChatService    private final Handler mHandler = new Handler() {        @Override        public void handleMessage(Message msg) {            switch (msg.what) {            // case 100:            // byte[] bbbb = (byte[]) msg.obj;            // String cccc = new String(bbbb);            // System.out.println(cccc);            // break;            case MESSAGE_STATE_CHANGE:                switch (msg.arg1) {                case BluetoothService.STATE_CONNECTED:                    btn_connect.setText("已连接:" + mConnectedDeviceName);                    // mTitle.setText(R.string.title_connected_to);                    // mTitle.append(mConnectedDeviceName);                    // mConversationArrayAdapter.clear();                    break;                case BluetoothService.STATE_CONNECTING:                    btn_connect.setText("连接中...");                    break;                case BluetoothService.STATE_LISTEN:                case BluetoothService.STATE_NONE:                    btn_connect.setText("连接");                    break;                }                break;            case MESSAGE_WRITE:                // byte[] writeBuf = (byte[]) msg.obj;                // // construct a string from the buffer                // String writeMessage = new String(writeBuf);                // mConversationArrayAdapter.add("Me:  " + writeMessage);                break;            case MESSAGE_READ:                byte[] readBuf = (byte[]) msg.obj;                String readMessage = new String(readBuf, 0, msg.arg1);                    }                }                break;            case MESSAGE_DEVICE_NAME:                // save the connected device's name                // dismiss();                mConnectedDeviceName = msg.getData().getString(DEVICE_NAME);                Toast.makeText(getApplicationContext(), "连接到 " + mConnectedDeviceName, Toast.LENGTH_SHORT).show();                break;            case MESSAGE_TOAST:                Toast.makeText(getApplicationContext(), msg.getData().getString(TOAST), Toast.LENGTH_SHORT).show();                break;            }        }    };    public void onActivityResult(int requestCode, int resultCode, Intent data) {        switch (requestCode) {        case REQUEST_CONNECT_DEVICE:            // When DeviceListActivity returns with a device to connect            if (resultCode == Activity.RESULT_OK) {                // Get the device MAC address                String address = data.getExtras().getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS);                // Get the BLuetoothDevice object                BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);                // Attempt to connect to the device                mChatService.connect(device);            }            break;        case REQUEST_ENABLE_BT:            // When the request to enable Bluetooth returns            if (resultCode == Activity.RESULT_OK) {                // Bluetooth is now enabled, so set up a chat session                setupChat();            } else {                // User did not enable Bluetooth or an error occured                Toast.makeText(this, R.string.bt_not_enabled_leaving, Toast.LENGTH_SHORT).show();                finish();            }        }    }    private void ensureDiscoverable() {        if (mBluetoothAdapter.getScanMode() != BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {            Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);            discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);            startActivity(discoverableIntent);        }    }

三.问题的处理

1.刚开始就按照文档写的蓝牙,但是把接收到的蓝牙数据打印出来发现数据很乱,有丢失的,有重复的,网上搜了很多资料也没有解决,因为做全站仪蓝牙的很少,所以这个问题一直没有解决,先做完其他功能,又来解决它,实在没办法,我觉得是不是传输速率太快或者处理太快了,我就尝试性的把线程等待了100毫秒,奇迹出现了,数据正常,完好无损,虽然不知道这种解决方式靠不靠谱,经不经得住考验,还是未知,但测试了很久,没出现大的问题,希望有好的解决方式的人能指教一二,谢谢。

2.第二个问题就是停止位,因为数据发送一般会有停止位,判断为停止位时,数据接收完毕,然后才能进行数据处理,因为全站仪停止位是一位,而且也没有这玩意的文档,不知道停止位这个字节是啥,你可以打印出来这一位的值是啥,因为最后是\r\n,所以停止位应该是一个数加\r\n,所以你只要截取每次读完的字节的最后三位进行判断,是否是这三个字节,读到了停止位说明传输完毕了。

3.数据解析的问题。全站仪接收到的是字符串,因为没有对手机进行适配,所以接收到的不好解析,我是通过数据量较小的格式,对字符串进行操作,这一块写的我很恶心,但是没办法,我不知道andriod能解析gsi等格式的现成框架。
4.对于接收到的数据拼接处理。因为每次接收到的数据很短,需要进行拼接处理,有以下几种方法可以拼接成完整的数据
a.StringBuffer
b.写到本地文件
c. 通过view容器,通过append方法进行拼接,最后获取数据

四,最后

因为项目不能公开,所以网上找了一个demo给大家看看,有的是接受数据进行处理。附上地址:http://download.csdn.net/detail/qq_30124547/9542789

0 0
原创粉丝点击