蓝牙BLE芯片PHY6222之Peripheral从机自定义service服务

蓝牙BLE芯片PHY6222之Peripheral从机自定义service

  • 环境
  • 蓝牙通信相关知识点
  • 直接看代码

环境

SDK及路径:SDK\PHY62XX_SDK_3.1.1_0922\example\ble_peripheral\simpleBlePeripheral
硬件:PHY6222开发板
APP:nRF connect

蓝牙通信相关知识点

  1. BLE采用了client/server (C/S)架构来进行数据交互,一般而言BLE设备提供服务,因此设备是server,手机使用设备提供的服务,因此手机是client。
  2. service可以是一个蓝牙联盟定义的标准服务,我们可以称其为profile,比如HID/心率计/体温计/血糖仪等,都是标准蓝牙服务,因此都有相应的profile规格书;同时也有可以自定义的service,下面我写的就是自定义的BLE service。
  3. server是通过characteristic来表示数据的,一个characteristic包含三种属性:characteristic声明,characteristic的值以及characteristic的描述符(可以没有,也可以有多个描述符),Characteristic value就是我们要操作的数据。
  4. server可以直接把自己的characteristic的值告诉client,我们称其为notify或者indicate,跟read操作相比,只有需要传输数据的时候或者说只有当数据有效时,server才开始notify或者indicate数据到client,因此这种操作方式可以大大节省server的功耗。有时候client不想监听characteristic notify或者indicate过来的数据,那么就可以使用CCCD来关闭characteristic的notify或者indicate功能;如果client又需要监听characteristic的notify或者indicate,那么它可以重新使能CCCD来打开相关操作。也就是说characteristic具有notify或者indicate操作功能时,那么必须为其添加相应CCCD,以方便client来使能或者禁止notify或者indicate功能。

直接看代码

自定义的UUID

CONST uint8 my_serviceUUIID[ATT_UUID_SIZE] =
{0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88};
CONST uint8 my_Characteristic_UUID[ATT_UUID_SIZE] =
{0x34, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88};
CONST uint8 my_2_Characteristic_UUID[ATT_UUID_SIZE] =
{0x56, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88};

初始化属性表

static gattAttribute_t my_Attrb1[] =
{
    //my primary service
    {
        {ATT_BT_UUID_SIZE, primaryServiceUUID},/* type */  //主服务
        GATT_PERMIT_READ,					   /* permissions */  //权限
        0,									   /* handle */   //头
        (uint8*)& my_service				   /* pValue */  //值
    },
    //我的理解是GATT_PERMIT_READ 这个描述的是 数组 这个元素 具有的 权限 是 可读 或者 可写,   
	//my_Characteristic_permissions这个变量 描述 的 是  该数组元素 代表的特征值 具有  可写 的属性
    {
        {ATT_BT_UUID_SIZE, characterUUID},//type,属性类型 是特征值类型
        GATT_PERMIT_READ,
        0,
        &my_Characteristic_permissions//read ,  write ,notify,  indicate权限
    },
    {
        {ATT_UUID_SIZE, my_Characteristic_UUID},//自定义特征类型
        GATT_PERMIT_WRITE,
        0,
        &my_Characteristic_UUID_value//自定义特征UUID的值
    },
    {
        { ATT_BT_UUID_SIZE, clientCharCfgUUID },//类型是描述UUID
        GATT_PERMIT_READ | GATT_PERMIT_WRITE,
        0,
        (uint8*)my_notify_CCCD_value//描述的值
    },
    //----------------------------------------------------
    {

        {ATT_BT_UUID_SIZE, characterUUID},
        GATT_PERMIT_READ,
        0,
        &my_2_Characteristic_permissions
    },
    {
        {ATT_UUID_SIZE, my_2_Characteristic_UUID},
        GATT_PERMIT_WRITE,
        0,
        &my_2_Characteristic_UUID_value
    },
    {
        {ATT_BT_UUID_SIZE, clientCharCfgUUID},
        GATT_PERMIT_READ | GATT_PERMIT_WRITE,
        0,
        (uint8*)my_indcate_CCCD_value
    },
};

profile有改变时触发的回调函数

