【蓝牙】如何新建一个BLE GATT SERVICE

nRF52840 搭建GATT Service传送门 

本文基于高通平台QCC5121


1.BLE GATT SERVICE 结构

GATT的服务(service)是为了实现设备的某些功能或特征,是一系列数据和行为的集合。如下图所示,一个服务通常由特征(characteristic)或其他服务的引用组成,每一个特征都包含一个值和关于这个值的信息。在这里实现一个服务,即指定该服务的相关参数,在工程中添加相关变量和函数以处理信息。

 

2. 实现环境

芯片:QCC5121

调试工具:TRB2000,

库:ADK6.3

 

3.添加服务思路

由于高通提供了gatt service的注册工具,方便我们使用,所以我们首先根据规则注册一个服务到database中;之后在appGattInit初始化的时候,调用本服务的初始化函数;最后根据设计的服务的各功能实现其对应的句柄,实现各功能,最后指向其库函数,完成相应的动作。

 

4. 具体实现

4.1 添加gatt_server_database

在工程编译之前,编译器首先会调用gattdbgen.exe来生成gatt database,这是为了方便用户无需手动添加service的相关特性到工程中,并自动分配service编号,方便管理。这里用户只需新建一个.dbi文件,并将该文件包含在av_headset_db.db文件,gattdbgen.exe会根据其内容其生成.h和.c文件,添加到工程里。

测试时,我们建立两个特征,一个read特征,包含了read和notify的属性,另一个write特征,包含write属性。由于服务和特征均需要UUID,为避免重复,这里从0xEEE0开始指定UUID,新建一个gatt_sean_server_uuids.h,写入以下内容:

#ifndef __SEAN_UUIDS_H__
#define __SEAN_UUIDS_H__

#define UUID_SEAN_SERVICE						0xEEE0
#define UUID_SEAN_READ							0xEEE1
#define UUID_SEAN_WRITE							0xEEE2

#endif /* __SEAN_UUIDS_H__ */

 

这里我们新建一个gatt_sean_server_db.dbi, 打开后写以下内容:

#ifndef __GATT_SEAN_SERVER_DB_DBI__
#define __GATT_SEAN_SERVER_DB_DBI__

#include "gatt_sean_server_uuids.h"

primary_service {
    uuid : UUID_SEAN_SERVICE,
    name : "SEAN_SERVICE",
    characteristic  {
        uuid        : UUID_SEAN_READ,
        name        : "SEAN_READ",
        flags       : [ FLAG_IRQ , FLAG_DYNLEN ],
        properties  : [ read , notify ],
        value       : 0x0,
        client_config {
            flags   : [ FLAG_IRQ , FLAG_DYNLEN ], 
            name    : "SEAN_NOTIFICATION"
        }
    },

    characteristic {
        uuid        : UUID_SEAN_WRITE,
        name        : "SEAN_WRITE",
        flags       : [ FLAG_IRQ , FLAG_DYNLEN ],
        properties  : [ write ],
        value       : 0x0
    }
},
#endif /* __GATT_SEAN_SERVER_DB_DBI__ */

这里flags用到了”FLAG_IRQ”和“FLAG_DYNLEN”,其含义如图 4‑1所示。

 保存后关闭,在av_headset_db.db中添加

#include "gatt_sean_server_db.dbi"

即可,之后工程重新编译,会发现在av_headset_db.h中多出了这一段,这些宏在注册gatt服务时会用到。

#define HANDLE_SEAN_SERVICE             (0x0019)
#define HANDLE_SEAN_SERVICE_END         (0x001e)
#define HANDLE_SEAN_READ                (0x001b)
#define HANDLE_SEAN_NOTIFICATION        (0x001c)
#define HANDLE_SEAN_WRITE               (0x001e)

注意这里primary_service使用到了JSON格式,其中的语法要严格遵循,否则会在漫长的编译过程后会迎来报错。

工程重新编译后,本应当自动生

### 使用蓝牙BLE GATT协议在Android应用中实现实时数据传输并进行图形绘制 #### 1. 准备工作 为了能够在Android设备上通过蓝牙低功耗(Bluetooth Low Energy, BLEGATT协议实现上位机绘图,首先需要确保已经安装了支持BLE的硬件和软件环境。nRF Connect作为一款功能强大、操作简便的蓝牙连接辅助工具,在蓝牙技术的不断发展和普及中扮演着越来越重要的角色[^1]。 #### 2. 建立BLE连接 建立BLE连接的过程主要包括扫描周边可用的BLE设备、发起连接请求以及处理服务发现流程。以下是简化版的代码片段用于初始化BLE管理器: ```java public class BluetoothLeService extends Service { private final static String TAG = BluetoothLeService.class.getSimpleName(); public void initialize() { // 初始化BluetoothManager 和 BluetoothAdapter. final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); mBluetoothAdapter = bluetoothManager.getAdapter(); // 检查设备是否支持BLE. if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) { Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show(); stopSelf(); } // 设备不支持Bluetooth,则无法继续执行. if (mBluetoothAdapter == null) { Log.e(TAG, "Unable to obtain a BluetoothAdapter."); stopSelf(); return; } } } ``` #### 3. 数据接收与解析 当成功建立了与目标设备之间的通信链路之后,就可以利用GATT特性来读取来自外设的数据流。这些接收到的信息通常会被编码成字节数组的形式传递给应用程序层,因此有必要定义一套清晰的消息格式以便于后续解码过程中的准确性。 #### 4. 实现图表绘制逻辑 对于实时数据显示的需求来说,推荐采用高效的Canvas API来进行动态图像渲染。每当有的测量值到达时就触发一次重绘事件,并将最的一系列坐标点连结起来形成连续曲线。下面给出了一段简单的例子展示如何基于View类创建自定义视图组件完成这一任务: ```java import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import androidx.annotation.Nullable; import android.util.AttributeSet; public class LineChartView extends View { private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); List<Float> dataPoints; @Override protected void onDraw(Canvas canvas){ super.onDraw(canvas); int width = getWidth(), height=getHeight(); float margin=50f; RectF bounds=new RectF(margin,margin,width-margin,height-margin); Path path=new Path(); if(dataPoints!=null && !dataPoints.isEmpty()){ Iterator iterator=dataPoints.iterator(); Float firstValue=(Float)iterator.next(); path.moveTo(bounds.left,bounds.bottom-firstValue*(bounds.height()/MAX_VALUE)); while(iterator.hasNext()){ Float value=(Float)iterator.next(); path.lineTo( ((float)dataPoints.indexOf(value)/dataPoints.size())*bounds.width()+bounds.left, bounds.bottom-value*(bounds.height()/MAX_VALUE) ); } }else{ // Handle empty dataset case here... } paint.setColor(Color.BLUE); paint.setStrokeWidth(8f); canvas.drawPath(path,paint); } public void updateData(List<Float> newData){ this.dataPoints=new ArrayList<>(newData); invalidate(); // Request redraw with updated values. } } ``` 此部分实现了基本线条图的功能,可以根据实际应用场景调整样式属性如颜色、线宽等参数以满足特定需求。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值