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和授权
第一篇中将一些坑说明,那么这篇开始正式进入接入步骤.具体的参数说明,我不会列出,毕竟微信官方文档都有,我想大家都看的懂,而且这接口也有可能微信会变动,所以不列出来,也是不想引起大家的误解,接入步骤只起 ...
随机推荐
- Sql语句优化-查询两表不同行NOT IN、NOT EXISTS、连接查询Left Join
在实际开发中,我们往往需要比较两个或多个表数据的差别,比较那些数据相同那些数据不相同,这时我们有一下三种方法可以使用:1. IN或NOT IN,2. EXIST或NOTEXIST,3.使用连接查询(i ...
- Match 基因匹配 题解(From luoguBlog)
N<=20000!N2的LCS要原地爆炸. 去您妈的优化考场上有分就行TLE60真香嘿嘿嘿 然而这显然是个板子只不过像我这样见识短浅的蒟蒻不知道罢了 正解: 某大佬的博客 转化为lis后二分 复 ...
- 团体程序设计天梯赛-练习集-L1-044. 稳赢
L1-044. 稳赢 大家应该都会玩“锤子剪刀布”的游戏:两人同时给出手势,胜负规则如图所示: 现要求你编写一个稳赢不输的程序,根据对方的出招,给出对应的赢招.但是!为了不让对方输得太惨,你需要每隔K ...
- PAT_A1126#Eulerian Path
Source: PAT A1126 Eulerian Path (25 分) Description: In graph theory, an Eulerian path is a path in a ...
- 解析python部分常用魔术方法
def __add__(self, *args, **kwargs): # real signature unknown """ Return self+value. & ...
- Python基础练级攻略:day01
如果你有足够长时间做某事,一定会更擅长. 知识点: 计算机基础 变量 运算符 if语句 for-in循环 函数 列表.元组.字典.字符串.集合 ascii.unicode.utf-8.gbk 区别 A ...
- HTTP 状态码之:301、302 重定向
转自:http://www.cnblogs.com/5207/p/5908354.html 概念 301 Moved Permanently 被请求的资源已永久移动到新位置,并且将来任何对此资源的引用 ...
- [luogu1397 NOI2013] 矩阵游戏 (数学)
传送门 Description 婷婷是个喜欢矩阵的小朋友,有一天她想用电脑生成一个巨大的n行m列的矩阵(你不用担心她如何存储).她生成的这个矩阵满足一个神奇的性质:若用F[i][j]来表示矩阵中第i行 ...
- 了解CSS overflow属性 标签: htmlcss属性 2016-12-31 14:38 75人阅读 评论(1)
overflow属性规定当内容溢出元素框时如何显示. 例:div { width:150px; height:150px; overflow:scroll; } 可能的值有: 值 ...
- 如何在 vuex action 中获取到 vue 实例
问题:在做运营开发工具的时候 我想要请求后台服务器保存成功后 弹出一个弹框(饿了吗 的 message 弹框), 由于$message 是挂在 Vue原型链上的方法 (Vue.prototype.$m ...