android蓝牙与下位机交互

来源:互联网 发布:淘宝买了个单机版 编辑:程序博客网 时间:2024/05/01 17:36

最近在做一个项目,是蓝牙与下位机进行交互,只是简单的数据交互,使用蓝牙4.0.。。。

先看看项目的简易通信协议:

     协议内容,是一个44位字节的通信命令式协议:

协议格式:

   输出格式:pump on + (char)13 + (char)10

    返回格式 10PID 9PStatus 10FID 9FStatus <CF><LR>,去掉结尾符共42位,结尾以char[10]char[13];

解释下:

char[13]char[10]就是“\r\n”;



看懂了这些,开始找思路,其实蓝牙无非就是socket通信,下位机当做S端,终端设备是C端,请求连接S端,然后用socket向S端写数据,写过C的都知道,C中没有String的概

念,只有char*[],这样就有个问题,我们java的命令行是拼接的String字符串,如何去转化成char*[]呢,我们知道C接受数据时候的没有byte,但是要理解byte其实就是无属的char

即(C没有这个类型,byte表示一个字节,对应C的unsigned char),java是没有指针概念的,,其实这里非常简单,,char*[]无非就是一个char型的数组,那么有了这条思路,我

们用String.getByteArray()

即可。转化成字节数组,那么对应的就是C中unsigned char[ ],既然数据类型匹配完成,那么就开始从java入手书写代码:

主界面:


<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent" >    <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:orientation="vertical" >        <ImageButton            android:id="@+id/btnOpenBT"            android:layout_width="60dp"            android:layout_height="60dp"            android:background="@drawable/bluetooth_off" />        <LinearLayout            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:orientation="horizontal" >            <TextView                android:id="@+id/tvDeviceName"                android:layout_width="0dp"                android:layout_height="wrap_content"                android:layout_weight="1"                android:gravity="right"                android:text="Bluetooth"                android:textSize="14sp" />        </LinearLayout>        <TextView            android:layout_width="fill_parent"            android:layout_height="wrap_content"            android:layout_marginTop="30dp"            android:text="写入测试" />        <EditText            android:id="@+id/output_test"            android:layout_width="fill_parent"            android:layout_height="wrap_content" />        <TextView            android:layout_width="fill_parent"            android:layout_height="wrap_content"            android:text="数据回显测试" />        <TextView            android:id="@+id/input_test"            android:layout_width="fill_parent"            android:textSize="14sp"            android:layout_height="30dp" />        <Button            android:id="@+id/start_test"            android:layout_width="fill_parent"            android:layout_height="wrap_content"            android:text="开始测试" />        <Button            android:id="@+id/btn1"            android:layout_width="fill_parent"            android:layout_height="wrap_content"            android:text="pump on" />        <Button            android:id="@+id/btn2"            android:layout_width="fill_parent"            android:layout_height="wrap_content"            android:text="pump off" />        <Button            android:id="@+id/btn3"            android:layout_width="fill_parent"            android:layout_height="wrap_content"            android:text="detector pid_fid" />        <Button            android:id="@+id/btn4"            android:layout_width="fill_parent"            android:layout_height="wrap_content"            android:text="ignite" />    </LinearLayout></ScrollView>
搜索蓝牙布局界面:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical" >    <TextView        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:text="@string/newdevice" />    <ListView        android:id="@+id/lvNewDevices"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_weight="2"        android:stackFromBottom="true" >    </ListView>    <TextView        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:text="@string/paireddevice" />    <ListView        android:id="@+id/lvPairedDevices"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_weight="2"        android:stackFromBottom="true" >    </ListView>    <Button        android:id="@+id/btnScan"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:text="@string/scan" /></LinearLayout>

开始代码:

