ESP32S蓝牙10

在这次综合应用中,我们算是放大招啦。

这次我们用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;
    }
}


  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

tongyue

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值