CONST gattServiceCBs_t my_ProfileCBs =
{
    my_ReadAttrCB,
    my_WriteAttrCB,
    NULL
};
static bStatus_t my_WriteAttrCB(uint16 connHandle, gattAttribute_t* pAttr,
                                uint8* pValue, uint16 len, uint16 offset)
{
    bStatus_t status = SUCCESS;

    //uint8 notifyApp = 0xFF;
    // If attribute permissions require authorization to write, return error
    if (gattPermitAuthorWrite(pAttr->permissions))
    {
        // Insufficient authorization
        return (ATT_ERR_INSUFFICIENT_AUTHOR);
    }

    if (pAttr->type.len == ATT_BT_UUID_SIZE)
    {
        // 16-bit UUID
        uint16 uuid = BUILD_UINT16(pAttr->type.uuid[0], pAttr->type.uuid[1]);

        if (uuid == GATT_CLIENT_CHAR_CFG_UUID)
        {
            if(pAttr->handle == my_Attrb1[3].handle) {
                status = GATTServApp_ProcessCCCWriteReq(connHandle, pAttr, pValue, len,
                                                        offset, GATT_CLIENT_CFG_NOTIFY);

                if (status == SUCCESS)
                {
                    uint16 charCfg = BUILD_UINT16(pValue[0], pValue[1]);
                    LOG("CCCD set: [%d]\n", charCfg);
                    s_my_app.notify_en = (charCfg == 1);
									osal_start_timerEx( simpleBLEPeripheral_TaskID, SBP_TEST_TX_NOTIFY, 500 );
                }
            } else if(pAttr->handle == my_Attrb1[6].handle)

            {
                status = GATTServApp_ProcessCCCWriteReq(connHandle, pAttr, pValue, len,
                                                        offset, GATT_CLIENT_CFG_INDICATE);
                if (status == SUCCESS)
                {
                    uint16 charCfg = BUILD_UINT16(pValue[0], pValue[1]);
                    LOG("write indicata: [%d]\n", charCfg);
									
                }

            }
        }
        else
        {
            LOG("WR:%d\n", pAttr->handle);

            // 128-bit UUID Command
            if (pAttr->handle == my_Attrb1[MY_COMMAND_HANDLE].handle)
            {
//            process_cmd(pValue, len);
            }
        }

        return (status);
    }
}

static uint8 my_ReadAttrCB(uint16 connHandle, gattAttribute_t* pAttr,uint8 * pValue, uint16 * pLen, uint16 offset, uint8 maxLen)
{
    bStatus_t status = SUCCESS;
    LOG("ReadAttrCB\n");

    // If attribute permissions require authorization to read, return error
    if (gattPermitAuthorRead(pAttr->permissions))
    {
        // Insufficient authorization
        return (ATT_ERR_INSUFFICIENT_AUTHOR);
    }

    return (status);
}

notify

static bStatus_t send_Notify(attHandleValueNoti_t* pNoti)
{
    uint16 connHandle;
    uint16 value;
    GAPRole_GetParameter(GAPROLE_CONNHANDLE, &connHandle);
    value = GATTServApp_ReadCharCfg(connHandle, my_notify_CCCD_value);

    if (connHandle == INVALID_CONNHANDLE)
        return bleIncorrectMode;

    // If notifications enabled
    if (value & GATT_CLIENT_CFG_NOTIFY)
    {
        // Set the handle
        pNoti->handle = my_Attrb1[MY_RSP_HANDLE].handle;
        // Send the Indication
        return GATT_Notification(connHandle, pNoti, FALSE);
    }

    return bleIncorrectMode;
}

indicate

static bStatus_t send_indicate(attHandleValueInd_t* indi)
{
    uint16 connHandle;
    uint16 value;
    GAPRole_GetParameter(GAPROLE_CONNHANDLE, &connHandle);
    value = GATTServApp_ReadCharCfg(connHandle, my_indcate_CCCD_value);

    if (connHandle == INVALID_CONNHANDLE)
        return bleIncorrectMode;

    // If notifications enabled
    if (value & GATT_CLIENT_CFG_INDICATE)
    {
        // Set the handle
        indi->handle = my_Attrb1[5].handle;
        // Send the Indication
        return GATT_Indication(connHandle, indi, FALSE, simpleBLEPeripheral_TaskID);
    }

    return bleIncorrectMode;
}

注册profile回调

bStatus_t my_Profile_RegisterAppCBs( my_ProfileCBs_t* appCallbacks )
{
    if ( appCallbacks )
    {
        my_Profile_AppCBs = appCallbacks;
        return ( SUCCESS );
    }
    else
    {
        return ( bleAlreadyInRequestedMode );
    }
}

注册服务(关键点)

bStatus_t my_app_addservice(uint32 services)
{
    uint8 status = SUCCESS;
    VOID linkDB_Register(my_Profile_HandleConnStatusCB);
    GATTServApp_InitCharCfg(INVALID_CONNHANDLE, my_notify_CCCD_value);
    status = GATTServApp_RegisterService(my_Attrb1, GATT_NUM_ATTRS(my_Attrb1), &my_ProfileCBs);
    if (status != SUCCESS)
        LOG("Add OTA service failed!\n");

    return (status);
}

在初始化的时候添加服务
蓝牙BLE芯片PHY6222之Peripheral从机自定义service服务_第1张图片
CCCD使能后,一秒notify一次数据到APP端
蓝牙BLE芯片PHY6222之Peripheral从机自定义service服务_第2张图片
蓝牙BLE芯片PHY6222之Peripheral从机自定义service服务_第3张图片

你可能感兴趣的:(PHY6222,芯片,蓝牙,物联网,iot,stm32)