开发环境

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开发文档

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的更多相关文章

  1. gokit 统计分析 M2M接入服务 OTA固件升级 硬件社交化

    统计分析 M2M接入服务  OTA固件升级 硬件社交化 统计分析 为智能硬件定制的统计分析服务.只需添加入一行代码的集成工作,多维度的设备使用和用户行为数据就能自动统计出来. 演示 特色一:设备上线情 ...

  2. 接入WxPusher微信推送服务出现错误:Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported

    背景 使用WxPusher微信推送服务 ,可以及时的将服务的一些运行异常信息,发送到自己的微信上,方便了解服务的运行状态(PS:这个服务是免费的). 你可以在这里看到WxPusher微信推送服务的接入 ...

  3. 微信硬件H5面板开发(一) ---- 调用openApi

    微信硬件平台是微信推出连接物与人,物与物的IOT解决方案.也就是说可以通过微信控制各种智能设备.比如一些蓝牙设备.空调.电视等等. 我本身不懂硬件(虽然是电子信息专业),硬件是北航的两个研究生在弄,小 ...

  4. C#开发微信门户及应用(32)--微信支付接入和API封装使用

    在微信的应用上,微信支付是一个比较有用的部分,但也是比较复杂的技术要点,在微商大行其道的年代,自己的商店没有增加微信支付好像也说不过去,微信支付旨在为广大微信用户及商户提供更优质的支付服务,微信的支付 ...

  5. 微信平台接入Web页面功能接口(C#)

    微信平台接入web页面功能接口 今年因工作需要,通过微信平台接入公司的Wap页面,回忆下,记录内容,方面以后使用. 1.成为开发者后,你才可以使用公众平台的开发功能.需要填写URL和ToKen,接口配 ...

  6. 2.Android硬件访问服务编写系统代码【转】

    本文转载自:https://blog.csdn.net/qq_33443989/article/details/76696772 版权声明:本文为博主(Tower)自学笔记,欢迎转载! :-)     ...

  7. LED硬件访问服务(2)——JNI/HAL

    一.系统编程 1.SystemServer.java类中提供了main()方法,说明它是以一个进程的方式存在的,启动后直接执行其run() 2.注册服务ServiceManager.addServic ...

  8. 硬件访问服务学习笔记_WDS

    1.Android驱动框架App1 App2 App3 App4-------------------硬件访问服务-------------------JNI-------------------C库 ...

  9. 亲历H5移动端游戏微信支付接入及那些坑(二)——获取Openid和授权

    第一篇中将一些坑说明,那么这篇开始正式进入接入步骤.具体的参数说明,我不会列出,毕竟微信官方文档都有,我想大家都看的懂,而且这接口也有可能微信会变动,所以不列出来,也是不想引起大家的误解,接入步骤只起 ...

随机推荐

  1. C#的WebBrowser操作frame

    刚学c#不久,也不太懂什么IHTMLDocument.IHTMLDocument2.IWebBrowser2等等.自己琢磨了好久,终于知道了怎么用WebBrowser操作frame和iframe. 1 ...

  2. dubbo之上下文信息

    上下文信息 上下文中存放的是当前调用过程中所需的环境信息.所有配置信息都将转换为 URL 的参数,参见 schema 配置参考手册 中的对应URL参数一列. RpcContext 是一个 Thread ...

  3. Maya API编程快速入门

    一.Maya API编程简介 Autodesk® Maya® is an open product. This means that anyone outside of Autodesk can ch ...

  4. extension Array where Element 代码学习

    var fieldNames: [String] { let p = UnsafePointer<Int32>(self.pointer) return Array(utf8Strings ...

  5. 去掉二级页面 tabs 菜单, 修改返回按钮

    imports: [ /*引入的模块 依赖的模块*/ BrowserModule, ComponentsModule, IonicModule.forRoot(MyApp,{ tabsHideOnSu ...

  6. java模拟Cookies登陆

    在使用java访问URL时,如果该URL需要身份验证,那么就不能够直接访问,因为没有登陆.那么,如何解决这个问题呢? 方法是使用java模拟登陆,登陆后记录下cookie信息,在下次发起请求时时将co ...

  7. echarts在地图上绘制散点图(任意点)

    项目需求:在省份地图上绘制散点图,散点位置不一定是哪个城市或哪个区县,即任意点 通过查询官网文档,找到一个与需求类似的Demo:https://www.echartsjs.com/gallery/ed ...

  8. 【Codeforces 229B】Planets

    [链接] 我是链接,点我呀:) [题意] [题解] 设dis[i]表示到达i号传送器的最早时刻. 显然,虽然有那么多的出发时刻的限制,但我们还是越早到越好的. 因为你到得越早,出发的时间肯定不会比到达 ...

  9. hdu 4857 逆向拓扑排序+反向输出

    /*一组测试实例 4 4 2 3 1 2 4 */ #include<stdio.h> #include<string.h> #include<queue> usi ...

  10. 0708关于理解mysql SQL执行顺序

    转自 http://www.jellythink.com/archives/924,博客比价清晰 我理解上文的是SQL执行顺序 总体方案.当你加入索引了以后,其实他的执行计划是有细微的变化,比方说刚开 ...