Android Ble蓝牙App(二)连接与发现服务

这篇具有很好参考价值的文章主要介绍了Android Ble蓝牙App(二)连接与发现服务。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

  在上一篇中我们进行扫描设备的处理,本文中进行连接和发现服务的数据处理,运行效果图如下所示:
android ble蓝牙调用 ui线程,蓝牙,BLE连接设备,BLE发现服务

目录

  • Ble蓝牙App(一)扫描
  • Ble蓝牙App(二)连接与发现服务
  • Ble蓝牙App(三)特性和属性
  • Ble蓝牙App(四)UI优化和描述符
  • Ble蓝牙App(五)数据操作

正文

  现在我们从MainActivity进入到ScanActivity,选中一个设备返回到MainActivity,下面要对选中的设备进行处理,首先我们来做连接。

一、GATT回调

  在之前我们写了一个BleCore,这里面是对扫描的封装,那么对于连接来说我们同样可以封装到这里,我们可以在BleCore中写一个BleGattCallback 类,代码如下所示:

class BleGattCallback : BluetoothGattCallback() {

        /**
         * 连接状态改变
         */
        override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) {
            
        }

        /**
         * 发现服务
         */
        override fun onServicesDiscovered(gatt: BluetoothGatt, status: Int) {
            
        }
    }

  因为本文要做的事情是连接和发现服务,所以我们就先重写这两个函数,注意一点的是,蓝牙的操作都是在子线程中进行的,如果我们需要知道当前是否连接,则需要写一个接口用于回调到Activity中,在ble包下新建一个BleCallback接口,代码如下所示:

interface BleCallback {

    /**
     * 设备的所有信息
     */
    fun deviceInfo(info: String)

    /**
     * 连接状态
     * @param state true or false
     */
    fun onConnectionStateChange(state: Boolean)

    /**
     * 发现服务
     */
    fun onServicesDiscovered(services: List<BluetoothGattService>)
}

  接口中定义了三个函数,通过注释我们清晰的知道都是什么作用,这里着重介绍第一个函数,这个函数会显示设备各个时候的状态信息,从连接之后的所有动作,如果我们需要保存设备的操作日志的话,可以通过这个来进行处理保存。

然后回到BleCore,在companion object中声明变量和设置接口回调的函数:

    @SuppressLint("StaticFieldLeak")
    companion object {

        ...

        private var mGatt: BluetoothGatt? = null

        private var mBleCallback: BleCallback? = null

        private lateinit var mBleGattCallback: BleGattCallback
        /**
         * 是否连接
         */
        private var mIsConnected = false

        fun getInstance(context: Context) = instance ?: synchronized(this) {
            instance ?: BleCore(context).also {
                instance = it
                //蓝牙扫描
                bleScan = BleScan.getInstance(context)
                //初始化
                mBleGattCallback = BleGattCallback()
            }
        }		

        /**
         * 设备信息
         */
        private fun deviceInfo(info: String) = mBleCallback?.deviceInfo(info)
        /**
         * 连接状态
         */
        private fun connectState(state: Boolean) {
            mIsConnected = state
            mBleCallback?.onConnectionStateChange(state)
        }
    }

同时在 companion object外创建一个函数,代码如下所示:

    fun setBleCallback(bleCallback: BleCallback) {
        mBleCallback = bleCallback
    }

此函数和setPhyScanCallback()函数是同级的,下面我们增加连接和断连的函数。

二、连接和断连

在BleCore中增加如下代码:

	/**
     * 连接蓝牙设备
     */
    fun connect(device: BluetoothDevice) {
        deviceInfo("连接中...")
        mGatt = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            device.connectGatt(context, false, mBleGattCallback, BluetoothDevice.TRANSPORT_LE, BluetoothDevice.PHY_LE_2M_MASK)
        } else {
            device.connectGatt(context, false, mBleGattCallback)
        }
    }

    /**
     * 断开连接
     */
    fun disconnect() {
        deviceInfo("断开连接...")
        mGatt?.disconnect()
    }

