Android接收蓝牙万用表数据
来源:互联网 发布:mac 终端怎么切换用户 编辑:程序博客网 时间:2024/04/29 03:17
刚刚做了一个关于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) findViewById(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的博客 - 博客频道 - CSDNhttp://blog.chinaunix.net/uid-21411227-id-5750386.htm
http://blog.csdn.Net/yanglei0917/article/details/52947719?locationNum=7&fps=1
阅读全文
0 0
- Android接收蓝牙万用表数据
- android蓝牙(二)——接收数据
- Android:蓝牙接收心电计数据 绘制心电图
- 蓝牙后台接收数据
- Android蓝牙搜索设备,向其发送数据并接收
- [蓝牙]蓝牙后台接收数据(BLE4.0)
- Android开发蓝牙篇之蓝牙配对、连接与接收数据
- Android蓝牙开发之数据窜位和数据接收错误以及重组字节数据
- 关于蓝牙接收数据的解决方案
- iOS蓝牙后台接收数据(BLE4.0)
- 蓝牙后台接收数据(BLE4.0)
- iOS开发- 蓝牙后台接收数据
- iOS蓝牙4.0(BLE)-后台接收数据
- 蓝牙后台接收数据(BLE4.0)
- iOS蓝牙4.0(BLE)-后台接收数据
- 蓝牙通信,接收数据粘包
- android 蓝牙编程重点---如何发送和接收16进制数据
- android 蓝牙编程重点---如何发送和接收16进制数据
- 从数据库获取数据实现动态曲线表
- struts2.5的method使用通配符无效问题
- Fill UVA
- 详解设计模式——建造者模式
- 滑动冲突(上)
- Android接收蓝牙万用表数据
- Makefile中=与:=的准确定义与区别(转载)
- eclipse搭建SSH框架
- 2017衢州联赛第四题题解
- HeadFirstJava 7,8,9
- 设计模式学习笔记(Java篇)之单例模式
- Android真机调试异常java.net.SocketTimeoutException
- 【LeetCode】129. Sum Root to Leaf Numbers
- 湘潭OJ 1264 挺好的一道贪心题