zoukankan      html  css  js  c++  java
  • 四、BLE(中)

    1.1       GATT Manager

    GATT MGR模块管理所有的GATT服务,同时也是连接GATT模块与GATT ServiceS模块的桥梁。

    1.1.1    主要功能模块

    先来看一张该模块的API关系图,sink_gatt_manager.c里面定义的接口主要供ApplicationLayer调用和回调,如用户(BLE Server)调用sinkGattManagerStartAdvertising()开始进行广播,用户(BLE Client)调用sinkGattManagerStartConnection()开始进行BLE连接。该该部分同时负责接收和处理来自ApplicationLayer的消息——GATT_MANAGER_DISCONNECT_IND,GATT_MANAGER_REGISTER_WITH_GATT_CFM等GATT_MANAGER_XXX系列消息。这些消息主要用来处理注册连接确认,断开连接请求等事件。

     

           Gatt_nanager_handler.c主要定义和实现了内部回调函数gattManagerMessageHandler(),该接口主要接收来自GATT模块的GATT_XXX系列消息,以及GATT MGR内部的消息GATT_MANAGER_INTERNAL_MSG_XXX。处理这些消息的函数接口主要分布在gatt_manager_server.c和gatt_manager_client.c两个函数内部。

           根据BLE工作的角色不同,BLE分别定义了两套接口,分别完成客户和服务的角色的任务。

             作为BLE客户主要完成的任务有:

    1.连接到服务器。这里包括主导发起连接至服务器,以及接收到服务器连接请求的确认。即:GattManagerConnectToRemoteServer()用来主动发起连接请求,在接收到GATT_CONNECT_CFM消息后,调用gattManagerClientRemoteServerConnected ()接口用于确认连接,完成连接的三次握手过程。

    2. GATT支持notification和indication操作,因此客户端需要有着两种请求操作对应的接口。gattManagerClientRemoteServerNotification()和gattManagerClientRemoteServerIndication()就是为了实现这两种操作巍峨设计的。

    3. 获取服务器的服务。根据GATT标准,获取服务的服务主要有:获取服务器主要GATT服务,获取某个GATT服务的所有特征值定义,获取某个GATT服务的特征值描述符,读/写某个特征值等。

             作为BLE服务器主要完成的任务有:

    1.广播,以及处理客户端的连接请求。gattManagerServerAdvertising()开启广播,GattManagerWaitForRemoteClient()等待远程客户发起连接,gattManagerServerConnectInd()处理连接请求。gattManagerServerRemoteClientConnected()处理连接请求确认(三次握手最后一次)消息。

    2.注册GATT service。GattManagerRegisterServer()向GATT MGR模块注册一个GATT service。

    3.处理来自客户端的GATT操作,如access,indication,notification等。其中indication,notification操作都是由服务器主动对客户端发起的操作,因此客户端和服务器端处理的消息刚好是互为匹配的,即服务器处理的消息有(GATT_ACCESS_IND, GATT_NOTIFICATION_CFM, GATT_INDICATION_CFM),客户端对应的处理消息有(ATT_ACCESS_RSP, GATT_NOTIFICATION_IND, GATT_INDICATION_IND)。

    1.1.2    GATT数据库

    作为GATT的服务器,通常需要存储比较多的数据来支撑多个不同的GATT服务,因此在GATT服务器端,建立一个数据库是必要的。在CSR的BlueCore和CSRμEnergy软件开发工具包(SDK)中使用了一种特殊的数据库目标语言。该数据库通过GATT数据库生成器(CSR提供的gattdbgen.exe)自动生成。这就允许应用程序开发者以一种简单易读,便于维护的方式来创建一个数据库,避免采用诸如SDP这种用复杂的二进制形式表示方式。

    数据库的生成

    GATT数据库生成器输入一个用jeason语言描述的GATT服务文件foobar.db,输出一个foobar.c和foobar.h文件,这两个文件可以作为ADK工程的一部分进行编译和链接。可见数据库的生产是在整个工程编译前,准确的说是在预编译阶段就已经完成了。显然这样生产的数据是一个准常量的数据库,不能往里面新增记录,即不能动态的添加GATT服务,所有的服务必须在编译前就已经确定好。

    例如,在ADK的sink例程中,sink_gatt_db.db作为数据库生成器的输入文件,输出sink_gatt_db.c和sink_gatt_db.h。

    其中xxx_db.c文件有const uint16 gattDatabase[] = {}存储数据库记录。并提供两个接口工外部操作数据库,这两个接口分别为:

    uint16 *GattGetDatabase(uint16 *len);  /*获取数据库存储区首地址*/

    uint16 GattGetDatabaseSize(void);      /*获取数据库大小*/

    在xxx_db.h文件中,除了GattGetDatabase()和GattGetDatabaseSize()接口的声明外,还有数据库中所有ATT记录的句柄(UUID)的宏定义,通常以HANDLE_GAIA_XXX的形式定义。通过该宏,可以快速索引某条ATT记录。

    BLE在初始化GATT Manager模块时,对GATT database进行了初始化:

    initialiseGattWithServers()->

    GattManagerRegisterConstDB(&gattDatabase[0], GattGetDatabaseSize());

    例如某个gaia_db.db内容为:

    primary_service {

        uuid : 0x01

        name : "GAIA_SERVICE",

        characteristic {

            uuid        : 0x02,

            name        : "GAIA_COMMAND_ENDPOINT",

            flags       : [ FLAG_IRQ, FLAG_DYNLEN, FLAG_ENCR_W ],

            properties  : [ write ],

            value       : 0x0

        }

    },

    则其生成的gaia_db.c文件如下:

    /* Static GATT database */

    const uint16 gattDatabase[] = {

        /* 0001: Primary Service 0001 */

        0x0002, 0x0100,

        /* 0002: Characteristic Declaration 0002 */

        0x3005, 0x0803, 0x0002, 0x0000,

        /* 0003: . */

        0xdd01, 0x0000,

    };

    uint16 *GattGetDatabase(uint16 *len)

    {

        uint16 *rc = PanicUnlessMalloc(sizeof(gattDatabase));

        *len = sizeof(gattDatabase);

        memmove(rc, gattDatabase, sizeof(gattDatabase));

        return rc;

    }

    uint16 GattGetDatabaseSize(void)

    {

        return sizeof(gattDatabase);

    }

    其生成的gaia_db.h文件如下:

    #define HANDLE_GAIA_SERVICE             (0x0001)

    #define HANDLE_GAIA_SERVICE_END         (0xffff)

    #define HANDLE_GAIA_COMMAND_ENDPOINT    (0x0003)

    uint16 *GattGetDatabase(uint16 *len);

    uint16 GattGetDatabaseSize(void);

    数据库维护

             GATT数据库的数据单元是ATT记录,通过某条ATT记录的句柄(handler)可以快速和唯一地访问该条记录,例如,如果希望访问电池服务的电量特征值,该条特征值定义封装在一条句柄为0x0003的ATT记录中,通过句柄0x0003找到该条ATT记录,ATT.value即对应着电池电量值。

  • 相关阅读:
    什么是知行动手实验室?
    SpringBoot Admin2.0 集成 Java 诊断神器 Arthas 实践
    一文读懂容器存储接口 CSI
    AI 事件驱动场景 Serverless 实践
    一不小心,它成为了 GitHub Alibaba Group 下 Star 最多的开源项目
    5G 和云原生时代的技术下半场,视频化是最大最新的确定性
    基于 RocketMQ Prometheus Exporter 打造定制化 DevOps 平台
    Knative 基于流量的灰度发布和自动弹性实践
    阿里的 RocketMQ 如何让双十一峰值之下 0 故障?
    阿里巴巴开源容器镜像加速技术
  • 原文地址:https://www.cnblogs.com/fbli/p/5930363.html
Copyright © 2011-2022 走看看