连接与断开连接,调用时会触发onConnectionStateChange()函数。

三、连接状态回调

下面修改这个函数的代码,如下所示:

        override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) {
            val address = gatt.device.address
            when (newState) {
                BluetoothProfile.STATE_CONNECTED -> {
                    deviceInfo("已连接:$address")
                    connectState(true)
                }
                BluetoothProfile.STATE_DISCONNECTED -> {
                    deviceInfo("已断开连接:$address")
                    connectState(false)
                }
                else -> {
                    Log.d(TAG, "onConnectionStateChange: $status")
                    connectState(false)
                    mGatt?.close()
                    mGatt = null
                }
            }
        }

在回调中,连接成功和断开连接都会有一个对应的状态码,通过状态回调到接口函数中,然后回到MainActivity中使用一下这个回调,首先我们修改一下activity_main.xml中的代码,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <com.google.android.material.appbar.MaterialToolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="@color/orange"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:navigationIcon="@drawable/ic_scan_ble"
        app:title="GoodBle"
        app:titleCentered="true"
        app:titleTextColor="@color/white">

        <TextView
            android:id="@+id/tv_disconnect"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="end"
            android:layout_marginEnd="8dp"
            android:visibility="gone"
            android:padding="8dp"
            android:text="断开连接"
            android:textColor="@color/white" />
    </com.google.android.material.appbar.MaterialToolbar>

    <TextView
        android:id="@+id/tv_device_info"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:padding="16dp"
        android:text="设备信息"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/toolbar" />

</androidx.constraintlayout.widget.ConstraintLayout>

在XML中只增加了两个TextView,分别用于断连和显示设备状态,然后我们修改MainActivity中的代码,如下所示:

class MainActivity : BaseActivity(), BleCallback {

    private val binding by viewBinding(ActivityMainBinding::inflate)

    private lateinit var bleCore: BleCore

    @SuppressLint("MissingPermission")
    private val scanIntent =
        registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
            if (result.resultCode == Activity.RESULT_OK) {
                if (result.data == null) return@registerForActivityResult
                //获取选中的设备
                val device = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
                    result.data!!.getParcelableExtra("device", BluetoothDevice::class.java)
                } else {
                    result.data!!.getParcelableExtra("device") as BluetoothDevice?
                }
                //连接设备
                if (device != null) bleCore.connect(device)
            }
        }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        bleCore = (application as BleApp).getBleCore()
        bleCore.setBleCallback(this@MainActivity)
        //进入扫描页面
        binding.toolbar.setNavigationOnClickListener { scanIntent.launch(Intent(this,ScanActivity::class.java)) }
        //断开连接
        binding.tvDisconnect.setOnClickListener {
            binding.tvDisconnect.visibility = View.GONE
            bleCore.disconnect()
        }
    }

    override fun deviceInfo(info: String) {
        runOnUiThread {
            binding.tvDeviceInfo.text = info
        }
    }

    override fun onConnectionStateChange(state: Boolean) {
        runOnUiThread {
            if (state) binding.tvDisconnect.visibility = View.VISIBLE
        }
    }

    override fun onServicesDiscovered(services: List<BluetoothGattService>) {
        
    }
}

  这里我们首先是通过Activity Result API的StartActivityForResult()函数进行页面跳转,在返回的时候拿到device对象,这在前一篇已经写好了,拿到device对象之后调用BleCoreconnect()函数进行连接设备,在onCreate()函数中进行BleCore的赋值,然后设置Ble的回调,实现BleCallback接口,重写里面的函数,当连接成功之后会通过回调deviceInfo()得到设备状态,因为是子线程所以在ui线程中渲染UI。而onConnectionStateChange()函数,回调连接成功或者失败,如果成功则为ture,就显示tvDisconnect控件,此时连接成功,点击这个tvDisconnect就会断开连接,点击监听就在onCreate()中写好了,下面我们运行一下看看效果。

android ble蓝牙调用 ui线程,蓝牙,BLE连接设备,BLE发现服务