package com.simpledraw.bluetoothservice;import java.text.DecimalFormat;import android.annotation.SuppressLint;import android.app.Activity;import android.bluetooth.BluetoothAdapter;import android.bluetooth.BluetoothDevice;import android.content.Intent;import android.os.Bundle;import android.os.Handler;import android.util.Log;import android.view.KeyEvent;import android.view.Menu;import android.view.MenuItem;import android.view.View;import android.view.View.OnClickListener;import android.view.animation.Animation;import android.view.animation.RotateAnimation;import android.view.animation.ScaleAnimation;import android.widget.Button;import android.widget.EditText;import android.widget.ImageButton;import android.widget.TextView;import android.widget.Toast;import com.simpledraw.bluetooth.BluetoothCommService;import com.simpledraw.bluetooth.BluetoothEnvironment;import com.simpledraw.bluetooth.ConstantsBluetooth;import com.simpledraw.bluetooth.ScanBTDeviceActivity;import com.simpledraw.bluetooth.data.Datagram;public class MainActivity extends Activity {private TextView tvDirection1, tvDirection2;private ScaleAnimation animTemperature, animHumidity;private RotateAnimation animPressure;private float currentDirection1 = 0, currentDirection2 = 0, currentTemperature = ConstantsEwins.MIN_TEMPERATURE_Y,currentHumidity = 0.0f, currentPressure = 0;DecimalFormat df = new DecimalFormat("0.00");private ImageButton btnOpenBT = null;private TextView tvDeviceName = null;private Datagram datagram = new Datagram();private BluetoothAdapter btAdapter;private BluetoothDevice mDevice;private int[] checked = new int[11];private long exitTime = 0;// 用于再按一次退出private String executStr = "";@SuppressLint("NewApi")@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);getBluetoothAdapter();findAllControls();}private EditText output_edit;private TextView input_edit;private Button startTest;private void findAllControls() {output_edit = (EditText) findViewById(R.id.output_test);input_edit = (TextView) findViewById(R.id.input_test);startTest = (Button) findViewById(R.id.start_test);((Button)findViewById(R.id.btn1)).setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {executStr = ((Button)v).getText().toString();output_edit.setText("");executStr+="\r\n";BluetoothEnvironment.service.write(executStr.getBytes());output_edit.setText(executStr);}});((Button)findViewById(R.id.btn2)).setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {executStr = ((Button)v).getText().toString();output_edit.setText(executStr);output_edit.setText("");executStr+="\r\n";BluetoothEnvironment.service.write(executStr.getBytes());}});((Button)findViewById(R.id.btn3)).setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {executStr = ((Button)v).getText().toString();output_edit.setText(executStr);output_edit.setText("");executStr="log start\r\n";BluetoothEnvironment.service.write(executStr.getBytes());executStr="detector pid_fid\r\n";BluetoothEnvironment.service.write(executStr.getBytes());}});((Button)findViewById(R.id.btn4)).setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {executStr = ((Button)v).getText().toString();output_edit.setText(executStr);output_edit.setText("");executStr+="\r\n";BluetoothEnvironment.service.write(executStr.getBytes());}});startTest.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View arg0) {if(BluetoothEnvironment.service!=null){output_edit.setText("");//String outputData = output_edit.getText().toString();executStr+="\r\n";//byte[] bytes = outputData.getBytes();//byte[] bytes2 = new byte[bytes.length+2];//for(int i = 0;i<bytes.length;i++){//bytes2[i] = bytes[i];//}//bytes2[bytes2.length-2] = 13;//bytes2[bytes2.length-1] = 10;BluetoothEnvironment.service.write(executStr.getBytes());}}});btnOpenBT = (ImageButton) findViewById(R.id.btnOpenBT);btnOpenBT.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View arg0) {Intent intent = new Intent(MainActivity.this, ScanBTDeviceActivity.class);startActivityForResult(intent, ConstantsBluetooth.REQUEST_CONNECT_DEVICE);}});tvDeviceName = (TextView) findViewById(R.id.tvDeviceName);for (int i = 0; i < 11; i++)checked[i] = View.VISIBLE;}private void getBluetoothAdapter() {btAdapter = BluetoothAdapter.getDefaultAdapter();if (btAdapter == null) {Toast.makeText(MainActivity.this, "本设备不支持蓝牙", Toast.LENGTH_SHORT).show();finish();return;}while (!btAdapter.isEnabled()) {if (btAdapter.enable()) {Toast.makeText(MainActivity.this, "蓝牙已经启动", Toast.LENGTH_SHORT).show();break;} else {Toast.makeText(MainActivity.this, "蓝牙启动失败", Toast.LENGTH_SHORT).show();return;}}if (btAdapter.getScanMode() != BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);startActivity(intent);}}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {menu.add(0, 1, 0, R.string.tianjiachuanganqi);return true;}@Overridepublic boolean onOptionsItemSelected(MenuItem item) {if (item.getOrder() == 0) {Intent intent = new Intent(MainActivity.this, AddDeleteSensorsActivity.class);intent.putExtra("checked", checked);startActivityForResult(intent, ConstantsEwins.REQUEST_ADDDELETE_SENSORS);}return super.onOptionsItemSelected(item);}@Overrideprotected void onResume() {System.out.println("------- ON RESUME ---------");super.onResume();if (BluetoothEnvironment.service != null) {if (btAdapter.isEnabled() && BluetoothEnvironment.service.getState() == ConstantsBluetooth.STATE_NONE) {BluetoothEnvironment.service.start();}BluetoothEnvironment.service.setHandler(mHandler, null);} else {BluetoothEnvironment.service = new BluetoothCommService(this, mHandler, null);}}@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);switch (requestCode) {case ConstantsBluetooth.REQUEST_CONNECT_DEVICE:if (resultCode == RESULT_OK) {String address = data.getExtras().getString(ConstantsBluetooth.DEVICE_ADDRESS);mDevice = btAdapter.getRemoteDevice(address);if (mDevice == null)return;if (BluetoothEnvironment.service != null)BluetoothEnvironment.service.connect(mDevice);}break;case ConstantsEwins.REQUEST_ADDDELETE_SENSORS:if (resultCode == RESULT_OK) {}break;default:break;}}@SuppressLint("HandlerLeak")private final Handler mHandler = new Handler() {int length = 0;boolean firstReceived = true;long lastReadTime = System.currentTimeMillis();StringBuffer sb = new StringBuffer(ConstantsEwins.DATA_LENGTH);@Overridepublic void handleMessage(android.os.Message msg) {switch (msg.what) {case ConstantsBluetooth.MESSAGE_STATE_CHANGE:switch (msg.arg1) {case ConstantsBluetooth.STATE_CONNECTED:Toast.makeText(MainActivity.this, "已连接至" + msg.obj + "!!fdasfds", Toast.LENGTH_SHORT).show();tvDeviceName.setText((String) msg.obj);btnOpenBT.setBackgroundResource(R.drawable.bluetooth_on);break;case ConstantsBluetooth.STATE_CONNECTING:Toast.makeText(MainActivity.this, "正在连接,请稍候", Toast.LENGTH_LONG).show();break;case ConstantsBluetooth.STATE_LISTEN:if (ConstantsBluetooth.CONNECTION_FAILED.equals(msg.obj)) {Toast.makeText(MainActivity.this, "连接不成功", Toast.LENGTH_SHORT).show();btnOpenBT.setBackgroundResource(R.drawable.bluetooth_off);} else if (ConstantsBluetooth.CONNECTION_LOST.equals(msg.obj)) {Toast.makeText(MainActivity.this, "连接丢失", Toast.LENGTH_SHORT).show();btnOpenBT.setBackgroundResource(R.drawable.bluetooth_off);}break;case ConstantsBluetooth.STATE_NONE:btnOpenBT.setBackgroundResource(R.drawable.bluetooth_off);break;}break;case ConstantsBluetooth.MESSAGE_WRITE:break;case ConstantsBluetooth.MESSAGE_READ:if (firstReceived)lastReadTime = System.currentTimeMillis();firstReceived = false;if (System.currentTimeMillis() - lastReadTime > ConstantsEwins.DATAGRAM_INTERVAL) {if (length == ConstantsEwins.DATAGRAM_BYTES_LENGTH) {datagram.parseDatagram(sb.toString());modifyViews();}sb = new StringBuffer(ConstantsEwins.DATA_LENGTH);length = 0;}String data = (String) msg.obj;System.out.println("接收到的数据:" + data);Log.e("texts",data);length += msg.arg1;sb.append(data);lastReadTime = System.currentTimeMillis();input_edit.setText(data);//sb.toString()break;}}};@SuppressLint("NewApi")private void modifyViews() {tvDirection1.setText("风向1: " + (datagram.getDirection1() - (datagram.getDirection1() / 360) * 360) + "°");tvDirection2.setText("风向2: " + (datagram.getDirection2() - (datagram.getDirection2() / 360) * 360) + "°");// 风速改变long newDuration;newDuration = calcSpeedDuration(datagram.getSpeed1());newDuration = calcSpeedDuration(datagram.getSpeed2());newDuration = calcSpeedDuration(datagram.getSpeed3());newDuration = calcSpeedDuration(datagram.getSpeed4());newDuration = calcSpeedDuration(datagram.getSpeed5());newDuration = calcSpeedDuration(datagram.getSpeed6());currentDirection1 = datagram.getDirection1();currentDirection2 = datagram.getDirection2();// 温度、湿度和气压float newTemperature = (datagram.getTemperature() - ConstantsEwins.MIN_TEMPERATURE_VALUE)* ConstantsEwins.TEMPERATURE_STEP + ConstantsEwins.MIN_TEMPERATURE_Y;float newHumidity = datagram.getHumidity() * ConstantsEwins.HUMIDITY_STEP + ConstantsEwins.MIN_HUMIDITY_Y;float newPressure = (datagram.getPressure() - ConstantsEwins.MIN_PRESSURE_VALUE) * ConstantsEwins.PRESSURE_STEP;animTemperature = new ScaleAnimation(1.0f, 1.0f, currentTemperature, newTemperature,Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0.8f);animTemperature.setDuration(500);animTemperature.setFillAfter(true);animHumidity = new ScaleAnimation(1.0f, 1.0f, currentHumidity, newHumidity, Animation.RELATIVE_TO_SELF, 0,Animation.RELATIVE_TO_SELF, 0.8f);animHumidity.setDuration(500);animHumidity.setFillAfter(true);animPressure = new RotateAnimation(currentPressure, newPressure, Animation.RELATIVE_TO_SELF, 0.5f,Animation.RELATIVE_TO_SELF, 0.5f);animPressure.setDuration(500);animPressure.setFillAfter(true);currentTemperature = newTemperature;currentHumidity = newHumidity;currentPressure = newPressure;}private long calcSpeedDuration(float speed) {int level;if (speed < 1.5f)level = 1;else if (speed > 1.6 && speed < 5.4)level = 2;else if (speed > 5.5 && speed < 7.9)level = 3;else if (speed > 8.0 && speed < 10.7)level = 4;else if (speed > 10.8 && speed < 13.8)level = 5;else if (speed > 13.9 && speed < 17.1)level = 6;else if (speed > 17.2 && speed < 20.7)level = 7;else if (speed > 20.8 && speed < 24.4)level = 8;else if (speed > 24.5 && speed < 28.4)level = 9;else if (speed > 28.5 && speed < 32.6)level = 10;elselevel = 11;long duration;duration = (11 - level) * ConstantsEwins.SPEED_DURATION_STEP + ConstantsEwins.MIN_SPEED_DURATION;return duration;}@Overridepublic boolean onKeyDown(int keyCode, KeyEvent event) {if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN) {if ((System.currentTimeMillis() - exitTime) > 2000) {Toast.makeText(this, "再按一次退出程序", Toast.LENGTH_SHORT).show();exitTime = System.currentTimeMillis();} else {finish();System.exit(0);}return true;}return super.onKeyDown(keyCode, event);}}

package com.simpledraw.bluetoothservice;import android.content.Context;import android.graphics.Canvas;import android.graphics.drawable.Drawable;import android.util.AttributeSet;import android.widget.ImageView;public class DirectionPointerView extends ImageView {private float mDirection;private Drawable compass;public DirectionPointerView(Context context) {super(context);mDirection = 0.0f;compass = null;}public DirectionPointerView(Context context, AttributeSet attrs) {super(context, attrs);mDirection = 0.0f;compass = null;}public DirectionPointerView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);mDirection = 0.0f;compass = null;}@Overrideprotected void onDraw(Canvas canvas) {if (compass == null) {compass = getDrawable();compass.setBounds(0, 0, getWidth(), getHeight());}canvas.save();canvas.rotate(mDirection, getWidth() / 2, getHeight() / 2);compass.draw(canvas);canvas.restore();}public void updateDirection(float direction) {mDirection = direction;invalidate();}}

