查看: 1718|回复: 2

[原创] 【经验分享】自制ble服务

[复制链接]

该用户从未签到

656

主题

6312

帖子

0

超级版主

Rank: 8Rank: 8

积分
20015
最后登录
2024-4-25
发表于 2020-9-2 10:41:12 | 显示全部楼层 |阅读模式
本帖最后由 小恩GG 于 2020-9-2 13:42 编辑

找一个例程,比如health_t例程
设备:KW36
手机应用:nrf connect

1 在gatt_uuid128.h 自定义UUID,使用宏定义UUID128(服务名/特征名,128位uuid)
UUID128(uuid_service_adcTst,0x01,0x03,0x07,0x09,0x0b,0x0d,0x0f,0x02,0x03,0x01,0x04,0x43,0x23,0x32,0x33,0x78)

UUID128(uuid_characteristic_adcTst,0x01,0x03,0x07,0x0a,0x0b,0x0d,0x0f,0x02,0x04,0x01,0x04,0x93,0x23,0x32,0x33,0x79)
名字+16字节uuid


2 gatt_db.h定义服务

PRIMARY_SERVICE_UUID128(service_device_adc,uuid_service_adcTst)
CHARACTERISTIC_UUID128(char_adc_value,uuid_characteristic_adcTst,(gGattCharPropRead_c| gGattCharPropNotify_c | gGattCharPropWrite_c))
       VALUE_UUID128(value_adc_value, uuid_characteristic_adcTst,gPermissionFlagReadable_c | gPermissionFlagWritable_c ,1, 0x00)
       CCCD(cccd_adc)



3 在profiles下创建一个新文件夹,放自定义服务,在文件夹下放两个文件,xxx_interface.h和xxx_services.c


4 在interface.h自定义数据结构,类似
typedef struct psConfig_tag
{
    uint16_t    serviceHandle;                /*!<Service handle */
    uint8_t    potentiometerValue;           /*!<Input report field */
} psConfig_t;
声明两个开启服务的函数,类似
bleResult_t Ps_Start(psConfig_t *pServiceConfig);
bleResult_t
Ps_Stop(psConfig_t *pServiceConfig);
两个注册客户端注册服务,类似
bleResult_t Ps_Subscribe(deviceId_t clientDeviceId);
bleResult_t
Ps_Unsubscribe();
用于读写更新特征的函数,类似
bleResult_t Ps_RecordPotentiometerMeasurement (uint16_t serviceHandle, uint8_t newPotentiometerValue);

5 service.c要实现
一个静态变量用于存储ID
static deviceId_t mPs_SubscribedClientId;
实现以上函数
bleResult_t Ps_Start (psConfig_t *pServiceConfig)
{   
   
/* Clear subscibed clien ID (if any) */
    mPs_SubscribedClientId
= gInvalidDeviceId_c;
   
   
/* Set the initial value defined in pServiceConfig to the characteristic values */
   
return Ps_RecordPotentiometerMeasurement (pServiceConfig->serviceHandle,
                                             pServiceConfig
->potentiometerValue);
}

bleResult_t Ps_Stop
(psConfig_t *pServiceConfig)
{
  
/* Unsubscribe current client */
   
return Ps_Unsubscribe();
}

bleResult_t
Ps_Subscribe(deviceId_t deviceId)
{
   
/* Subscribe a new client to this service */
    mPs_SubscribedClientId
= deviceId;

   
return gBleSuccess_c;
}