从这个效果图来看,我们连接成功之后有状态,点击断开连接也会有状态改变,那么连接就写好了。

四、发现服务

  连接写好了,下面可以写发现服务了,我们可以在连接成功的处理中进行发现服务,下面我们修改一下BleGattCallback中的onConnectionStateChange()函数中的代码,如下图所示:

android ble蓝牙调用 ui线程,蓝牙,BLE连接设备,BLE发现服务

通过gatt.discoverServices()进行发现服务的动作,在此之前通过deviceInfo设置当前的动作状态,发现服务执行会触发onServicesDiscovered()回调,在这个回调中我们可以回调到页面,修改代码如下所示:

        override fun onServicesDiscovered(gatt: BluetoothGatt, status: Int) {
            if (status == BluetoothGatt.GATT_SUCCESS) {
                deviceInfo("发现了 ${gatt.services.size} 个服务")
                gatt.services?.let { mBleCallback?.onServicesDiscovered(it) }
            }
        }

在回调中设置发现服务的个数,然后回调,因为服务是多个的,那么下面我们就需要使用一个列表是装载服务,首先我们修改一下activity_main.xml,在里面增加一个RecyclerView,代码如下所示:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout...>

    ...

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rv_service"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/white"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/tv_device_info" />

</androidx.constraintlayout.widget.ConstraintLayout>

五、服务适配器

  要显示服务列表数据,首先需要一个适配器,而适配器又需要一个item去渲染数据,下面我们在layout下创建一个item_service.xml,代码如下所示:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/item_service"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginBottom="2dp"
    android:background="@color/white"
    android:orientation="vertical">

    <TextView
        android:id="@+id/tv_service_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="8dp"
        android:text="服务"
        android:textColor="@color/black"
        android:textSize="16sp"
        android:textStyle="bold"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/tv_uuid_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="UUID:"
        app:layout_constraintStart_toStartOf="@+id/tv_service_name"
        app:layout_constraintTop_toBottomOf="@+id/tv_service_name" />

    <TextView
        android:id="@+id/tv_service_uuid"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="UUID"
        android:textColor="@color/black"
        app:layout_constraintBottom_toBottomOf="@+id/tv_uuid_title"
        app:layout_constraintStart_toEndOf="@+id/tv_uuid_title"
        app:layout_constraintTop_toTopOf="@+id/tv_uuid_title" />

    <TextView
        android:id="@+id/tv_service_info"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="8dp"
        android:text="PRIMARY SERVICE"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="@+id/tv_service_name"
        app:layout_constraintTop_toBottomOf="@+id/tv_uuid_title" />

</androidx.constraintlayout.widget.ConstraintLayout>

下面我们在ble包下新建一个BleUtils类,代码如下所示:

object BleUtils {

    private val generic = "-0000-1000-8000-00805F9B34FB"

