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