bleResult_t
Ps_Unsubscribe()
{
   
/* Clear current subscribed client ID */
    mPs_SubscribedClientId
= gInvalidDeviceId_c;
   
return gBleSuccess_c;
}
这函数的 特征uuid变量是定义在uuid128里的,但是我实验时候发现,直接填进函数里会报未定义错误,后来使用了extern解决了问题
bleResult_t Ps_RecordPotentiometerMeasurement (uint16_t serviceHandle, uint8_t newPotentiometerValue)
{
    uint16_t  handle
;
    bleResult_t result
;

   
/* Get handle of Potentiometer characteristic */
    result
= GattDb_FindCharValueHandleInService(serviceHandle,
        gBleUuidType128_c
, (bleUuid_t*)&potentiometerCharacteristicUuid128, &handle);

   
if (result != gBleSuccess_c)
        
return result;

   
/* Update characteristic value */
    result
= GattDb_WriteAttribute(handle, sizeof(uint8_t), (uint8_t*)&newPotentiometerValue);

   
if (result != gBleSuccess_c)
        
return result;

   
Ps_SendPotentiometerMeasurementNotification(handle);

   
return gBleSuccess_c;
}
实现发送提醒的函数
static void Ps_SendPotentiometerMeasurementNotification
(
  uint16_t handle
)
{
    uint16_t  hCccd
;
    bool_t isNotificationActive
;

   
/* Get handle of CCCD */
   
if (GattDb_FindCccdHandleForCharValueHandle(handle, &hCccd) != gBleSuccess_c)
        
return;

   
if (gBleSuccess_c == Gap_CheckNotificationStatus
        
(mPs_SubscribedClientId, hCccd, &isNotificationActive) &&
        TRUE
== isNotificationActive)
   
{
        
GattServer_SendNotification(mPs_SubscribedClientId, handle);
   
}
}


6 在文件里,放置服务数据的地方,定义自定义的数据,类似
       StaticpsConfig_t psServiceConfig = {service_potentiometer,0};
这个service_potentiometer就是UUID定义的主服务


7 在BleApp_Config() 里开启服务
Ps_Start(&psServiceConfig);


8 在BleApp_ConnectionCallback,在gConnEvtConnected_c这个状态下,调用
Ps_Subscribe(peerDeviceId); 注册ID,开启对应服务定时器,实现定时器回调函数


9 如果需要处理,Notifications和写请求
在BleApp_GattServerCallback里的ccd写情况下,开启定时器,定时发送数据

写请求则要先用GattServer_RegisterHandlesForWriteNotifications来注册函数uint16_t notifiableHandleArray[] = {value_led_control, value_buzzer, value_accelerometer_scale, value_controller_command, value_controller_configuration};
    uint8_t notifiableHandleCount
= sizeof(notifiableHandleArray)/2;
    bleResult_t initializationResult
= GattServer_RegisterHandlesForWriteNotifications(notifiableHandleCount, (uint16_t*)&notifiableHandleArray[0]);
在BleApp_GattServerCallback里的属性写情况下,
同时要用GattServer_RegisterHandlesForWriteNotifications来注册句柄,cpHandles放了VALUE值的句柄,需要在里面添加VALUE对应的第一个名字

实现sendAttWrite…
static void BleApp_SendAttWriteResponse (deviceId_t* pDeviceId, gattServerEvent_t* pGattServerEvent, bleResult_t* pResult){
  attErrorCode_t attErrorCode
;
  
  
// Determine response to send (OK or Error)
  
if(*pResult == gBleSuccess_c)
    attErrorCode
= gAttErrCodeNoError_c;
  
else{
    attErrorCode
= (attErrorCode_t)(*pResult & 0x00FF);
  
}
  
// Send response to client  
  
GattServer_SendAttributeWrittenStatus(*pDeviceId, pGattServerEvent->eventData.attributeWrittenEvent.handle, attErrorCode);
}
按下nrf connect里的notify按钮则会触发cccd写事件 gEvtCharacteristicCccdWritten_c
启用配对验证在app_preinclude.h定义为1
/*! Enable/disable use of bondingcapability */
#define gAppUseBonding_d   1

/*! Enable/disable use of pairing procedure*/
#define gAppUsePairing_d   1

密钥定义
#define gPasskeyValue_c                999999
参考链接custom profile
SELF_Profile.pdf (226.83 KB, 下载次数: 9)
回复

使用道具 举报

  • TA的每日心情
    难过
    2023-9-6 15:15
  • 签到天数: 211 天

    [LV.7]常住居民III

    34

    主题

    805

    帖子

    0

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    2036
    最后登录
    2024-3-21
    发表于 2020-9-2 12:21:05 | 显示全部楼层
    学习了!
    该会员没有填写今日想说内容.
    回复

    使用道具 举报

  • TA的每日心情
    奋斗
    2023-2-24 18:42
  • 签到天数: 206 天

    [LV.7]常住居民III

    18

    主题

    311

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    2743
    最后登录
    2024-4-9
    发表于 2020-10-29 11:16:22 | 显示全部楼层
    双击666
    哎...今天够累的,签到来了~
    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2024-4-25 19:01 , Processed in 0.151426 second(s), 21 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

    快速回复 返回顶部 返回列表