您的位置:首页 > 移动开发 > Android开发

Android接收蓝牙万用表数据

2017-05-25 21:30 183 查看
        刚刚做了一个关于BLE蓝牙通信的Android应用,查阅了不少博客,得到了不少的帮助,现在回头看看这个过程,想把这些代码分享给那些需要的同学,由于第一次写博客,很多地方不懂,写的不好,多多包涵。

       开始正题,关于BLE蓝牙,有不少博客详细介绍了,在关联的URL处添加了一些可以参考,个人觉得最重要的一部分是关于其UUID部分,service和characteristic都有一个唯一的UUID来识别,我们需要知道蓝牙模块发送数据对应的UUID值,而接收或者发送的数据通过characteristic实现,不同的characteristic具有不同的属性(可读,可写,通知),而我们的characteristic包含在service里,即我们需要知道service和characteristic对应的UUID。

       实例化部分代码:参考博客关于心率测量通信,本次通过实验得知服务和接收数据对应的UUID,分别命名为BLE_SERVICE和BLE_SERVICE_READ,其他的UUID包括一些产品信息,以及配置的UUID。

1.BleDefinedUUIDs.java文件

class BleDefinedUUIDs {
//Service对应的UUID
static class Service {
final static UUID BLE_SERVICE=UUID.fromString("0000fff0-0000-1000-8000-00805f9b34fb");
};

static class Characteristic {
//characteristic的UUID
//        final static public UUID HEART_RATE_MEASUREMENT   = UUID.fromString("00002a37-0000-1000-8000-00805f9b34fb");
final static UUID BLE_SERVICE_READ           = UUID.fromString("0000fff4-0000-1000-8000-00805f9b34fb");
final static public UUID MANUFACTURER_STRING      = UUID.fromString("00002a29-0000-1000-8000-00805f9b34fb");
final static public UUID MODEL_NUMBER_STRING      = UUID.fromString("00002a24-0000-1000-8000-00805f9b34fb");
final static public UUID FIRMWARE_REVISION_STRING = UUID.fromString("00002a26-0000-1000-8000-00805f9b34fb");
final static public UUID APPEARANCE               = UUID.fromString("00002a01-0000-1000-8000-00805f9b34fb");
final static public UUID BODY_SENSOR_LOCATION     = UUID.fromString("00002a38-0000-1000-8000-00805f9b34fb");
}

static class Descriptor {
final static UUID CHAR_CLIENT_CONFIG       = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");
}
}


2.MainActivity.java文件

2.1判断设备是否支持蓝牙以及连接蓝牙(BLE蓝牙不同于手机系统配置的蓝牙,不需要输入密码)

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/**
* 判断当前设备是否支持ble
*/
if (!getPackageManager().hasSystemFeature(
PackageManager.FEATURE_BLUETOOTH_LE)) {
System.out.println("不支持BLE设备");
}
//得到蓝牙适配器
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(intent, REQUEST_ENABLE_BT);
}
Button start = (Button) findViewById(R.id.start);
lv = (ListView) findViewById(R.id.lv);
final TextView state = (TextView) findViewById(R.id.state);
adapter = new LeDeviceListAdapter();
start.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
scanLeDevice(true);
lv.setAdapter(adapter);
adapter.clear();
}

});
lv.setOnItemClickListener(new OnItemClickListener() {

private BluetoothGatt gatt;
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
//把搜索到的设备信息放到listview中,然后连接设备
BluetoothDevice device = adapter.getDevice(position);
state.setText("已连接");
gatt = device.connectGatt(getApplicationContext(), false,
mGattCallback);
}
});
}

2.2获得对应的服务以及characteristic

@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
//                System.out.println("Services discovered");
//得到数据信息的service
BluetoothGattService service = gatt
.getService(BLE_SERVICE);
if(service!=null){
mCharacteristic=service.getCharacteristic(BLE_SERVICE_READ);
boolean success=gatt.setCharacteristicNotification(mCharacteristic,true);
if (!success) {
Toast.makeText(MainActivity.this, "数据通知出错", Toast.LENGTH_LONG).show();
}
BluetoothGattDescriptor descriptor = mCharacteristic.getDescriptor(BleDefinedUUIDs.Descriptor.CHAR_CLIENT_CONFIG);
if (descriptor != null) {
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
gatt.writeDescriptor(descriptor);
}
}
}
}

