BLE 安卓APP控制LED灯的实现

/注:参考AmoMcu源代码修改。


打开APP,检查蓝牙是否打开

BluetoothAdapter mBluetoothAdapter;


final BluetoothManager bluetoothManager =(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
      mBluetoothAdapter = bluetoothManager.getAdapter();

// Ensures Bluetooth is available on the device and it is enabled. If not,
// displays a dialog requesting user permission to enable Bluetooth.
if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
   Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
   startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}

蓝牙扫描
private void scanLeDevice(final boolean enable) {
if (enable) {
    // Stops scanning after a pre-defined scan period.
            mHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    mScanning = false;
                    mBluetoothAdapter.stopLeScan(mLeScanCallback);
                }
            }, SCAN_PERIOD);


            mScanning = true;
            mBluetoothAdapter.startLeScan(mLeScanCallback);
        } else {
            mScanning = false;
            mBluetoothAdapter.stopLeScan(mLeScanCallback);
        }
    }


连接 GATT服务
绑定一个服务
  Intent gattServiceIntent = new Intent(this, BluetoothLeService.class);
    bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE);
注:BluetoothLeService.java,属于安卓源代码,可以到网上下载回来。
// Code to manage Service lifecycle.
    private final ServiceConnection mServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder service) {
            mBluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService();
            if (!mBluetoothLeService.initialize()) {
                Log.e(TAG, "Unable to initialize Bluetooth");
                finish();
            }
            // Automatically connects to the device upon successful start-up initialization.
            mBluetoothLeService.connect(mDeviceAddress);
        }
        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            mBluetoothLeService = null;
        }  
    };




点击某个特征值的响应:
获取前面的数据,不用再次扫描,由扫描页面得到的数据,传过来的
b=getIntent().getExtras();
tv_addr.setText(b.getString(EXTRAS_DEVICE_ADDRESS));
mDeviceAddress=b.getString(EXTRAS_DEVICE_ADDRESS);
tv_name.setText(b.getString(EXTRAS_DEVICE_NAME));
mDeviceName=b.getString(EXTRAS_DEVICE_NAME);
tv_rssi.setText(b.getString(EXTRAS_DEVICE_RSSI));

lv=(ExpandableListView)this.findViewById(R.id.expandableListView1);
lv.setOnChildClickListener(servicesListClickListner);


private final ExpandableListView.OnChildClickListener servicesListClickListner =
           new ExpandableListView.OnChildClickListener() {
               @Override
               public boolean onChildClick(ExpandableListView parent, View v, int groupPosition,
                                           int childPosition, long id) {                                
                   if (mGattCharacteristics != null) {
                       final BluetoothGattCharacteristic characteristic =
                               mGattCharacteristics.get(groupPosition).get(childPosition);
                       
                       //当前目标特征值
                       target_chara= characteristic;
                                               
                       final int charaProp = characteristic.getProperties();
                   
                       if ((charaProp | BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) {
                           mNotifyCharacteristic = characteristic;
                           
                           mBluetoothLeService.setCharacteristicNotification(
                                  characteristic, true);
                       }
                      tv_uuid.setText( characteristic.getUuid().toString());
                      Intent intent=new Intent();
                      b.putString("CONNET_SATE", status);
                      b.putString("UUID", characteristic.getUuid().toString());
                      intent.putExtras(b);
                      intent.setClass(MyGattDetail.this, LEDControl.class);
                      startActivity(intent);
                                     
               return true;
                   }              
                   return false;                
              }                         
   };
读写特征值的数据
读数据:
private static BluetoothGattCharacteristic myCharacteristic=null;
private static BluetoothLeService mBluetoothLeService;
mBluetoothLeService.readCharacteristic(myCharacteristic);


注释:readCharacteristic该函数会调用BluetoothGatt.readCharacteristic(BluetoothGattCharacteristic characteristic)


写数据:
mBluetoothLeService.writeCharacteristic(myCharacteristic);
注释:writeCharacteristic该函数会调用BluetoothGatt.writeCharacteristic(BluetoothGattCharacteristic characteristic)




示例代码:
private char[] buffer =new char [] {0x6F,0x0F,0x0F,0x0F,0x0F,0x0F};
private void send() { 
MyGattDetail .write(ConvertString(buffer));
}


private String ConvertString(char buffer[]){
String nRcvString;
     StringBuffer tStringBuf=new StringBuffer ();
     tStringBuf.append(buffer);      
     nRcvString=tStringBuf.toString();     
     return  nRcvString;
}


device_name = (TextView) findViewById(R.id.ledpage_devname);

ledButton1 = (ToggleButton) findViewById(R.id.ledpage_led1);
ledButton1.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
if(isChecked){
buffer[1]=0x01;
}else{
buffer[1]=0x00;
}
send();
}
});

ledButton2 = (ToggleButton) findViewById(R.id.ledpage_led2);
ledButton2.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
if(isChecked){
buffer[2]=0x01;

}else{
buffer[2]=0x00;
}
send();
}
});
ledButton3 = (ToggleButton) findViewById(R.id.ledpage_led3);
ledButton3.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
// TODO Auto-generated method stub
if(isChecked){
buffer[3]=0x01;
}else{
buffer[3]=0x00;
}
send();
}
});

ledButton4 = (ToggleButton) findViewById(R.id.ledpage_led4);
ledButton4.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
// TODO Auto-generated method stub
if(isChecked){
buffer[4]=0x01;
}else{
buffer[4]=0x00;
}
send();
}
});

使用ToggleButton控件控制LED:
问题:
使用TI的demo会发现打开一个LED会比较慢,偶尔还会失效。也就是说会掉帧,考虑大之前的所写的关于延时值的设置,如下:
Connection Interval(GAPROLE_MIN_CONN_INTERVAL && GAPROLE_MAX_CONN_INTERVAL)- 连接间隔,在BLE的两个设备的连接中使用跳频机制。两个设备使用特定的信道发送和接收数据,然后过一段时间后再使用新的信道(BLE协议栈的链路层处理信道的切换)。两个设备在切换信道后发送和接收数据称为一个连接事件。尽管没有应用数据被发送和接收,两个设备仍旧会交换链路层数据来维持连接。这个连接间隔就是这个两个连接事件的之间的时间间隔。间隔以1.25ms为单元,连接间隔的范围的6-3200既7.5ms-4s(4000ms)之间。
由此可以看出:间隔小,适用于那些需要快速反应的任务。LED灯需要快速的反应,所以经过设置如下:
// Minimum connection interval (units of 1.25ms, 80=100ms) if automatic parameter update request is enabled
#define DEFAULT_DESIRED_MIN_CONN_INTERVAL     6//80
// Maximum connection interval (units of 1.25ms, 800=1000ms) if automatic parameter update request is enabled
#define DEFAULT_DESIRED_MAX_CONN_INTERVAL     80//800

这样子实时体验就有大大的提升。


©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页