    /**
     * 获取蓝牙服务名称
     * @param uuid UUID
     */
    fun getServiceName(uuid: UUID) =
        when ("0x${uuid.toString().substring(4, 8).uppercase(Locale.getDefault())}") {
            "0x1800" -> "Generic Access service"
            "0x1801" -> "Generic Attribute service"
            "0x1802" -> "Immediate Alert service"
            "0x1803" -> "Link Loss service"
            "0x1804" -> "Tx Power service"
            "0x1805" -> "Current Time service"
            "0x1806" -> "Reference Time Update service"
            "0x1807" -> "Next DST Change service"
            "0x1808" -> "Glucose service"
            "0x1809" -> "Health Thermometer service"
            "0x180A" -> "Device Information service"
            "0x180D" -> "Heart Rate service"
            "0x180E" -> "Phone Alert Status service"
            "0x180F" -> "Battery service"
            "0x1810" -> "Blood Pressure service"
            "0x1811" -> "Alert Notification service"
            "0x1812" -> "Human Interface Device service"
            "0x1813" -> "Scan Parameters service"
            "0x1814" -> "Running Speed and Cadence service"
            "0x1815" -> "Automation IO service"
            "0x1816" -> "Cycling Speed and Cadence service"
            "0x1818" -> "Cycling Power service"
            "0x1819" -> "Location and Navigation service"
            "0x181A" -> "Environmental Sensing service"
            "0x181B" -> "Body Composition service"
            "0x181C" -> "User Data service"
            "0x181D" -> "Weight Scale service"
            "0x181E" -> "Bond Management service"
            "0x181F" -> "Continuous Glucose Monitoring service"
            "0x1820" -> "Internet Protocol Support service"
            "0x1821" -> "Indoor Positioning service"
            "0x1822" -> "Pulse Oximeter service"
            "0x1823" -> "HTTP Proxy service"
            "0x1824" -> "Transport Discovery service"
            "0x1825" -> "Object Transfer service"
            "0x1826" -> "Fitness Machine service"
            "0x1827" -> "Mesh Provisioning service"
            "0x1828" -> "Mesh Proxy service"
            "0x1829" -> "Reconnection Configuration service"
            "0x183A" -> "Insulin Delivery service"
            "0x183B" -> "Binary Sensor service"
            "0x183C" -> "Emergency Configuration service"
            "0x183D" -> "Authorization Control service"
            "0x183E" -> "Physical Activity Monitor service"
            "0x183F" -> "Elapsed Time service"
            "0x1840" -> "Generic Health Sensor service"
            "0x1843" -> "Audio Input Control service"
            "0x1844" -> "Volume Control service"
            "0x1845" -> "Volume Offset Control service"
            "0x1846" -> "Coordinated Set Identification service"
            "0x1847" -> "Device Time service"
            "0x1848" -> "Media Control service"
            "0x1849" -> "Generic Media Control service"
            "0x184A" -> "Constant Tone Extension service"
            "0x184B" -> "Telephone Bearer service"
            "0x184C" -> "Generic Telephone Bearer service"
            "0x184D" -> "Microphone Control service"
            "0x184E" -> "Audio Stream Control service"
            "0x184F" -> "Broadcast Audio Scan service"
            "0x1850" -> " Published Audio Capabilities service"
            "0x1851" -> "Basic Audio Announcement service"
            "0x1852" -> "Broadcast Audio Announcement service"
            "0x1853" -> "Common Audio service"
            "0x1854" -> "Hearing Access service"
            "0x1855" -> "Telephony and Media Audio service"
            "0x1856" -> "Public Broadcast Announcement service"
            "0x1857" -> "Electronic Shelf Label service"
            else -> "Unknown Service"
        }
        
    fun getServiceUUID(uuid: UUID) =
        "0x${uuid.toString().substring(4, 8).uppercase(Locale.getDefault())}"
}

  这里需要说明一下蓝牙的UUID,蓝牙UUID(Universally Unique Identifier)是用于唯一标识蓝牙设备和服务的一种标识符。它是一个128位长的数字,在蓝牙通信中起到唯一标识的作用。蓝牙UUID按照标准分为两种类型:

  1. 16位UUID:这些UUID通常用于蓝牙标准定义的一些通用服务和特性。例如,设备名称服务的UUID是 00001800-0000-1000-8000-00805F9B34FB。

  2. 128位UUID:这些UUID通常用于自定义的服务和特性,以确保全球唯一性。可以自行生成一个128位的UUID作为自定义的服务或特性标识。例如,一个自定义的服务UUID可以是 0000XXXX-0000-1000-8000-00805F9B34FB,其中的 XXXX 部分可以是任意的16进制数字。

在蓝牙通信中,设备使用UUID来发布和查找服务以及识别特性。UUID是蓝牙设备之间进行通信时的重要标识,确保了设备和服务的唯一性。

那么getServiceName()中的键你就知道是什么意思了,0x1800就是16进制数字,而对应的值则是SIG定义的,可以参考这个文档:Assigned_Numbers.pdf。如果你的值找不到对应的,那说明它不是SIG规范的,你这个服务UUID就是自己公司自定义的。

