nRF52832添加微信硬件接入服务AirSync
开发环境
SDK版本:nRF5_SDK_15.0.0
芯片:nRF52832-QFAA
OS: FreeRTOS 10.0.0
测试APP:AirSyncDebugger https://iot.weixin.qq.com/wiki/doc/blue/AirSyncDebugger2.3.0.apk
AirSync概述
AirSync是微信硬件平台提供的一种微信客户端与蓝牙设备间通讯的技术协议,它允许蓝牙设备与微信客户端之间收发数据,并支持通过微信客户端透传到远程服务器。该技术在支持微信互联的蓝牙手环、血压计、智能秤、血糖仪等设备上有比较多的应用。
详细开发文档请参考官网 微信硬件平台的
AirSync 服务添加
本文仅仅就怎么在sdk15的框架下添加 AirSync 服务进行描述,具体协议实现请参考官方给出的示例程序即可
ble_wechat_service.c
蓝牙设备需暴露两个特征值(Characteristics):Write特征值,Indication特征值。蓝牙设备从Write特征值接受数据,从Indication特征值发送数据。
/**
**********************************************************************************
* @file ble_wechat_service.c
* @author wanghuan any question please send mail to 371463817@qq.com
* @version V1.0
* @date 2019-01-28
* @brief 蓝牙BLE微信硬件接入服务
**********************************************************************************
* @attention
*
* 版权说明:Copyright (c) 2019-2020 江苏亨通光网科技有限公司
* 硬件平台:nRF52832_QFAA
* SDK版本:nRF5_SDK_15.0.0
* 修改日志:
*
**********************************************************************************
*/ #include "sdk_common.h"
#if NRF_MODULE_ENABLED(BLE_WECHAT)
#include "ble.h"
#include "ble_wechat_service.h"
#include "ble_srv_common.h"
#include "nrf_sdh_ble.h"
#include "nrf_sdh_soc.h"
#include "app_error.h" // 日志打印配置
#define NRF_LOG_MODULE_NAME ble_wechat
#if BLE_WECHAT_CONFIG_LOG_ENABLED
#define NRF_LOG_LEVEL BLE_WECHAT_CONFIG_LOG_LEVEL
#define NRF_LOG_INFO_COLOR BLE_WECHAT_CONFIG_INFO_COLOR
#define NRF_LOG_DEBUG_COLOR BLE_WECHAT_CONFIG_DEBUG_COLOR
#else // BLE_WECHAT_CONFIG_LOG_ENABLED
#define NRF_LOG_LEVEL 0
#endif // BLE_WECHAT_CONFIG_LOG_ENABLED
#include "nrf_log.h"
NRF_LOG_MODULE_REGISTER(); uint8_t m_addl_adv_manuf_data [BLE_GAP_ADDR_LEN]; /**@brief Function for handling the @ref BLE_GAP_EVT_CONNECTED event from the SoftDevice.
*
* @param[in] p_wechats BLE_WECHAT Service structure.
* @param[in] p_ble_evt Pointer to the event received from BLE stack.
*/
static void on_connect(ble_wechat_t * p_wechat, ble_evt_t const * p_ble_evt)
{
ret_code_t err_code;
ble_wechat_evt_t evt;
ble_gatts_value_t gatts_val;
uint8_t cccd_value[];
ble_wechat_client_context_t * p_client = NULL; p_wechat->conn_handle = p_ble_evt->evt.gap_evt.conn_handle; err_code = blcm_link_ctx_get(p_wechat->p_link_ctx_storage,
p_ble_evt->evt.gap_evt.conn_handle,
(void *) &p_client);
if (err_code != NRF_SUCCESS)
{
NRF_LOG_ERROR("Link context for 0x%02X connection handle could not be fetched.",
p_ble_evt->evt.gap_evt.conn_handle);
} /* Check the hosts CCCD value to inform of readiness to send data using the RX characteristic */
memset(&gatts_val, , sizeof(ble_gatts_value_t));
gatts_val.p_value = cccd_value;
gatts_val.len = sizeof(cccd_value);
gatts_val.offset = ; err_code = sd_ble_gatts_value_get(p_ble_evt->evt.gap_evt.conn_handle,
p_wechat->indicate_handles.cccd_handle,
&gatts_val); if ((err_code == NRF_SUCCESS) &&
(p_wechat->data_handler != NULL) &&
ble_srv_is_indication_enabled(gatts_val.p_value))
{
if (p_client != NULL)
{
p_client->is_indicate_enabled = true;
} memset(&evt, , sizeof(ble_wechat_evt_t));
evt.type = BLE_WECHAT_EVT_COMM_STARTED;
evt.p_wechat = p_wechat;
evt.conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
evt.p_link_ctx = p_client; p_wechat->data_handler(&evt);
}
} static void on_disconnect(ble_wechat_t * p_wechat, ble_evt_t const * p_ble_evt)
{
ble_wechat_evt_t evt; p_wechat->conn_handle = BLE_CONN_HANDLE_INVALID; evt.type = BLE_WECHAT_EVT_COMM_STOPPED;
evt.p_wechat = p_wechat;
evt.conn_handle = p_ble_evt->evt.gap_evt.conn_handle; p_wechat->data_handler(&evt);
} // BLE 写操作
static void on_write(ble_wechat_t * p_wechat, ble_evt_t const * p_ble_evt)
{
ret_code_t err_code;
ble_wechat_evt_t evt;
ble_wechat_client_context_t * p_client;
ble_gatts_evt_write_t const * p_evt_write = &p_ble_evt->evt.gatts_evt.params.write; err_code = blcm_link_ctx_get(p_wechat->p_link_ctx_storage,
p_ble_evt->evt.gatts_evt.conn_handle,
(void *) &p_client);
if (err_code != NRF_SUCCESS)
{
NRF_LOG_ERROR("Link context for 0x%02X connection handle could not be fetched.",
p_ble_evt->evt.gatts_evt.conn_handle);
} memset(&evt, , sizeof(ble_wechat_evt_t));
evt.p_wechat = p_wechat;
evt.conn_handle = p_ble_evt->evt.gatts_evt.conn_handle;
evt.p_link_ctx = p_client; if ((p_evt_write->handle == p_wechat->write_handles.value_handle) && (p_evt_write->len <= BLE_WECHAT_MAX_DATA_LEN) && (p_wechat->data_handler != NULL))
{
evt.type = BLE_WECHAT_EVT_RX_DATA;
evt.params.rx_data.p_data = p_evt_write->data;
evt.params.rx_data.length = p_evt_write->len; p_wechat->data_handler(&evt);
}
else
{
// Do Nothing. This event is not relevant for this service.
}
} static void on_indicate_comfirm(ble_wechat_t *p_wechat, ble_evt_t const * p_ble_evt)
{
ret_code_t err_code;
ble_wechat_evt_t evt;
ble_wechat_client_context_t * p_client; err_code = blcm_link_ctx_get(p_wechat->p_link_ctx_storage,
p_ble_evt->evt.gatts_evt.conn_handle,
(void *) &p_client);
if (err_code != NRF_SUCCESS)
{
NRF_LOG_ERROR("Link context for 0x%02X connection handle could not be fetched.",
p_ble_evt->evt.gatts_evt.conn_handle);
return;
} if (p_client->is_indicate_enabled)
{
memset(&evt, , sizeof(ble_wechat_evt_t));
evt.type = BLE_WECHAT_EVT_TX_RDY;
evt.p_wechat = p_wechat;
evt.conn_handle = p_ble_evt->evt.gatts_evt.conn_handle;
evt.p_link_ctx = p_client; p_wechat->data_handler(&evt);
}
} // BLE_WECHAT服务蓝牙事件处理函数
void ble_wechat_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context)
{
if ((p_context == NULL) || (p_ble_evt == NULL))
{
return;
} ble_wechat_t * p_wechat = (ble_wechat_t *)p_context; switch (p_ble_evt->header.evt_id)
{
case BLE_GAP_EVT_CONNECTED:
on_connect(p_wechat, p_ble_evt);
break; case BLE_GATTS_EVT_WRITE:
on_write(p_wechat, p_ble_evt);
break; case BLE_GATTS_EVT_HVC:
on_indicate_comfirm(p_wechat, p_ble_evt);
break; case BLE_GATTS_EVT_HVN_TX_COMPLETE:
// on_hvx_tx_complete(p_wechat, p_ble_evt);
break; case BLE_GAP_EVT_DISCONNECTED:
on_disconnect(p_wechat, p_ble_evt);
break;
default:
// No implementation needed.
break;
}
} static void get_mac_addr(uint8_t *p_mac_addr)
{
uint32_t error_code;
ble_gap_addr_t *p_mac_addr_t = (ble_gap_addr_t*)malloc(sizeof(ble_gap_addr_t));
error_code = sd_ble_gap_addr_get(p_mac_addr_t);
APP_ERROR_CHECK(error_code);
uint8_t *d = p_mac_addr_t->addr;
for ( uint8_t i = ; i >;)
{
i--;
p_mac_addr[-i]= d[i];
}
free(p_mac_addr_t);
p_mac_addr_t = NULL;
} // 微信服务蓝牙通信indicate特征字节添加
static uint32_t ble_wechat_add_indicate_char(ble_wechat_t * p_wechat)
{
ble_gatts_char_md_t char_md; //GATT特征属性全部都用char_md表示
ble_gatts_attr_t attr_char_value; //GATT属性
ble_uuid_t char_uuid; //特征字节用uuid表示
ble_gatts_attr_md_t attr_md; //特征值属性
ble_gatts_attr_md_t cccd_md; //CCCD信息(客户端特性配置描述符,用于配置通知和指示) memset(&cccd_md, , sizeof(cccd_md));
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm); //开放read权限(权限等级)
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.write_perm); //开放write权限
cccd_md.vloc = BLE_GATTS_VLOC_STACK; //属性值存放在堆栈空间,Softdevice可以控制的memory memset(&char_md, , sizeof(char_md));
// 特征值参数组(用于申明)
char char_desc[] = "indicate char";
char_md.p_char_user_desc = (uint8_t *)char_desc;
char_md.char_user_desc_size = strlen(char_desc);
char_md.char_user_desc_max_size =strlen(char_desc); char_md.char_props.indicate = ; //允许指示修改
char_md.p_char_pf = NULL;
char_md.p_user_desc_md = NULL;
char_md.p_cccd_md = &cccd_md;
char_md.p_sccd_md = NULL; // 使用公用服务蓝牙协议小组基础UUID
BLE_UUID_BLE_ASSIGN(char_uuid, BLE_UUID_WECHAT_INDICATE_CHARACTERISTICS); memset(&attr_md, , sizeof(attr_md));
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm);
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm); attr_md.vloc = BLE_GATTS_VLOC_STACK;
attr_md.rd_auth = ;
attr_md.wr_auth = ;
attr_md.vlen = ; memset(&attr_char_value, , sizeof(attr_char_value)); attr_char_value.p_uuid = &char_uuid;
attr_char_value.p_attr_md = &attr_md;
attr_char_value.init_len = strlen(char_desc);
attr_char_value.p_value = (uint8_t *)char_desc;
attr_char_value.init_offs = ;
attr_char_value.max_len = BLE_WECHAT_MAX_DATA_LEN; return sd_ble_gatts_characteristic_add(p_wechat->service_handle,
&char_md,
&attr_char_value,
&p_wechat->indicate_handles);
} // 微信服务蓝牙通信write特征字节添加
static uint32_t ble_wechat_add_write_char(ble_wechat_t * p_wechat)
{
ble_gatts_char_md_t char_md; //GATT特征属性全部都用char_md表示
ble_gatts_attr_t attr_char_value; //GATT属性
ble_uuid_t char_uuid; //特征字节用uuid表示
ble_gatts_attr_md_t attr_md; //特征值属性 memset(&char_md, , sizeof(char_md));
// 特征值参数组(用于申明)
char char_desc[] = "write char";
char_md.p_char_user_desc = (uint8_t *)char_desc;
char_md.char_user_desc_size = strlen(char_desc);
char_md.char_user_desc_max_size =strlen(char_desc); char_md.char_props.write = ; //允许请求写修改操作
char_md.p_char_pf = NULL;
char_md.p_user_desc_md = NULL;
char_md.p_cccd_md = NULL;
char_md.p_sccd_md = NULL; // 使用公用服务蓝牙协议小组基础UUID
BLE_UUID_BLE_ASSIGN(char_uuid, BLE_UUID_WECHAT_WRITE_CHARACTERISTICS); memset(&attr_md, , sizeof(attr_md));
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm);
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm); attr_md.vloc = BLE_GATTS_VLOC_STACK;
attr_md.rd_auth = ;
attr_md.wr_auth = ;
attr_md.vlen = ; memset(&attr_char_value, , sizeof(attr_char_value)); attr_char_value.p_uuid = &char_uuid;
attr_char_value.p_attr_md = &attr_md;
attr_char_value.init_len = strlen(char_desc);
attr_char_value.p_value = (uint8_t *)char_desc;
attr_char_value.init_offs = ;
attr_char_value.max_len = BLE_WECHAT_MAX_DATA_LEN; return sd_ble_gatts_characteristic_add(p_wechat->service_handle,
&char_md,
&attr_char_value,
&p_wechat->write_handles);
} // 微信服务蓝牙通信read特征字节添加
static uint32_t ble_wechat_add_read_char(ble_wechat_t * p_wechat)
{
ble_gatts_char_md_t char_md; //GATT特征属性全部都用char_md表示
ble_gatts_attr_t attr_char_value; //GATT属性
ble_uuid_t char_uuid; //特征字节用uuid表示
ble_gatts_attr_md_t attr_md; //特征值属性 get_mac_addr(m_addl_adv_manuf_data); memset(&char_md, , sizeof(char_md));
// 特征值参数组(用于申明)
// char char_desc[] = "read char";
// char_md.p_char_user_desc = (uint8_t *)char_desc;
// char_md.char_user_desc_size = strlen(char_desc);
// char_md.char_user_desc_max_size =strlen(char_desc); char_md.char_props.read = ; //允许读操作
char_md.p_char_user_desc = NULL;
char_md.p_char_pf = NULL;
char_md.p_user_desc_md = NULL;
char_md.p_cccd_md = NULL;
char_md.p_sccd_md = NULL; // 使用公用服务蓝牙协议小组基础UUID
BLE_UUID_BLE_ASSIGN(char_uuid, BLE_UUID_WECHAT_READ_CHARACTERISTICS); memset(&attr_md, , sizeof(attr_md));
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm);
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm); attr_md.vloc = BLE_GATTS_VLOC_STACK;
attr_md.rd_auth = ;
attr_md.wr_auth = ;
attr_md.vlen = ; memset(&attr_char_value, , sizeof(attr_char_value)); attr_char_value.p_uuid = &char_uuid;
attr_char_value.p_attr_md = &attr_md;
attr_char_value.init_len = sizeof(m_addl_adv_manuf_data);
attr_char_value.p_value = (uint8_t *)m_addl_adv_manuf_data;
attr_char_value.init_offs = ;
attr_char_value.max_len = BLE_WECHAT_MAX_DATA_LEN; return sd_ble_gatts_characteristic_add(p_wechat->service_handle,
&char_md,
&attr_char_value,
&p_wechat->read_handles);
} // BLE_WECHAT 服务初始化
uint32_t ble_wechat_init(ble_wechat_t * p_wechat, ble_wechat_init_t const * p_wechat_init)
{
ret_code_t err_code;
ble_uuid_t ble_uuid; VERIFY_PARAM_NOT_NULL(p_wechat);
VERIFY_PARAM_NOT_NULL(p_wechat_init); // 初始化服务结构体
// BLE_WECHAT 事件句柄
p_wechat->data_handler = p_wechat_init->data_handler; // 添加基于通用SIG-UUID的BLE_WECHAT服务
BLE_UUID_BLE_ASSIGN(ble_uuid, BLE_UUID_WECHAT_SERVICE); err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &ble_uuid, &p_wechat->service_handle);
VERIFY_SUCCESS(err_code); // 添加BLE_WECHAT服务特征字节
err_code = ble_wechat_add_indicate_char(p_wechat);
VERIFY_SUCCESS(err_code);
err_code = ble_wechat_add_write_char(p_wechat);
VERIFY_SUCCESS(err_code);
err_code = ble_wechat_add_read_char(p_wechat);
VERIFY_SUCCESS(err_code); return NRF_SUCCESS;
} // 蓝牙数据发送
uint32_t ble_wechat_indicate_data(ble_wechat_t * p_wechat, uint8_t * p_data, uint16_t * p_length)
{
ret_code_t err_code;
ble_gatts_hvx_params_t hvx_params;
ble_wechat_client_context_t * p_client; VERIFY_PARAM_NOT_NULL(p_wechat); err_code = blcm_link_ctx_get(p_wechat->p_link_ctx_storage, p_wechat->conn_handle, (void *) &p_client); //获取indicate是否使能
VERIFY_SUCCESS(err_code); if ((p_wechat->conn_handle == BLE_CONN_HANDLE_INVALID) || (p_client == NULL))
{
return NRF_ERROR_NOT_FOUND;
} if (!p_client->is_indicate_enabled)//通知使能了,没有使能通知返回错误,不蓝牙发送
{
return NRF_ERROR_INVALID_STATE;
} if (*p_length > BLE_WECHAT_MAX_DATA_LEN)
{
return NRF_ERROR_INVALID_PARAM;
} memset(&hvx_params, , sizeof(hvx_params)); hvx_params.handle = p_wechat->indicate_handles.value_handle;//数据处理
hvx_params.p_data = p_data; //数据
hvx_params.p_len = p_length; //长度
hvx_params.type = BLE_GATT_HVX_INDICATION; return sd_ble_gatts_hvx(p_wechat->conn_handle, &hvx_params);
} #endif // NRF_MODULE_ENABLED(BLE_WECHAT)
ble_airsyncs.h
#ifndef BLE_WECHAT_SERVICE__
#define BLE_WECHAT_SERVICE__ #include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include "sdk_config.h"
#include "ble.h"
#include "ble_srv_common.h"
#include "nrf_sdh_ble.h"
#include "ble_link_ctx_manager.h" #ifdef __cplusplus
extern "C" {
#endif // 蓝牙微信服务实例宏定义
// _name ->实例名称
// _nus_max_clients ->最大客户端链接数
#define BLE_WECHAT_DEF(_name, _wechat_max_clients) \
BLE_LINK_CTX_MANAGER_DEF(CONCAT_2(_name, _link_ctx_storage), \
(_wechat_max_clients), \
sizeof(ble_wechat_client_context_t)); \
static ble_wechat_t _name = \
{ \
.p_link_ctx_storage = &CONCAT_2(_name, _link_ctx_storage) \
}; \
NRF_SDH_BLE_OBSERVER(_name ## _obs, \
, \
ble_wechat_on_ble_evt, \
&_name) // 蓝牙微信服务UUID定义
#define BLE_UUID_WECHAT_SERVICE 0xFEE7
#define BLE_UUID_WECHAT_WRITE_CHARACTERISTICS 0xFEC7
#define BLE_UUID_WECHAT_INDICATE_CHARACTERISTICS 0xFEC8
#define BLE_UUID_WECHAT_READ_CHARACTERISTICS 0xFEC9 #define BLE_WECHAT_MAX_DATA_LEN 20 /**@brief BLE_WECHAT Service event types. */
// 蓝牙微信服务事件类型
typedef enum
{
BLE_WECHAT_EVT_RX_DATA, /**< Data received. */
BLE_WECHAT_EVT_TX_RDY, /**< Service is ready to accept new data to be transmitted. */
BLE_WECHAT_EVT_COMM_STARTED, /**< Notification has been enabled. */
BLE_WECHAT_EVT_COMM_STOPPED, /**< Notification has been disabled. */
} ble_wechat_evt_type_t; /* Forward declaration of the ble_wechat_t type. 前置申明*/
typedef struct ble_wechat_s ble_wechat_t; /**@brief BLE_WECHAT Service @ref BLE_WECHATS_EVT_RX_DATA event data.
* 蓝牙接收数据事件数据结构体
* @details This structure is passed to an event when @ref BLE_WECHATS_EVT_RX_DATA occurs.
*/
typedef struct
{
uint8_t const * p_data; /**< A pointer to the buffer with received data. */
uint16_t length; /**< Length of received data. */
} ble_wechat_evt_rx_data_t; /**@brief BLE_WECHAT Service client context structure.
*
* @details This structure contains state context related to hosts.
* 蓝牙客户端参数
*/
typedef struct
{
bool is_indicate_enabled; /**< Variable to indicate if the peer has enabled notification of the WECHAT_INDICATE characteristic.*/
} ble_wechat_client_context_t; /**@brief BLE_WECHAT Service event structure.
* 蓝牙微信服务事件结构体
* @details This structure is passed to an event coming from service.
*/
typedef struct
{
ble_wechat_evt_type_t type; /**< Event type. */
ble_wechat_t * p_wechat; /**< A pointer to the instance. */
uint16_t conn_handle; /**< Connection handle. */
ble_wechat_client_context_t * p_link_ctx; /**< A pointer to the link context. */
union
{
ble_wechat_evt_rx_data_t rx_data; /**< @ref BLE_WECHATS_EVT_RX_DATA event data. */
} params;
} ble_wechat_evt_t; /**@brief BLE_WECHAT Service event handler type. */
// 蓝牙微信服务事件回调函数类型
typedef void (* ble_wechat_data_handler_t) (ble_wechat_evt_t * p_evt); /**@brief BLE_WECHAT Service initialization structure. */
// 蓝牙微信服务初始化结构体,主要用于注册应用数据接收处理回调
typedef struct
{
ble_wechat_data_handler_t data_handler; /**< Event handler to be called for handling received data. */
} ble_wechat_init_t; /**@brief BLE_WECHAT Service structure.
* 蓝牙微信服务结构体
* @details This structure contains status information related to the service.
*/
struct ble_wechat_s
{
uint8_t uuid_type; /**< UUID type for Nordic UART Service Base UUID. */
uint16_t service_handle; /**< Handle of Nordic UART Service (as provided by the SoftDevice). */
uint16_t conn_handle;
ble_gatts_char_handles_t indicate_handles; /**< Handles related to the GNTS characteristic (as provided by the SoftDevice). */
ble_gatts_char_handles_t write_handles;
ble_gatts_char_handles_t read_handles;
blcm_link_ctx_storage_t * const p_link_ctx_storage; /**< Pointer to link context storage with handles of all current connections and its context. */
ble_wechat_data_handler_t data_handler; /**< Event handler to be called for handling received data. */
}; uint32_t ble_wechat_init(ble_wechat_t * p_wechat, ble_wechat_init_t const * p_wechat_init); void ble_wechat_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context); uint32_t ble_wechat_indicate_data(ble_wechat_t * p_wechat, uint8_t * p_data, uint16_t * p_length); #ifdef __cplusplus
}
#endif #endif // BLE_WECHAT_SERVICE__ /** @} */
在用户程序中添加服务相关代码
#if (WECHAT_TEST_EN == 1)
BLE_WECHAT_DEF(m_wechat, NRF_SDH_BLE_TOTAL_LINK_COUNT); //微信蓝牙服务
#endif // 添加私有服务时,需更改NRF_SDH_BLE_VS_UUID_COUNT
static ble_uuid_t m_adv_uuids[] = /**< Universally unique service identifiers. */
{
{BLE_UUID_DEVICE_INFORMATION_SERVICE, BLE_UUID_TYPE_BLE},
#if (WECHAT_TEST_EN == 1)
{BLE_UUID_WECHAT_SERVICE, BLE_UUID_TYPE_BLE},
#endif
};
在服务初始化 static void services_init(void) 添加
#if (WECHAT_TEST_EN == 1)
// 添加BLE_WECHAT服务
ble_wechat_init_t m_wechat_init;
memset(&m_wechat_init, , sizeof(m_wechat_init));
m_wechat_init.data_handler = ble_wechat_data_handler; err_code = ble_wechat_init(&m_wechat, &m_wechat_init);
APP_ERROR_CHECK(err_code);
#endif
#if (WECHAT_TEST_EN == 1)
static void ble_wechat_data_handler(ble_wechat_evt_t * p_evt) //微信蓝牙接收数据处理(write特征属性)
{
if (p_evt->type == BLE_WECHAT_EVT_RX_DATA) //蓝牙有数据接收
{
NRF_LOG_INFO("Received data from BLE_WECHAT.");
NRF_LOG_HEXDUMP_INFO(p_evt->params.rx_data.p_data, p_evt->params.rx_data.length);
ble_wechat_indicate_data(&m_wechat, (uint8_t*)p_evt->params.rx_data.p_data, &p_evt->params.rx_data.length);
}
}
#endif
在广播初始化 static void advertising_init(void) 中添加
#if (WECHAT_TEST_EN == 1)
extern uint8_t m_addl_adv_manuf_data [BLE_GAP_ADDR_LEN];
ble_advdata_manuf_data_t manuf_data;
manuf_data.company_identifier = 0x0088;
manuf_data.data.size = ;
manuf_data.data.p_data = m_addl_adv_manuf_data; NRF_LOG_INFO("BLE_WECHAT mac addr.");
NRF_LOG_HEXDUMP_INFO(manuf_data.data.p_data, manuf_data.data.size);
init.advdata.p_manuf_specific_data = &manuf_data;
#endif
至此 AirSync 的服务相关代码实现完毕,剩下的是协议方面的处理;
nRF52832添加微信硬件接入服务AirSync的更多相关文章
- gokit 统计分析 M2M接入服务 OTA固件升级 硬件社交化
统计分析 M2M接入服务 OTA固件升级 硬件社交化 统计分析 为智能硬件定制的统计分析服务.只需添加入一行代码的集成工作,多维度的设备使用和用户行为数据就能自动统计出来. 演示 特色一:设备上线情 ...
- 接入WxPusher微信推送服务出现错误:Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported
背景 使用WxPusher微信推送服务 ,可以及时的将服务的一些运行异常信息,发送到自己的微信上,方便了解服务的运行状态(PS:这个服务是免费的). 你可以在这里看到WxPusher微信推送服务的接入 ...
- 微信硬件H5面板开发(一) ---- 调用openApi
微信硬件平台是微信推出连接物与人,物与物的IOT解决方案.也就是说可以通过微信控制各种智能设备.比如一些蓝牙设备.空调.电视等等. 我本身不懂硬件(虽然是电子信息专业),硬件是北航的两个研究生在弄,小 ...
- C#开发微信门户及应用(32)--微信支付接入和API封装使用
在微信的应用上,微信支付是一个比较有用的部分,但也是比较复杂的技术要点,在微商大行其道的年代,自己的商店没有增加微信支付好像也说不过去,微信支付旨在为广大微信用户及商户提供更优质的支付服务,微信的支付 ...
- 微信平台接入Web页面功能接口(C#)
微信平台接入web页面功能接口 今年因工作需要,通过微信平台接入公司的Wap页面,回忆下,记录内容,方面以后使用. 1.成为开发者后,你才可以使用公众平台的开发功能.需要填写URL和ToKen,接口配 ...
- 2.Android硬件访问服务编写系统代码【转】
本文转载自:https://blog.csdn.net/qq_33443989/article/details/76696772 版权声明:本文为博主(Tower)自学笔记,欢迎转载! :-) ...
- LED硬件访问服务(2)——JNI/HAL
一.系统编程 1.SystemServer.java类中提供了main()方法,说明它是以一个进程的方式存在的,启动后直接执行其run() 2.注册服务ServiceManager.addServic ...
- 硬件访问服务学习笔记_WDS
1.Android驱动框架App1 App2 App3 App4-------------------硬件访问服务-------------------JNI-------------------C库 ...
- 亲历H5移动端游戏微信支付接入及那些坑(二)——获取Openid和授权
第一篇中将一些坑说明,那么这篇开始正式进入接入步骤.具体的参数说明,我不会列出,毕竟微信官方文档都有,我想大家都看的懂,而且这接口也有可能微信会变动,所以不列出来,也是不想引起大家的误解,接入步骤只起 ...
随机推荐
- ORACLE锁表解锁
SELECT object_name, machine, s.sid, s.serial# FROM gv$locked_object l, dba_objects o, gv$session s W ...
- Embedded之Stack之一
1 Intro When a program starts executing, a certain contiguous section of memory is set aside for the ...
- LINQ to Entities 不识别方法“System.Nullable`1[System.Int32] DiffDays(System.Nullable`1[System.DateTime], System.Nullable`1[System.DateTime])”,因此该方法无法转换为存储表达式。
解决方案: db.table.Where(m=>System.Data.Objects.EntityFunctions.DiffDays(m.CreateTime, DateTime.Now) ...
- spring 回顾
主要就是它的IOC理念 即:把对象的创建.初始化.销毁等工作交给spring容器来做 依赖jar
- Selenium3+python自动化 -JS处理滚动条
selenium并不是万能的,有时候页面上操作无法实现的,这时候就需要借助JS来完成了. 常见场景: 当页面上的元素超过一屏后,想操作屏幕下方的元素,是不能直接定位到,会报元素不可见的. 这时候需要借 ...
- S-HR薪酬项目与核算表的关系
- 【scoi2009】围豆豆(最短路模型)
洛谷题面:https://www.luogu.org/problemnew/show/P2566 由每个豆子引一条射线,与射线交点个数为奇数相当于多边形围住了它,这样可以定义一个状态f[x][y][s ...
- 10.shard、replica机制及单node下创建index
主要知识点 1.shard&replica机制梳理 2.单node环境下创建index的情况 1.shard&replica机制再次梳理 (1)index包含多 ...
- NLTK学习笔记(二):文本、语料资源和WordNet汇总
目录 语料库基本函数表 文本语料库分类 常见语料库及其用法 载入自定义语料库 词典资源 停用词语料库 WordNet面向语义的英语字典 语义相似度 语料库基本函数表 示例 描述 fileids() 语 ...
- Java设计模式之 — 单例(Singleton)
转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/8860649 写软件的时候经常需要用到打印日志功能,可以帮助你调试和定位问题,项目上 ...