蓝牙相关api及mesh组网在应用层的讨论

1 传统蓝牙
通信使用socket
使用1对1连接
扫描

BluetoothAdapter bt = BluetoothAdapter.getDefaultAdapter();
if (!bt.isDiscovering())
    bt.startDiscovery();

扫描结果回调
自定义一个广播接收器的回调

String action = intent.getAction();
if (action == null)
    return;
Log.i(TAG, "===" + action);
BluetoothDevice dev = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (dev != null)
    Log.i(TAG, "BluetoothDevice: " + dev.getName() + ", " + dev.getAddress());
switch (action) {
    case BluetoothDevice.ACTION_FOUND:
        short rssi = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI, Short.MAX_VALUE);
        Log.i(TAG, "EXTRA_RSSI:" + rssi);
        mListener.foundDev(dev);
        break;
....

然后可以用一个列表展示出来
连接
如要在两台设备之间创建连接,您必须同时实现服务器端和客户端机制,因为其中一台设备必须开放服务器套接字,而另一台设备必须使用服务器设备的 MAC 地址发起连接。服务器设备和客户端设备均会以不同方法获得所需的 BluetoothSocket。接受传入连接后,服务器会收到套接字信息。在打开与服务器相连的 RFCOMM 通道时,客户端会提供套接字信息。
当服务器和客户端在同一 RFCOMM 通道上分别拥有已连接的 BluetoothSocket 时,即可将二者视为彼此连接。这种情况下,每台设备都能获得输入和输出流式传输,并开始传输数据,相关详细介绍请参阅管理连接部分。本部分介绍如何在两台设备之间发起连接。
使用mac地址发起连接

 BluetoothSocket socket = dev.createInsecureRfcommSocketToServiceRecord(SPP_UUID);

uuid为随机生成的字符串
此时服务端就可以

mSSocket = adapter.listenUsingInsecureRfcommWithServiceRecord(TAG, SPP_UUID);
 BluetoothSocket socket = mSSocket.accept();

建立连接
建立连接后就可以使用 getInputStream() 和 getOutputStream(),分别获取通过套接字处理数据传输的 InputStream 和 OutputStream。
备注 原则上讲一般用1对1传输
蓝牙5.0以下建立socket方法有配对不到的问题
5.0协议之间不存在问题
2 BLE
经试验已证实手机可同时充当ble的主机和从机
客户端扫描
首先获取蓝牙适配器(启动时需要动态申请权限),设置扫描结果的回调(开始扫描停止扫描都需要回调)

private val bleadapter = BluetoothAdapter.getDefaultAdapter()
private val callback = object : ScanCallback() {
override fun onScanFailed(errorCode: Int) {
super.onScanFailed(errorCode)
Toast.makeText(this@MainActivity, errorCode.toString(), Toast.LENGTH_SHORT).show()
}
override fun onScanResult(callbackType: Int, result: ScanResult?) {
       //这里进行蓝牙设备的挑选
        //可以根据mac地址,信号强度等筛选
    }
}

在oncreate时

bluetoothManager= getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager

系统级服务必须在oncreate后调用
// 手动开启蓝牙扫描,回调即可拿到扫描的数据

val scanner = bleadapter.bluetoothLeScanner
        scanner.startScan(callback)
        val hander = Handler()
        hander.postDelayed({
            scanner.stopScan(callback)
        }, 10000)

启动服务端
//这里要设置广播内容,并开启广播回调

bleadapter.bluetoothLeAdvertiser.startAdvertising(
            settings,
            advertiseData,
            scanResponse,
            mAdvertiseCallback
        )
    // 注意:必须要开启可连接的BLE广播,其它设备才能发现并连接BLE服务端!
    // =============启动BLE蓝牙服务端=====================================================================================
    val service = BluetoothGattService(
        UUID_SERVICE,
        BluetoothGattService.SERVICE_TYPE_PRIMARY
    )
    if (bluetoothManager != null) mBluetoothGattServer =
        bluetoothManager.openGattServer(this, mBluetoothGattServerCallback)
    mBluetoothGattServer!!.addService(service)

自定义uuid rt

 companion object{
        val UUID_SERVICE =
            UUID.fromString("10000000-0000-0000-0000-000000000000") //自定义UUID
        val UUID_CHAR_READ_NOTIFY =
            UUID.fromString("11000000-0000-0000-0000-000000000000")
        val UUID_DESC_NOTITY =
            UUID.fromString("11100000-0000-0000-0000-000000000000")
        val UUID_CHAR_WRITE =
            UUID.fromString("12000000-0000-0000-0000-000000000000")
    }
  val settings = AdvertiseSettings.Builder()
        .setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY) //广播模式: 低功耗,平衡,低延迟
        .setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH) //发射功率级别: 极低,低,中,高
        .setConnectable(true) //能否连接,广播分为可连接广播和不可连接广播
        .build()
    //广播数据(必须,广播启动就会发送)
    val advertiseData = AdvertiseData.Builder()
        .setIncludeDeviceName(true) //包含蓝牙名称
        .setIncludeTxPowerLevel(true) //包含发射功率级别
        .addManufacturerData(1, byteArrayOf(23, 33)) //设备厂商数据,自定义
        .build()
    //扫描响应数据(可选,当客户端扫描时才发送)
    val scanResponse = AdvertiseData.Builder()
        .addManufacturerData(2, byteArrayOf(66, 66)) //设备厂商数据,自定义
        .addServiceUuid(ParcelUuid(UUID_SERVICE)) //服务UUID
        //                .addServiceData(new ParcelUuid(UUID_SERVICE), new byte[]{2}) //服务数据,自定义
        .build()
private val mAdvertiseCallback: AdvertiseCallback = object : AdvertiseCallback() {
        override fun onStartSuccess(settingsInEffect: AdvertiseSettings) {
            logTv("BLE广播开启成功")
        }
        override fun onStartFailure(errorCode: Int) {
            logTv("BLE广播开启失败,错误码:$errorCode")
        }
    }

这里同样可以加上需要的特征,例如数据读写或通知等操作
最后实现服务回调即可

val mBluetoothGattServerCallback: BluetoothGattServerCallback =
        object : BluetoothGattServerCallback()

这里的回调同样可以根据特征实现读写

3 Mesh组网基础

可行的点
1 自动配对
2 每个设备即可以作为主节点,又可以作为重节点
3 自定义特征和扫描的值,对于每一个节点,可以根据扫描到的其他节点收发的信息判断是否在网络内
4 可以使用已知算法(泛洪、djstr等)进行节点连接管理
5 可使用定时器等手段在应用层模拟链路层的数据包(再封装一层)来实现自组网算法
不可行的点
每次通信只能传值20个字节
每次通信最好间隔200ms以上
实现难度大,从数据角度讲难度高于个人wifi或rfid

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值