package com.simpledraw.bluetoothservice;public class ConstantsEwins {public static final int REQUEST_ADDDELETE_SENSORS = 2;public static final float MAX_SPEED_VALUE = 100;public static final float MIN_SPEED_VALUE = 0;public static final int MIN_SPEED_DURATION = 500;public static final int SPEED_DURATION_STEP = 500;public static final float MAX_TEMPERATURE_VALUE = 53;public static final float MIN_TEMPERATURE_VALUE = -40;public static final float MIN_TEMPERATURE_Y = 0.02f;public static final float TEMPERATURE_STEP = 0.01185f;public static final float MIN_HUMIDITY_Y = 0.0f;public static final float HUMIDITY_STEP = 0.01118f;public static final float MAX_PRESSURE_VALUE = 120;public static final float MIN_PRESSURE_VALUE = 10;public static final float PRESSURE_STEP = 2.38f;public static final int DATAGRAM_INTERVAL = 500;// 报文的字节数public static final int DATAGRAM_BYTES_LENGTH = 20;// 需要使用的数据长度,例如将字节变成16进制字符串的长度,0x80变成80public static final int DATA_LENGTH = 40;}

package com.simpledraw.bluetooth.data;import android.annotation.SuppressLint;@SuppressLint("DefaultLocale")public class DataTypeConverter {public static String double2Str(double d) {return String.format("%.1f", d);}public static double str2Double(String str) {return Double.parseDouble(str);}public static String getMacAddress(String pStr) {return pStr.substring(pStr.length() - 17);}public static double hexStr2Double(String pStr) {int i = Integer.parseInt(pStr, 16);double d;if (pStr.startsWith("F")) {d = (double) (i - 65536) / 100;} else {d = (double) i / 100;}d = ((double) Math.round(d * 10)) / 10;return d;}public static float hexStr2Float(String pStr) {return (float) (hexStr2Double(pStr));}public static int hexStr2Int(String pStr) {return Integer.parseInt(pStr, 16);}}


package com.simpledraw.bluetooth.data;import java.text.DecimalFormat;import com.simpledraw.bluetoothservice.ConstantsEwins;public class Datagram {private float speed1;private float speed2;private float speed3;private float speed4;private float speed5;private float speed6;private int direction1;private int direction2;private float temperature;private int humidity;private float pressure;DecimalFormat df = new DecimalFormat(".00");public float getSpeed1() {return speed1;}public void setSpeed1(float speed1) {this.speed1 = speed1 > ConstantsEwins.MAX_SPEED_VALUE ? ConstantsEwins.MAX_SPEED_VALUE: (speed1 < ConstantsEwins.MIN_SPEED_VALUE ? ConstantsEwins.MIN_SPEED_VALUE : speed1);}public float getSpeed2() {return speed2;}public void setSpeed2(float speed2) {this.speed2 = speed2 > ConstantsEwins.MAX_SPEED_VALUE ? ConstantsEwins.MAX_SPEED_VALUE: (speed2 < ConstantsEwins.MIN_SPEED_VALUE ? ConstantsEwins.MIN_SPEED_VALUE : speed2);}public float getSpeed3() {return speed3;}public void setSpeed3(float speed3) {this.speed3 = speed3 > ConstantsEwins.MAX_SPEED_VALUE ? ConstantsEwins.MAX_SPEED_VALUE: (speed3 < ConstantsEwins.MIN_SPEED_VALUE ? ConstantsEwins.MIN_SPEED_VALUE : speed3);}public float getSpeed4() {return speed4;}public void setSpeed4(float speed4) {this.speed4 = speed4 > ConstantsEwins.MAX_SPEED_VALUE ? ConstantsEwins.MAX_SPEED_VALUE: (speed4 < ConstantsEwins.MIN_SPEED_VALUE ? ConstantsEwins.MIN_SPEED_VALUE : speed4);}public float getSpeed5() {return speed5;}public void setSpeed5(float speed5) {this.speed5 = speed5 > ConstantsEwins.MAX_SPEED_VALUE ? ConstantsEwins.MAX_SPEED_VALUE: (speed5 < ConstantsEwins.MIN_SPEED_VALUE ? ConstantsEwins.MIN_SPEED_VALUE : speed5);}public float getSpeed6() {return speed6;}public void setSpeed6(float speed6) {this.speed6 = speed6 > ConstantsEwins.MAX_SPEED_VALUE ? ConstantsEwins.MAX_SPEED_VALUE: (speed6 < ConstantsEwins.MIN_SPEED_VALUE ? ConstantsEwins.MIN_SPEED_VALUE : speed6);}public int getDirection1() {return direction1;}public void setDirection1(int direction1) {this.direction1 = direction1;}public int getDirection2() {return direction2;}public void setDirection2(int direction2) {this.direction2 = direction2;}public float getTemperature() {return temperature;}public void setTemperature(float temperature) {this.temperature = temperature > ConstantsEwins.MAX_TEMPERATURE_VALUE ? ConstantsEwins.MAX_TEMPERATURE_VALUE: (temperature < ConstantsEwins.MIN_TEMPERATURE_VALUE ? ConstantsEwins.MIN_TEMPERATURE_VALUE: temperature);}public int getHumidity() {return humidity;}public void setHumidity(int humidity) {this.humidity = humidity > 100 ? 100 : (humidity < 0 ? 0 : humidity);}public float getPressure() {return pressure;}public void setPressure(float pressure) {this.pressure = pressure > ConstantsEwins.MAX_PRESSURE_VALUE ? ConstantsEwins.MAX_PRESSURE_VALUE: (pressure < ConstantsEwins.MIN_PRESSURE_VALUE ? ConstantsEwins.MIN_PRESSURE_VALUE : pressure);}public void parseDatagram(String datagram) {// datagram = "01076954204231804B0A08072102C3046307F209";if (datagram == null || datagram == "") {System.out.println("kong");return;}setSpeed1(calcSpeed(datagram.substring(4, 6)));setSpeed2(calcSpeed(datagram.substring(6, 8)));setSpeed3(calcSpeed(datagram.substring(8, 10)));setSpeed4(calcSpeed(datagram.substring(10, 12)));setSpeed5(calcSpeed(datagram.substring(12, 14)));setSpeed6(calcSpeed(datagram.substring(14, 16)));setDirection1(calcDirection(datagram.substring(22, 24) + datagram.substring(20, 22)));setDirection2(calcDirection(datagram.substring(26, 28) + datagram.substring(24, 26)));setTemperature(calcTemperature(datagram.substring(30, 32) + datagram.substring(28, 30)));setHumidity(calcHumidity(datagram.substring(34, 36) + datagram.substring(32, 34)));setPressure(calcPressure(datagram.substring(38, 40) + datagram.substring(36, 38)));}private float calcSpeed(String pStrSpeedHex) {float speed = DataTypeConverter.hexStr2Int(pStrSpeedHex);return speed * 0.765f + 0.35f;}private int calcDirection(String pStrDirectionHex) {int direction = DataTypeConverter.hexStr2Int(pStrDirectionHex);return (int) (direction * 0.094230277);}private float calcTemperature(String pStrTempHex) {float temperature = DataTypeConverter.hexStr2Int(pStrTempHex);return (float) (temperature * 0.088695557 - 86.38);}private int calcHumidity(String pStrHumidityHex) {int humidity = DataTypeConverter.hexStr2Int(pStrHumidityHex);return (int) (humidity * 0.031933594);}private float calcPressure(String pStrPressureHex) {float pressure = DataTypeConverter.hexStr2Int(pStrPressureHex);return (float) (pressure * 0.03479165 + 10.55);}}

package com.simpledraw.bluetooth;import java.util.Set;import android.app.Activity;import android.bluetooth.BluetoothAdapter;import android.bluetooth.BluetoothDevice;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import android.content.IntentFilter;import android.os.Bundle;import android.view.View;import android.view.View.OnClickListener;import android.view.Window;import android.widget.AdapterView;import android.widget.AdapterView.OnItemClickListener;import android.widget.ArrayAdapter;import android.widget.Button;import android.widget.ListView;import android.widget.TextView;import com.simpledraw.bluetooth.data.DataTypeConverter;import com.simpledraw.bluetoothservice.R;public class ScanBTDeviceActivity extends Activity {private Button btnScan = null;private ListView lvNewDevices, lvPairedDevices;private ArrayAdapter<String> adapterNewDevices, adapterPairedDevice;private BluetoothAdapter btAdapter;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// Setup the windowrequestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);setContentView(R.layout.device_list);findAllViews();btAdapter = BluetoothAdapter.getDefaultAdapter();if (btAdapter == null) {finish();return;}Set<BluetoothDevice> pairedDevices = btAdapter.getBondedDevices();for (BluetoothDevice device : pairedDevices) {adapterPairedDevice.add(device.getName() + "\n" + device.getAddress());}IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);registerReceiver(mReceiver, filter);filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);registerReceiver(mReceiver, filter);}private void findAllViews() {btnScan = (Button) findViewById(R.id.btnScan);lvNewDevices = (ListView) findViewById(R.id.lvNewDevices);adapterNewDevices = new ArrayAdapter<String>(ScanBTDeviceActivity.this, android.R.layout.simple_list_item_1);lvNewDevices.setAdapter(adapterNewDevices);lvNewDevices.setOnItemClickListener(DeviceListClickListener);lvPairedDevices = (ListView) findViewById(R.id.lvPairedDevices);adapterPairedDevice = new ArrayAdapter<String>(ScanBTDeviceActivity.this, android.R.layout.simple_list_item_1);lvPairedDevices.setAdapter(adapterPairedDevice);lvPairedDevices.setOnItemClickListener(DeviceListClickListener);btnScan.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View arg0) {discoverDevices();}});}private void discoverDevices() {btnScan.setEnabled(false);setTitle(R.string.scanning);if (btAdapter.isDiscovering()) {btAdapter.cancelDiscovery();}btAdapter.startDiscovery();}private OnItemClickListener DeviceListClickListener = new OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {btAdapter.cancelDiscovery();String address = DataTypeConverter.getMacAddress(((TextView) arg1).getText().toString());Intent intent = new Intent();intent.putExtra(ConstantsBluetooth.DEVICE_ADDRESS, address);setResult(RESULT_OK, intent);finish();}};@Overrideprotected void onDestroy() {super.onDestroy();if (btAdapter != null) {btAdapter.cancelDiscovery();}unregisterReceiver(mReceiver);};private final BroadcastReceiver mReceiver = new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {String action = intent.getAction();if (BluetoothDevice.ACTION_FOUND.equals(action)) {BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);if (device.getBondState() != BluetoothDevice.BOND_BONDED)adapterNewDevices.add(device.getName() + "\n" + device.getAddress());} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {btnScan.setEnabled(true);setTitle(R.string.select_device);}}};}

package com.simpledraw.bluetooth;import java.util.UUID;public class ConstantsBluetooth {public static final int REQUEST_CONNECT_DEVICE = 1;public static final String DEVICE_ADDRESS = "deviceaddress";public static final String CONNECTED_DEVICE_NAME = "connecteddevicename";public static final String SERVER_NAME = "BluetoothComm";public static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");public static final int MESSAGE_STATE_CHANGE = 1;public static final int MESSAGE_READ = 2;public static final int MESSAGE_WRITE = 3;public static final int MESSAGE_DEVICE_NAME = 4;public static final int STATE_NONE = 0; // do nothingpublic static final int STATE_LISTEN = 1; // 监听连接public static final int STATE_CONNECTING = 2; // now initiating an outgoingpublic static final int STATE_CONNECTED = 3; // 已连接上远程设备public static final String CONNECTION_FAILED = "fail";public static final String CONNECTION_LOST = "lost";public static final String CONNECTION_CONNECTED = "connected";public static final String COMMAND_1 = "uLPCC_0000CD?";public static final byte[] COMMAND_ACK = new byte[] { (byte) 0x06 };}

package com.simpledraw.bluetooth;public class BluetoothEnvironment {public static BluetoothCommService service;}

package com.simpledraw.bluetooth;import java.io.BufferedInputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.io.Serializable;import java.util.UUID;import android.annotation.SuppressLint;import android.bluetooth.BluetoothAdapter;import android.bluetooth.BluetoothDevice;import android.bluetooth.BluetoothServerSocket;import android.bluetooth.BluetoothSocket;import android.content.Context;import android.os.Handler;import android.os.Message;import android.util.Log;import android.widget.Toast;public class BluetoothCommService implements Serializable {private static final long serialVersionUID = 1L;private static final String NAME = "BluetoothComm";// SPP协议UUIDprivate static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");// Member fieldsprivate final BluetoothAdapter mAdapter;private Handler mHandler, receiveHandler;private int mState;private AcceptThread mAcceptThread;private ConnectThread mConnectThread;private ConnectedThread mConnectedThread;public BluetoothCommService(Context context, Handler handler, Handler p_receiveHandler) {mAdapter = BluetoothAdapter.getDefaultAdapter();mHandler = handler;receiveHandler = p_receiveHandler;mState = ConstantsBluetooth.STATE_NONE;}public void setHandler(Handler pHandler, Handler p_receiveHandler) {mHandler = pHandler;receiveHandler = p_receiveHandler;}/** * Set the current state of the chat connection *  * @param state *            An integer defining the current connection state */private synchronized void setState(int state) {mState = state;mHandler.obtainMessage(ConstantsBluetooth.MESSAGE_STATE_CHANGE, state, -1).sendToTarget();}/** * Return the current connection state. */public synchronized int getState() {return mState;}/** * 开始服务,主要是开始AcceptThread线程,打开一个监听回话由BaowenActivity的onResume方法调用, * ***开启监听线程**** */public synchronized void start() {// 取消所有正在尝试连接的线程if (mConnectThread != null) {mConnectThread.cancel();mConnectThread = null;}// 取消所有已经连接上的线程if (mConnectedThread != null) {mConnectedThread.cancel();mConnectedThread = null;}// 打开一个监听BluetoothServerSocket的线程if (mAcceptThread == null) {mAcceptThread = new AcceptThread();mAcceptThread.start();// 开启监听线程}setState(ConstantsBluetooth.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) {// Cancel any thread attempting to make a connectionif (mState == ConstantsBluetooth.STATE_CONNECTING) {// 正在连接状态״̬if (mConnectThread != null) {// 有ConnectThread,结束mConnectThread.cancel();mConnectThread = null;}}// Cancel any thread currently running a connectionif (mConnectedThread != null) {// 有处于连接中的线程,结束mConnectedThread.cancel();mConnectedThread = null;}// Start the thread to connect with the given devicemConnectThread = new ConnectThread(device);mConnectThread.start();// 开启新的连接请求线程setState(ConstantsBluetooth.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) {// Cancel the thread that completed the connectionif (mConnectThread != null) {mConnectThread.cancel();mConnectThread = null;}// Cancel any thread currently running a connectionif (mConnectedThread != null) {mConnectedThread.cancel();mConnectedThread = null;}// Cancel the accept thread because we only want to connect to one// deviceif (mAcceptThread != null) {mAcceptThread.cancel();mAcceptThread = null;}// Start the thread to manage the connection and perform transmissionsmConnectedThread = new ConnectedThread(socket);mConnectedThread.start();// 和客户端开始通信// 把已连接的设备的名称发给UI线程Message msg = mHandler.obtainMessage(ConstantsBluetooth.MESSAGE_STATE_CHANGE);msg.arg1 = ConstantsBluetooth.STATE_CONNECTED;msg.obj = device.getName();mHandler.sendMessage(msg);mState = ConstantsBluetooth.STATE_CONNECTED;}/** * Stop all threads */public synchronized void stop() {if (mConnectThread != null) {mConnectThread.cancel();mConnectThread = null;}if (mConnectedThread != null) {mConnectedThread.cancel();mConnectedThread = null;}if (mAcceptThread != null) {mAcceptThread.cancel();mAcceptThread = null;}setState(ConstantsBluetooth.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 objectConnectedThread r;// Synchronize a copy of the ConnectedThreadsynchronized (this) {if (mState != ConstantsBluetooth.STATE_CONNECTED)return;r = mConnectedThread;// 得到连接线程}// Perform the write unsynchronizedr.write(out);}/** * Indicate that the connection attempt failed and notify the UI Activity. */private void connectionFailed() {setState(ConstantsBluetooth.STATE_LISTEN);// // Send a failure message back to the ActivityMessage msg = mHandler.obtainMessage(ConstantsBluetooth.MESSAGE_STATE_CHANGE);msg.obj = "fail";mHandler.sendMessage(msg);}/** * Indicate that the connection was lost and notify the UI Activity. */@SuppressWarnings("unused")private void connectionLost() {setState(ConstantsBluetooth.STATE_LISTEN);// Send a failure message back to the ActivityMessage msg = mHandler.obtainMessage(ConstantsBluetooth.MESSAGE_STATE_CHANGE);msg.obj = "lost";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 {// 本地的socketprivate final BluetoothServerSocket mmServerSocket;public AcceptThread() {BluetoothServerSocket tmp = null;// 创建一个新的监听服务器sockettry {// 根据名称,UUID创建并返回BluetoothServerSocket,这是创建BluetoothSocket服务器端的第一步tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME, SPP_UUID);} catch (IOException e) {}// 得到BluetoothServerSocket对象mmServerSocket = tmp;}public void run() {setName("AcceptThread");// set the name of threadBluetoothSocket socket = null;// Listen to the server socket if we're not connectedwhile (mState != ConstantsBluetooth.STATE_CONNECTED) {// 若没有连接,一直执行try {// 注意:BluetoothServerSocket的accept是一个阻塞性线程,一直到用户成功的配对,因此不要放在Activity中,// 远程蓝牙设备请求跟本设备建立连接请求时,// BluetoothServerSocket会在连接被接收时返回一个被连接的BluetoothSocket对象。socket = mmServerSocket.accept();} catch (IOException e) {break;}// 连接建立成功if (socket != null) {synchronized (BluetoothCommService.this) {switch (mState) {case ConstantsBluetooth.STATE_LISTEN:case ConstantsBluetooth.STATE_CONNECTING:// 已经连接上,开始ConnectedThread线程connected(socket, socket.getRemoteDevice());break;case ConstantsBluetooth.STATE_NONE:case ConstantsBluetooth.STATE_CONNECTED:// 或者设备没有准备好,或者已经连接,都将这个新的BluetoothSocket关掉// 释放服务套接字,但不会关闭accept()返回的BluetoothSockettry {socket.close();} catch (IOException e) {}break;}}}}}public void cancel() {try {mmServerSocket.close();} catch (IOException 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 BluetoothDevicetry {// 通过远程设备直接创建一个BluetoothSocket,要求该设备已经打开了BluetoothServerSocket获得一个BluetoothSocket对象tmp = device.createRfcommSocketToServiceRecord(SPP_UUID);} catch (IOException e) {}mmSocket = tmp;}public void run() {setName("ConnectThread");// 取消搜索mAdapter.cancelDiscovery();// Make a connection to the BluetoothSockettry {// This is a blocking call and will only return on a// successful connection or an exceptionmmSocket.connect();} catch (IOException e) {connectionFailed();// Close the sockettry {mmSocket.close();} catch (IOException e2) {}// Start the service over to restart listening modeBluetoothCommService.this.start();return;}// Reset the ConnectThread because we're donesynchronized (BluetoothCommService.this) {mConnectThread = null;}// Start the connected thread,已连接上,管理连接connected(mmSocket, mmDevice);}public void cancel() {try {mmSocket.close();} catch (IOException 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 OutputStream mmOutStream;private final BufferedInputStream reader;public ConnectedThread(BluetoothSocket socket) {mmSocket = socket;InputStream tmpIn = null;OutputStream tmpOut = null;// Get the BluetoothSocket input and output streamstry {tmpIn = socket.getInputStream();tmpOut = socket.getOutputStream();} catch (IOException e) {}reader = new BufferedInputStream(tmpIn);mmOutStream = tmpOut;}private String dataStr = "";@SuppressLint("NewApi")public void run() {byte[] buffer = new byte[44], temp = new byte[127];StringBuffer sb;String b;int numReadedBytes;boolean cleaning = true;long startTime = System.currentTimeMillis();// 保持对InputStream的监听while (true) {try {//if (cleaning) {////if (System.currentTimeMillis() - startTime < 2000) {////////numReadedBytes = reader.read(temp);//// System.out.println("cleaning:" + numReadedBytes);//continue;////} else////cleaning = false;//}numReadedBytes = reader.read(buffer);//tempString tempStr = new String(buffer);//temp write to logtempStr.replace("\r\n", "***");String[] strs = tempStr.split("\r\n");// System.out.println("numReaded0:" + numReadedBytes);Log.d("texts",tempStr);sb = new StringBuffer();//for (int i = 0; i < numReadedBytes; i++) {//b = Integer.toHexString(buffer[i] & 0xFF);//if (b.length() < 2)//sb.append("0");//sb.append(b);//}mHandler.obtainMessage(ConstantsBluetooth.MESSAGE_READ, numReadedBytes, 0, new String(buffer)).sendToTarget();buffer = new byte[44];} catch (Exception e) {e.printStackTrace();}}}/** * Write to the connected OutStream. *  * @param buffer *            The bytes to write */public void write(byte[] buffer) {try {mmOutStream.write(buffer);mHandler.obtainMessage(ConstantsBluetooth.MESSAGE_WRITE, -1, -1, buffer).sendToTarget();} catch (IOException e) {e.printStackTrace();Log.i("texts", "数据流写入失败");}}public void cancel() {try {mmSocket.close();} catch (IOException e) {}}}}

OK,,,这样我所以项目都贴到上面了,,因为个人原因,不能贴项目源码,,但是改了一个项目,,亲测可用,,

我们要重点注意这里

MainActivity.java:

((Button)findViewById(R.id.btn1)).setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {executStr = ((Button)v).getText().toString();output_edit.setText("");executStr+="\r\n";BluetoothEnvironment.service.write(executStr.getBytes());output_edit.setText(executStr);}});


这段是真实向下位机写数据,,如果你项目非常紧急,建议直接找到此处,修改这里,还有类似位置,然后我们在看看S端Return的值:

MainActivity.java:

case ConstantsBluetooth.MESSAGE_READ:if (firstReceived)lastReadTime = System.currentTimeMillis();firstReceived = false;if (System.currentTimeMillis() - lastReadTime > ConstantsEwins.DATAGRAM_INTERVAL) {if (length == ConstantsEwins.DATAGRAM_BYTES_LENGTH) {datagram.parseDatagram(sb.toString());modifyViews();}sb = new StringBuffer(ConstantsEwins.DATA_LENGTH);length = 0;}String data = (String) msg.obj;System.out.println("接收到的数据:" + data);Log.e("texts",data);length += msg.arg1;sb.append(data);lastReadTime = System.currentTimeMillis();input_edit.setText(data);//sb.toString()break;

以上即可与下位机交互,,,图片资源请自行寻找,,懒得贴了,,不做伸手党!!!




0 0