2.3当characteristic的值发生变化时,能够及时获得变化后的值,接收到的数据根据对应的通信协议来实现数据转换。本次接收的为12位16进制数据,通过实验发现其中包含的电压单位信息以及万用表显示的数据信息,通过将接收到的数据变为字符串,对字符串的截取处理十分方便,然后获得其变为float型以实现数据的真实数值。

/**
* 当service里边的characteristic发生改变调用
*/
@Override
public void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
if(characteristic.equals(mCharacteristic))
{
final byte[] raw = mCharacteristic.getValue();
final String data=bytesToHexString(raw);
final int sign=Integer.parseInt(data.substring(10,11));//判断符号位是否为负,若为负则将其设为0
final int dot = Integer.parseInt(data.substring(1, 2));
final int unit=Integer.parseInt(data.substring(0,1));
runOnUiThread(new Runnable() {
@Override
public void run() {
//决定单位为V还是mV
switch(unit){
case 1:
TextView textView=(TextView)findViewById(R.id.unit);
textView.setText("mV");break;
case 2:
TextView textView_1=(TextView)findViewById(R.id.unit);
textView_1.setText("V");break;
default: Toast.makeText(MainActivity.this,"暂没开放此档位相关功能",Toast.LENGTH_SHORT).show();break;
}

//数据显示
if(sign<8) {
if(dot==3|dot==2|dot==1){
int dotDecision= (int) Math.pow(10,dot);//根据记录以及数据格式类型发现,当dot该位置为1,2,3时,
// 其小数点分别位于右2,3,4位,顾考虑将其除以对应的dot次方,格式网站(https://note.youdao.com/share/?token=517D506A7CF04DB3A2406129928B0B08&gid=15157487#/)
float a=((float)Integer.parseInt(data.substring(10, 12) + data.substring(8, 10), 16))/dotDecision;//将字符串连接转换为float类型
String display=a+"";//将float转换为字符串,以显示
TextView textView = (TextView) findViewById(R.id.Info);
textView.setText(display);
}else if(dot==9){
float a=((float)Integer.parseInt(data.substring(10, 12) + data.substring(8, 10), 16))/10;//将字符串连接转换为float类型
String display=a+"";//将float转换为字符串,以显示
TextView textView = (TextView) findViewById(R.id.Info);
textView.setText(display);
}
//                        else {
//                            Toast.makeText(MainActivity.this,"请确认万用表在V档位",Toast.LENGTH_LONG).show();
//                        }
}else {
String display=""+0;//考虑到暂时用不到负数,故将其设置为0处理
TextView textView = (TextView) findViewByI
9979
d(R.id.Info);
textView.setText(display);
Toast.makeText(MainActivity.this,"请检查万用表是否接反而造成负值",Toast.LENGTH_SHORT).show();
}
//                  Toast.makeText(MainActivity.this, data, Toast.LENGTH_LONG).show();
}
});
}else {
Toast.makeText(MainActivity.this, "无数据", Toast.LENGTH_LONG).show();
}
}
//将byte类型转换为字符串类型
public String bytesToHexString(byte[] raw){
StringBuilder stringBuilder = new StringBuilder("");
if (raw == null || raw.length <= 0) {
return null;
}
for (int i = 0; i < raw.length; i++) {
int v = raw[i] & 0xFF;
String hv = Integer.toHexString(v);
if (hv.length() < 2) {
stringBuilder.append(0);
}
stringBuilder.append(hv);
}
return stringBuilder.toString();
}

3.总结



上图为手机界面,由于本次只是接收蓝牙传输数据加以显示,下一步将依据接收到的数据设置阈值以控制其他设备,再写......由于第一次写博客,很仓促,开心就好。

资源下载:BLE蓝牙万用表传输数据 - 下载频道 - CSDN.NET
http://download.csdn.net/detail/bigat/9853524
参考资源:

BLE GATT规范中关于UUID与属性的详细解析-zhenhuaqin-ChinaUnix博客
Android蓝牙Ble开发之获取心率 - yanglei0917的博客 - 博客频道 - CSDN
http://blog.chinaunix.net/uid-21411227-id-5750386.htm http://blog.csdn.Net/yanglei0917/article/details/52947719?locationNum=7&fps=1
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Android 蓝牙通信