下面我们写适配器,在adapter包下新建一个ServiceAdapter类,代码如下所示:

class ServiceAdapter(
    private val services: List<BluetoothGattService>
) : RecyclerView.Adapter<ServiceAdapter.ViewHolder>() {

    private var mOnItemClickListener: OnItemClickListener? = null

    fun setOnItemClickListener(mOnItemClickListener: OnItemClickListener?) {
        this.mOnItemClickListener = mOnItemClickListener
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val viewHolder = ViewHolder(ItemServiceBinding.inflate(LayoutInflater.from(parent.context), parent, false))
        viewHolder.binding.itemService.setOnClickListener { mOnItemClickListener?.onItemClick(it, viewHolder.adapterPosition) }
        return viewHolder
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.binding.tvServiceName.text = BleUtils.getServiceName(services[position].uuid)
        holder.binding.tvServiceUuid.text = BleUtils.getServiceUUID(services[position].uuid)
    }

    override fun getItemCount() = services.size

    class ViewHolder(itemView: ItemServiceBinding) : RecyclerView.ViewHolder(itemView.root) {
        var binding: ItemServiceBinding

        init {
            binding = itemView
        }
    }
}

这里的代码就是比较简单的,就是基本的写法,下面回到MainActivity中进行显示数据。

六、显示服务

首先声明变量:

    private var mServiceAdapter: ServiceAdapter? = null

    private val mServiceList: MutableList<BluetoothGattService> = mutableListOf()

然后实现OnItemClickListener 接口

class MainActivity : BaseActivity(), BleCallback, OnItemClickListener {

重写onItemClick()函数。

    override fun onItemClick(view: View?, position: Int) {
        showMsg(mServiceList[position].uuid.toString())
    }

修改onServicesDiscovered()函数,代码如下所示:

    override fun onServicesDiscovered(services: List<BluetoothGattService>) {
        runOnUiThread {
            mServiceList.clear()
            mServiceList.addAll(services)
            mServiceAdapter ?: run {
                mServiceAdapter = ServiceAdapter(mServiceList)
                binding.rvService.apply {
                    (itemAnimator as SimpleItemAnimator).supportsChangeAnimations = false
                    layoutManager = LinearLayoutManager(this@MainActivity)
                    adapter = mServiceAdapter
                }
                mServiceAdapter!!.setOnItemClickListener(this@MainActivity)
                mServiceAdapter
            }
            mServiceAdapter!!.notifyDataSetChanged()
        }
    }

这里的写法其实和扫描设备哪里如出一辙,下面我们运行一下看看,什么效果。
android ble蓝牙调用 ui线程,蓝牙,BLE连接设备,BLE发现服务

七、源码

如果对你有所帮助的话,不妨 StarFork,山高水长,后会有期~

源码地址:GoodBle文章来源地址https://www.toymoban.com/news/detail-792365.html

到了这里,关于Android Ble蓝牙App(二)连接与发现服务的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Android Ble蓝牙App(三)特性和属性

