在这次综合应用中,我们算是放大招啦。
这次我们用BLE蓝牙设备进行组网通讯,中间的那部手机运行的是BLE客户端程序,因此在这个网络中,成了中心设备;右边的那部手机、以及左边的两个ESP32S模块,都是周围设备。
首先我们先给两个ESP32S开发板接入电脑,我在电脑中打开了两个串口监视器,分别监视两个开发板的收发信息,这样开发板接通电源后,自动广播服务消息。我们也要打开右边的手机中的服务端的APP,并按动广播服务按钮。这样所有的周围设备都已经开始广播服务,做好了被连接的准备。
其次,打开中心设备的手机APP,所有的操作几乎都是在中心设备上完成的。我们可以扫描蓝牙,这样手机会显示搜索到了周围的三个BLE蓝牙信号。(如果有缺漏,可以重新搜索)
接着可以连接蓝牙。这样中心设备的APP会根据搜索到的蓝牙信号设备列表,一个一个地建立连接,如果建立一个连接成功就会一边显示这个设备信息。
完成连接后,我们可以随便点击列表中的能某一个蓝牙设备,就会向这个设备发送一条消息,(因为所有的周围设备都被设置成自动返回了,也就是周围设备接收到消息时,第一时间把这条消息的内容返送回中心设备),也会接收到这个周围设备返送火来的一条同样内容的消息。
最后,如果你不想连接了,可以按断开连接按钮,即可断开周围所有设备,并清空设备列表。
实现BLE一拖几的基本原理:
1. 我对若干个BLE蓝牙设备的组网(一个中心设备,同时连接和控制多个周围的设备)问题一直耿耿于怀。于是查阅了网上的一些资料,发现蓝牙真的可以和周围的7个蓝牙设备同时连接;当然通讯只能是轮流的,也就是中心设备挨个与周围设备进行通讯。
2. 周围程序就是服务端的程序修改的,增加了自动返回消息的代码而已(当周围设备接收到中心设备发送过来的消息时,把接收到的消息原样返回给中心设备)。
3. 关键的控制在与中心设备,他起到控制连接,控制通讯的作用。
那我们还是先来看一下,BLE是怎样把用户消息发送给另一个BLE的:
character_write.setValue(str);
bluetoothGatt.writeCharacteristic(character_write);
从这两行发送代码可以看出,发送消息需要用到的是BluetoothGatt蓝牙服务系统, character_write蓝牙写通道(特征),当然还接受消息还需要另一个character_read蓝牙读通道。我们有了这三个东西,就能实现两个BLE蓝牙设备完成通讯了。
4. 要实现中心设备与若干个周围设备同时保持连接,我们采用一种HasMap的集合来保存每一个周围设备的BluetoothGatt、character_write、character_read。
以保存BluetoothGatt为例:
private HashMap<String, BluetoothGatt> mBluetoothGattMap;
这句代码是定义一个HasMap对象,这个由一个一个的<键名,键值>组成的集合,键名是搜索到的周围设备的MAC地址字符串,键值就是对应的这个设备的BluetoothGatt服务框架对象了。
mBluetoothGattMap.put(address, bluetoothGatt);
这句代码是当我们成功地与周围的一个设备完成连接时,就把这个设备的<address,BluetoothGatt>保存到集合中。
for (Map.Entry<String, BluetoothGatt> s : mBluetoothGattMap.entrySet()) {
String key = s.getKey();
if (addstr.equals(key)) {
bluetoothGatt = s.getValue();
break;
}
}
这几行代码是对这个集合进行一个一个地读取(轮询),并与指定的MAC地址进行比较,找出指定设备的BluetoothGatt对象。也就是我们在APP中,有一个列表保存的是已连接的周围设备的MAC地址,当用户随便点击某一个设备时,APP就能获得用户选择的设备的MAC地址,然后经过对这个集合进行一个一个的轮询,就能根据MAC地址,找出这个设备的BluetoothGatt对象了。
character_read = mGattCharacteristicNotifyMap.get(addstr);
当然我们也可以不用轮询,而是直接使用设备的MAC地址,直接从集合中把需要的对象读取出来。那这边就有一个问题了,为什么可以直接读取,那还需要用轮询呢?其实轮询是必要的,他可以确保知道需要查找的这个设备究竟在不在这个集合中,也就是只有先在集合中找到了这个设备,才获取这个设备。而使用GET的直接读取的方法,如果这个设备已经断开了,已经不在这个集合中了,你使用了GET就会返回一个空对象NULL。
mBluetoothGattMap.remove(address);
当APP检测到某一个设备已经断开时(如果某个设备停止运行,或者离开了十几二十米,中心设备就会检测这个设备已经断开连接),我们可以用这句代码把这个设备从集合中移除出去,当然列表项也是要移除的,这样用户才能看到某个设备已经断开的消息。
创建、插入、轮询、读取、移除,这写就是HasMap集合有关的一些操作。我们就是通过这些操作,来保存周围BLE设备的通讯对象的,并实现了中心设备与若干个周围设备组网、通讯的。
最后贴上程序源码,算是笔记吧。这个是主程序 MainActivity. java
package com.example.bluetooth;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Build;
import android.view.MotionEvent;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
@SuppressLint("NewApi")
public class MainActivity extends AppCompatActivity {
private UUID mServiceUUID = UUID.fromString("6E400001-B5A3-F393-E0A9-E50E24DCCA9E");
private UUID mReadUUID = UUID.fromString("6E400003-B5A3-F393-E0A9-E50E24DCCA9E");
private UUID mWriteUUID = UUID.fromString("6E400002-B5A3-F393-E0A9-E50E24DCCA9E");
private Button scan_button, send_button, discon_button;
private TextView msgstr;
private EditText msgstr02;
private BluetoothAdapter bleadapter;
private BluetoothGatt bluetoothGatt;
private BluetoothGattCharacteristic character_read, character_write;
private BluetoothDevice bledevice;
private List<BluetoothDevice> mDeviceList;
private HashMap<String, BluetoothGatt> mBluetoothGattMap; //临时保存 BluetoothGatt
private HashMap<String, BluetoothGattCharacteristic> mGattCharacteristicMap;// 临时保存蓝牙的特征值 Characteristic
private HashMap<String, BluetoothGattCharacteristic> mGattCharacteristicNotifyMap;// 临时保存蓝牙的特征值 Characteristic
private ArrayList list;
private ArrayAdapter adapter;
private ListView mListView;
private int inval=0;
private boolean connected = false;
private String addstr ="";
private Handler handler= new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
msgstr02.setText(msgstr02.getText().toString() + "in: " + (String) msg.obj);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
msgstr = (TextView)findViewById(R.id.txt_msg);
msgstr02 = (EditText)findViewById(R.id.txt_msg02);
scan_button = (Button)findViewById(R.id.btn_scan);
send_button = (Button)findViewById(R.id.btn_send);
discon_button = (Button)findViewById(R.id.btn_discon);
mListView = (ListView)findViewById(R.id.listView1);
msgstr02.setFocusable(false);
//初始化ble设配器
BluetoothManager manager = (BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE);
bleadapter = manager.getAdapter();
//判断蓝牙是否开启,若是关闭则请求打开蓝牙
if (bleadapter == null || !bleadapter.isEnabled()) {
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(intent, 1);
}
//搜索按钮
scan_button.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
msgstr.setText("扫描中,请稍候 ...");
//初始化列表变量,一个用于存储自定义类,一个用于存储字符串
mDeviceList=new ArrayList<BluetoothDevice>();
list = new ArrayList();
//把扫描过程放进一个线程里面进行
new Thread(new Runnable() {
@Override
public void run() {
//如果发现一个BLE设备,就会执行一次callback回调函数
bleadapter.startLeScan(callback);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
bleadapter.stopLeScan(callback);
msgstr.setText("");
}
}).start();
}
});
//连接服务按钮
send_button.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
mBluetoothGattMap = new HashMap<String, BluetoothGatt>();
mGattCharacteristicMap = new HashMap<String, BluetoothGattCharacteristic>();
mGattCharacteristicNotifyMap = new HashMap<String, BluetoothGattCharacteristic>();
Thread t = new Thread() {
int acid = 0;
int devices = mDeviceList.size();
public void run() {
while(acid < devices) {
connected = false;
bledevice = mDeviceList.get(acid);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
bluetoothGatt = bledevice.connectGatt(MainActivity.this, false, gattcallback, BluetoothDevice.TRANSPORT_LE);
else
bluetoothGatt = bledevice.connectGatt(MainActivity.this, false, gattcallback);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(connected)
{
Message mesg = new Message();
mesg.what = 1;
mesg.obj = "获取服务" + bledevice.getAddress() + "\n\r";
MainActivity.this.handler.sendMessage(mesg);
}
acid++;
}
}
};
t.start();
}
});
//断开连接按钮
discon_button.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
Thread t = new Thread() {
int acid = 0;
int devices = mDeviceList.size();
public void run() {
while(acid < devices) {
addstr = mDeviceList.get(acid).getAddress();
bluetoothGatt = mBluetoothGattMap.get(addstr);
if(bluetoothGatt != null)
bluetoothGatt.disconnect();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
acid++;
}
}
};
t.start();
list.clear();
adapter = new ArrayAdapter(MainActivity.this, android.R.layout.simple_list_item_1, list);
mListView.setAdapter(adapter);
msgstr.setText("已经停止所有的连接");
}
});
//列表框侦听,当用户点击选择蓝牙时,连接蓝牙
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
BluetoothDevice mbledevice = mDeviceList.get(position);
addstr = mbledevice.getAddress();
String adstr = "";
boolean coned = false;
for (Map.Entry<String, BluetoothGatt> s : mBluetoothGattMap.entrySet()) {
String key = s.getKey();
adstr = adstr + key;
if (addstr.equals(key)) {
bluetoothGatt = s.getValue();
coned = true;
break;
}
}
if(coned) {
character_read = mGattCharacteristicNotifyMap.get(addstr);
setCharacteristicNotification(character_read, true);
character_write = mGattCharacteristicMap.get(addstr);
if(bluetoothGatt==null || character_write==null || character_read==null) {
msgstr.setText("no no" + adstr);
return;
}else {
try {
Thread.sleep(150);
} catch (InterruptedException e) {
e.printStackTrace();
}
inval += 1;
String str = "hello" + inval+ "\n\r";
character_write.setValue(str);
bluetoothGatt.writeCharacteristic(character_write);
msgstr02.setText(msgstr02.getText().toString()+ "ou: "+ str);
}
}else {
msgstr.setText("no " + adstr);
}
}
});
}
//这个是蓝牙扫描的回调函数,每当扫描到一个BLE设备时,就会运行一次这个函数
public BluetoothAdapter.LeScanCallback callback = new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice bluetoothDevice, int i, byte[] bytes) {
if (bluetoothDevice != null){
//这里给大家另外两种显示扫描结果的方法,可以用消息框或标签来显示
//Toast.makeText(MainActivity.this,bluetoothDevice.getName(), Toast.LENGTH_SHORT).show();
//showresult.append(bleDevice.getName() + " " + bleDevice.getMac() +"\n");
if(!mDeviceList.contains(bluetoothDevice)){
mDeviceList.add(bluetoothDevice);
//list是存储字符串的集合,adapter是连接字符串到列表框的工具
list.add(bluetoothDevice.getName() + " " + bluetoothDevice.getAddress());
adapter = new ArrayAdapter(MainActivity.this, android.R.layout.simple_list_item_1, list);
mListView.setAdapter(adapter);
}
}
}
};
//这个是蓝牙管理的回调函数,管理BLE的连接、获取服务、读写消息
private BluetoothGattCallback gattcallback = new BluetoothGattCallback() {
//连接状态,当APP与BLE连接成功、或者连接断开时,都会触发这个事件
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, final int newState) {
super.onConnectionStateChange(gatt, status, newState);
runOnUiThread(new Runnable() {
@Override
public void run() {
switch (newState) {
//已经连接
case BluetoothProfile.STATE_CONNECTED:
//当连接成功,就获取BLE的服务,并触发获取服务的事件
bluetoothGatt.discoverServices();
break;
//正在连接
case BluetoothProfile.STATE_CONNECTING:
msgstr.setText("正在连接" + "\n");
break;
//连接断开
case BluetoothProfile.STATE_DISCONNECTED:
try{
String address = bluetoothGatt.getDevice().getAddress();
mBluetoothGattMap.remove(address);
mGattCharacteristicMap.remove(address);
mGattCharacteristicNotifyMap.remove(address);
bluetoothGatt.close();
msgstr02.setText("");
}catch(Exception e){
e.printStackTrace();
}
break;
//正在断开
case BluetoothProfile.STATE_DISCONNECTING:
msgstr.setText("断开中" + "\n");
break;
}
}
});
}
//这个是获取BLE服务的事件,如果获取成功
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
super.onServicesDiscovered(gatt, status);
if (status == BluetoothGatt.GATT_SUCCESS) {
BluetoothGattService gattService = bluetoothGatt.getService(mServiceUUID);
//获取指定的UUID服务不为空时
if(gattService != null){
//获取指定的UUID读写通道
character_read= gattService.getCharacteristic(mReadUUID);
character_write= gattService.getCharacteristic(mWriteUUID);
//把读取通道设置为可侦听、可读取状态
if(character_read!= null)
setCharacteristicNotification(character_read, true);
String address = bluetoothGatt.getDevice().getAddress();
mBluetoothGattMap.put(address, bluetoothGatt);
mGattCharacteristicNotifyMap.put(address, character_read);
mGattCharacteristicMap.put(address, character_write);
connected = true;
}else{
msgstr.setText("获取服务失败");
}
}
}
@Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicRead(gatt, characteristic, status);
}
@Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicWrite(gatt, characteristic, status);
}
//这个是侦听事件,当有数据从BLE设备传入APP的时候,就会引发这个事件
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
super.onCharacteristicChanged(gatt, characteristic);
if(characteristic == character_read){
Message mesg = new Message();
mesg.what = 1;
mesg.obj = new String(characteristic.getValue());
MainActivity.this.handler.sendMessage(mesg);
}
}
@Override
public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
super.onDescriptorRead(gatt, descriptor, status);
}
@Override
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
super.onDescriptorWrite(gatt, descriptor, status);
}
@Override
public void onReliableWriteCompleted(BluetoothGatt gatt, int status) {
super.onReliableWriteCompleted(gatt, status);
}
@Override
public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
super.onReadRemoteRssi(gatt, rssi, status);
}
@Override
public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
super.onMtuChanged(gatt, mtu, status);
}
} ;
//这个是把某个通道设置为可侦听状态
public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic, boolean enabled) {
bluetoothGatt.setCharacteristicNotification(characteristic, enabled);
boolean isEnableNotification = bluetoothGatt.setCharacteristicNotification(characteristic, enabled);
if(isEnableNotification) {
//一个读写通道里面,可能一次就传递多个类型的数值,每个类型数字都要设置侦听属性
List<BluetoothGattDescriptor>descriptorList = characteristic.getDescriptors();
if(descriptorList != null&& descriptorList.size()> 0) {
for(BluetoothGattDescriptor descriptor : descriptorList) {
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
bluetoothGatt.writeDescriptor(descriptor);
}
}
}
}
}
这个是界面设计 activity_main. xml
<LinearLayout 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"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<Button
android:id="@+id/btn_scan"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="扫描蓝牙" />
<Button
android:id="@+id/btn_send"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="连接蓝牙" />
<ListView
android:id="@+id/listView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="visible" />
<Button
android:id="@+id/btn_discon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="断开蓝牙" />
<TextView
android:id="@+id/txt_msg"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<EditText
android:id="@+id/txt_msg02"
android:minLines="12"
android:gravity="top"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
这个是安卓的版本号以及权限申请 在AndroidManifest. xml
<uses-sdk
android:minSdkVersion="11"
android:targetSdkVersion="21" />
<!-- 添加蓝牙权限 -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-feature android:name="android.hardware.location.gps" />
<!-- Android6.0 蓝牙扫描才须要-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission-sdk-23 android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
这个是周围设备服务端的程序,在接收消息的时候,增加了自动返回消息的代码:
//获取接收,接收的数据为参数中的value
@Override
public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId, BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {
super.onCharacteristicWriteRequest(device, requestId, characteristic, preparedWrite, responseNeeded, offset, value);
gattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, value);
String str = new String(value);
character_write.setValue(str);
gattServer.notifyCharacteristicChanged(bluetoothDevice, character_write, false);
Message mesg = new Message();
mesg.what = 1;
mesg.obj = str;
MainActivity.this.handler.sendMessage(mesg);
}
这个是ESP32S开发板的修改后的驱动程序,增加了自动返回的代码,是用arduino IDE写的:
// 包含所必需的库
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
BLEServer *pServer = NULL;
BLECharacteristic *pTxCharacteristic;
bool deviceConnected = false;
bool oldDeviceConnected = false;
char BLEbuf[32] = {0};
String data = "";
// 定义收发服务的UUID(唯一标识)
#define SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E"
// RX串口标识
#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
// TX串口标识
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"
class MyServerCallbacks: public BLEServerCallbacks {
void onConnect(BLEServer* pServer) {
deviceConnected = true;
};
void onDisconnect(BLEServer* pServer) {
deviceConnected = false;
}
};
class MyCallbacks: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
std::string rxValue = pCharacteristic->getValue();
if (rxValue.length() > 0) {
delay(5);
pTxCharacteristic->setValue(rxValue); //收到数据后返回数据
pTxCharacteristic->notify();
data =rxValue.c_str();
}
}
};
// setup()在复位或上电后运行一次:
void setup() {
Serial.begin(115200);
// 初始化蓝牙设备
BLEDevice::init("MyESP32");
// 为蓝牙设备创建服务器
pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks());
// 基于SERVICE_UUID来创建一个服务
BLEService *pService = pServer->createService(SERVICE_UUID);
pTxCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID_TX,
BLECharacteristic::PROPERTY_NOTIFY
);
pTxCharacteristic->addDescriptor(new BLE2902());
BLECharacteristic * pRxCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID_RX,
BLECharacteristic::PROPERTY_WRITE
);
pRxCharacteristic->setCallbacks(new MyCallbacks());
// 开启服务
pService->start();
// 开启通知
pServer->getAdvertising()->start();
Serial.println("Waiting a client connection to notify...");
Serial.println();
}
// loop()一直循环执行:
void loop() {
if (deviceConnected==1 & data.length()>0) {
//String ss="hello";
memset(BLEbuf, 0, 32);
memcpy(BLEbuf, data.c_str(), 32);//数据赋值
Serial.println(BLEbuf);
data = ""; //返回数据后进行清空,否则一直发送data
}
if (Serial.available() > 0)//串口接收到数据
{
delay(20);
String inputString = "";
while(Serial.available())
inputString = inputString + char(Serial.read());
pTxCharacteristic->setValue(inputString.c_str()); //收到数据后返回数据
pTxCharacteristic->notify();
}
// 没有新连接时
if (!deviceConnected && oldDeviceConnected) {
// 给蓝牙堆栈准备数据的时间
delay(500);
pServer->startAdvertising();
// 重新开始广播
Serial.println("start advertising");
oldDeviceConnected = deviceConnected;
}
// 正在连接时
if (deviceConnected && !oldDeviceConnected) {
// 正在连接时进行的操作
oldDeviceConnected = deviceConnected;
}
}