在目标设备的蓝牙模块启动时,作为GATT Server,要初始化Battery Service,并注册call back函数来处理Battery service相关的事件,callback函数名为BAS_Event_Callback。
然后在BLE GATT server设备向外发送广播数据时,在配置Service字段时,可以加入Battery Service的UUID值。按照大端存放,广播数据中的第一个字节是0x18,第二个是0x0F。
在Assigned Numbers | Bluetooth® Technology Website中,3.4 GATT Services里,定义了BLE使用的各种服务的16bit UUID。其中Battery service的值是0x180F。
对于Battery Service, 是一个Service和一个Characteristic组成,Characteristic包含4个Attribute。
GATT Serve设备的电量信息可以通过Notify方式传递给GATT client的设备。需要GATT Server端的Battery level Characteristic的Client Configuration的属性值是支持NOTIFY的。
在事件处理的BAS event call back函数中,有三个事件:
typedef enum _tagBAS_Event_Type_t
{
etBAS_Server_Read_Client_Configuration_Request, /*!< Dispatched when a BAS Client requests read client configuration to a registered BAS Server. */
etBAS_Server_Client_Configuration_Update, /*!< Dispatched when a BAS Client requests to update client configuration to a registered BAS Server. */
etBAS_Server_Read_Battery_Level_Request /*!< Dispatched when a BAS Client requests read battery level to a registered BAS Server. */
} BAS_Event_Type_t;
第一个事件,是GATT Client请求读取BAS GATT Server上已注册BAS服务的Battery Level Characteristic的Client Configuration的值。
第二个事件,是GATT Client请求更新BAS GATT Server上已注册BAS服务的Battery Level Characteristic的Client Configuration的值。
第三个事件,是GATT Client请求读取BAS GATT Server上已注册BAS服务的Battery Level Characteristic的值。
Client Configuration是GATT Server上的Characteristic里的一个属性(attribute),用来描述GATT Client的设置的。
这个属性的值以变量的数据形式存储在GATT Server上,一般由GATT Client发送请求来进行读取和写入,这个值用来表示此Characteristic值是否允许GATT server发起Notify或Indicate操作。比如将Battery level的值Notify给GATT Client。
默认值为0,GATT Server则不能使用Notify功能。
/* GATT Client Configuration Characteristic Definitions. */
#define GATT_CLIENT_CONFIGURATION_CHARACTERISTIC_NOTIFY_ENABLE 0x0001
#define GATT_CLIENT_CONFIGURATION_CHARACTERISTIC_INDICATE_ENABLE 0x0002
所以GATT Server收到的前两个事件,就是GATT Client的关于Client Configuration的操作请求,一个是读取,一个是更新。
另外一个事件是GATT Client来读取Battery level的值。
这三个事件在BAS_Event_Callback里进行处理。收到etBAS_Server_Read_Client_Configuration_Request,会调用GATT_Read_Response,将值发送出去。
收到etBAS_Server_Client_Configuration_Update,将收到的值更新到本地。
收到etBAS_Server_Read_Battery_Level_Request,会将本地的Battery Level的值通过调用GATT_Read_Response,发送出去。
参考的蓝牙协议栈代码,可以访问TI网站:
TIBLUETOOTHSTACK-SDK Software development kit (SDK) | TI.com
下载TI的Bluetopia Protocol Stack。需要注册TI用户。
比如选择:MSP432 (CC256XMS432BTBLESW),CC256XMS432BTBLESW Driver or library | TI.com
下载后安装,在安装路径找到到蓝牙协议栈内容。找到里面的BAS.c和HOGPDemo.c,就有使用Battery Service的代码。
===== 分割线 =====
具体实现细节:
Array of GATT_Service_Attribute_Entry_t:
BTPSCONST GATT_Service_Attribute_Entry_t Battery_Service[] =
{
{GATT_ATTRIBUTE_FLAGS_READABLE, aetPrimaryService16, (Byte_t *)&BAS_Service_UUID},
{GATT_ATTRIBUTE_FLAGS_READABLE, aetCharacteristicDeclaration16, (Byte_t *)&BAS_Battery_Level_Declaration},
{GATT_ATTRIBUTE_FLAGS_READABLE, aetCharacteristicValue16, (Byte_t *)&BAS_Battery_Level_Value},
{GATT_ATTRIBUTE_FLAGS_READABLE_WRITABLE, aetCharacteristicDescriptor16, (Byte_t *)&Client_Characteristic_Configuration},
};
这个表有四个属性,第一个是Service的UUID值。Byte0 0x0F,Byte1 0x18,小端排列。
第二个是声明这个Characteristic,Byte0 0x19,Byte1 0x2A,小端排列。这个在Assigned Numbers文档里,3.8 Characteristics -> 3.8.1 Characteristics by Name,有一行定义。
Characteristic Name是Battery Level,UUID是0x2A19。
第三个是这个Characteristic的值,也是前面Notify Battery Level时,使用offset 2时就是发送的这个属性的通知。
第四个是,Client Configuration。这个在Assigned Numbers文档里,3.7 Descriptors, UUID是0x2902,表示Client Characteristic Configuration。
1,Notify Battery Level
调用函数:
int GATT_Handle_Value_Notification(unsigned int BluetoothStackID, unsigned int ServiceID, unsigned int ConnectionID, Word_t AttributeOffset, Word_t AttributeValueLength, Byte_t *AttributeValue);
传入参数:
BluetoothStackID // Stack ID
ServiceID // Battery Service ID
ConnectionID // GATT Connection ID
AttributeOffset = BAS_BATTERY_LEVEL_ATTRIBUTE_OFFSET = 2
AttributeValueLength = 1
*AttributeValue = Battery Level
返回值:
ret_val = NON_ALIGNED_BYTE_SIZE = 1
2,Initialize Battery Service
调用函数:
int GATT_Register_Service(unsigned int BluetoothStackID, Byte_t ServiceFlags, unsigned int NumberOfServiceAttributeEntries, GATT_Service_Attribute_Entry_t *ServiceTable, GATT_Attribute_Handle_Group_t *ServiceHandleGroupResult, GATT_Server_Event_Callback_t ServerEventCallback, unsigned long CallbackParameter);
传入参数:
BluetoothStackID // Stack ID
ServiceFlags = GATT_SERVICE_FLAGS_LE_SERVICE
NumberOfServiceAttributeEntries = 4
ServiceTable = Array of GATT_Service_Attribute_Entry_t
BAS_Event_Callback_t = GATT_ServerEventCallback // In this GATT call back, it will cal BAS Event call back.
CallbackParameter = 1 // Instance ID for Application to refer the service info
传出参数:
ServiceHandleGroupResult // Starting Handle and Ending Handle
返回值:
ret_val = ServiceID
3,GATT_ServerEventCallback 里的处理
主要是处理两个事件,一个etGATT_Server_Read_Request和etGATT_Server_Write_Request。
etGATT_Server_Write_Request
收到的是GATT Event。根据AttributeOffset,找到Attribute表格里的属性。需要判断这个属性是aetCharacteristicDescriptor16,也就是要写入的是Client_Characteristic_Configuration。
再根据GATT Event中的AttributeValueLength和AttributeValue值,构造一个BAS_Client_Configuration_Update事件发给BAS Event call back,即etBAS_Server_Client_Configuration_Update。
etGATT_Server_Read_Request
如果读取的是Client Configuration,则构造一个etBAS_Server_Read_Client_Configuration_Request的BAS_Event_Data_t,发给BAS Event call back函数,请求读取Client Configuration的值。
如果读取的是Battery Level Attribute,则构造一个etBAS_Server_Read_Battery_Level_Request的BAS_Event_Data_t,发给BAS Event call back函数,请求读取Battery Level的值。