      在上一篇中我们完成了连接和发现服务两个动作,那么再发现服务之后要做什么呢?发现服务只是让你知道设备有什么服务,可以做什么事情。 Ble蓝牙App(一)扫描 Ble蓝牙App(二)连接与发现服务 Ble蓝牙App(三)特性和属性 Ble蓝牙App(四)UI优化和描述符 Ble蓝牙App(五

    2024年02月14日
    浏览(36)
  • Android Ble蓝牙App(四)UI优化和描述符

      上一篇中了解了特性和属性,同时显示设备蓝牙服务下的特性和属性,本文中就需要来使用这些特性和属性来完成一些功能。 Ble蓝牙App(一)扫描 Ble蓝牙App(二)连接与发现服务 Ble蓝牙App(三)特性和属性 Ble蓝牙App(四)UI优化和描述符 Ble蓝牙App(五)数据操作   

    2024年02月13日
    浏览(45)
  • Android Ble蓝牙App(六)请求MTU与显示设备信息

      在上一篇文章中已经了解了数据操作的方式,而数据交互的字节长度取决于我们手机与蓝牙设备的最大支持长度。 Ble蓝牙App(一)扫描 Ble蓝牙App(二)连接与发现服务 Ble蓝牙App(三)特性和属性 Ble蓝牙App(四)UI优化和描述符 Ble蓝牙App(五)数据操作 Ble蓝牙App(六)

    2024年02月04日
    浏览(44)
  • Android蓝牙BLE开发

    最近正在研究Android的蓝牙BLE开发学习,以下是自己做的个人总结 首先得说明什么是低功耗蓝牙BLE,BLE的全称为Bluetooth low energy(或称Blooth LE,BLE),从英文全称便可以知晓其是一种低功耗的蓝牙技术,是蓝牙技术联盟设计和销售的一种个人局域网技术,旨在用于医疗保健、运

    2023年04月09日
    浏览(42)
  • Android -BLE 蓝牙模块开发

    Android-Ble蓝牙开发Demo示例–扫描,连接,发送和接收数据,分包解包(附源码) - 简书 前言 万物互联的物联网时代的已经来临,ble蓝牙开发在其中扮演着举重若轻的角色。最近刚好闲一点,抽时间梳理下这块的知识点。 涉及ble蓝牙通讯的客户端(开启、扫描、连接、发送... https://

    2024年02月09日
    浏览(43)
  • Android低功耗蓝牙(BLE)开发(二)

    在上一篇文章Android低功耗蓝牙(BLE)开发(一)中我们了解了BLE的相关概念,这里我们来实际用代码演示安卓进行BLE连接和通讯的功能。本文代码基于Android5.0以上(API 21) 1.声明权限 在AndroidManifest.xml文件中添加BLE相关的权限声明。 2.判断设备是否支持BLE以及蓝牙是否打开 3.进

    2024年02月09日
    浏览(58)
  • 蓝牙 - 关于BLE的安全连接

    A Basic Introduction to BLE 4.x Security 引言 Bluetooth Low Energy (BLE)正在迅速成为当今最常用的无线标准之一。同样地,它也越来越多地被用于传输敏感信息的应用中。因此,希望将BLE集成到其产品中的设计者应该了解这项技术的安全特性和限制。本文试图对这些功能做一个基本的概

    2024年02月01日
    浏览(43)
  • windows+python+bleak+BLE低功耗蓝牙通讯连接

    1.为什么选bleak   参考这篇知乎:https://zhuanlan.zhihu.com/p/577687336   windows端使用python连接常规的BLE设备(蓝牙4.0),仅考虑bleak模块(排除pybluez、pybluez2、pygatt)。 2.本文主要参考   本文主要参考bleak的官方文档:https://github.com/hbldh/bleak 3.本文所用设备   应事先学习蓝

    2024年02月02日
    浏览(41)
  • BLE基础理论/Android BLE开发示例

    参考:https://blog.csdn.net/qq_36075612/article/details/127739150?spm=1001.2014.3001.5502 参考: https://blog.csdn.net/qq_36075612/article/details/122772966?spm=1001.2014.3001.5502 传统蓝牙是在之前的 1.0.1.2 , 2.0+EDR,2.1+EDR,3.0+EDR 等基础上发展和完善起来 的。 传统蓝牙可以用与数据量比较大的传输,如语音,音乐

    2024年02月15日
    浏览(47)
  • ESP32蓝牙实例-BLE服务器与客户端通信

    在本文中,我们将介绍如何使用低功耗蓝牙在两个 ESP32 开发板之间执行 BLE 服务器客户端通信。 换句话说,将介绍如何通过 BLE 在两个 ESP32 开发板之间交换数据。 服务器和客户端之间的通信将通过 BLE 进行,其中一个 ESP32 板充当 BLE 服务器并将传感器读数发送到 ESP32 客户端

    2024年02月09日
    浏览(51)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包