支持BLE设备接入“腾讯连连”小程序

This commit is contained in:
zekwang
2020-12-01 20:11:07 +08:00
parent 2a06226767
commit a6ff5bb42b
151 changed files with 47376 additions and 7 deletions

View File

@@ -0,0 +1,6 @@
# The following lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(llsync)

View File

@@ -0,0 +1,28 @@
if (CONFIG_QCLOUD_LLSYNC_SUPPORT)
set(srcs
src/core/ble_qiot_llsync_data.c
src/core/ble_qiot_llsync_device.c
src/core/ble_qiot_llsync_event.c
src/core/ble_qiot_service.c
src/utils/ble_qiot_utils_base64.c
src/utils/ble_qiot_utils_hmac.c
src/utils/ble_qiot_utils_log.c
src/utils/ble_qiot_utils_md5.c
src/utils/ble_qiot_utils_sha1.c)
list(APPEND srcs
date_template/ble_qiot_template.c)
list(APPEND srcs
hal/ble_qiot_ble_device.c
hal/ble_qiot_ble_service.c)
set(includes inc src/internal_inc)
set(priv_includes date_template src/internal_inc hal)
endif ()
idf_component_register(SRCS "${srcs}"
INCLUDE_DIRS "${includes}"
PRIV_INCLUDE_DIRS "${priv_includes}"
REQUIRES bt)

View File

@@ -0,0 +1,7 @@
menu "QCloud LLSync"
config QCLOUD_LLSYNC_SUPPORT
bool "QCloud LLSync support."
default "y"
endmenu

View File

@@ -0,0 +1,149 @@
/*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* Unless required by applicable law or agreed to in writing, software distributed under the License is
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "ble_qiot_template.h"
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include "ble_qiot_export.h"
#include "ble_qiot_common.h"
#include "ble_qiot_param_check.h"
float sg_ch20_ppm = 0.0;
static int ble_property_ch20_ppm_value_set(const char *data, uint16_t len)
{
return 0;
}
static int ble_property_ch20_ppm_value_get(char *data, uint16_t buf_len)
{
memcpy(data, &sg_ch20_ppm, sizeof(float));
return sizeof(float);
}
static ble_property_t sg_ble_property_array[BLE_QIOT_PROPERTY_ID_BUTT] = {
{ble_property_ch20_ppm_value_set, ble_property_ch20_ppm_value_get, BLE_QIOT_PROPERTY_AUTH_READ,
BLE_QIOT_DATA_TYPE_FLOAT},
};
static bool ble_check_space_enough_by_type(uint8_t type, uint16_t left_size)
{
switch (type) {
case BLE_QIOT_DATA_TYPE_BOOL:
return left_size >= sizeof(uint8_t);
case BLE_QIOT_DATA_TYPE_INT:
case BLE_QIOT_DATA_TYPE_FLOAT:
case BLE_QIOT_DATA_TYPE_TIME:
return left_size >= sizeof(uint32_t);
case BLE_QIOT_DATA_TYPE_ENUM:
return left_size >= sizeof(uint16_t);
default:
// string length is unknow, default true
return true;
}
}
static uint16_t ble_check_ret_value_by_type(uint8_t type, uint16_t buf_len, uint16_t ret_val)
{
switch (type) {
case BLE_QIOT_DATA_TYPE_BOOL:
return ret_val <= sizeof(uint8_t);
case BLE_QIOT_DATA_TYPE_INT:
case BLE_QIOT_DATA_TYPE_FLOAT:
case BLE_QIOT_DATA_TYPE_TIME:
return ret_val <= sizeof(uint32_t);
case BLE_QIOT_DATA_TYPE_ENUM:
return ret_val <= sizeof(uint16_t);
default:
// string length is unknow, default true
return ret_val <= buf_len;
}
}
uint8_t ble_get_property_type_by_id(uint8_t id)
{
if (id >= BLE_QIOT_PROPERTY_ID_BUTT) {
ble_qiot_log_e("invalid property id %d", id);
return BLE_QIOT_DATA_TYPE_BUTT;
}
return sg_ble_property_array[id].type;
}
int ble_user_property_set_data(const e_ble_tlv *tlv)
{
POINTER_SANITY_CHECK(tlv, BLE_QIOT_RS_ERR_PARA);
if (tlv->id >= BLE_QIOT_PROPERTY_ID_BUTT) {
ble_qiot_log_e("invalid property id %d", tlv->id);
return BLE_QIOT_RS_ERR;
}
if (NULL != sg_ble_property_array[tlv->id].set_cb) {
if (0 != sg_ble_property_array[tlv->id].set_cb(tlv->val, tlv->len)) {
ble_qiot_log_e("set property id %d failed", tlv->id);
return BLE_QIOT_RS_ERR;
} else {
return BLE_QIOT_RS_OK;
}
}
ble_qiot_log_e("invalid set callback, id %d", tlv->id);
return BLE_QIOT_RS_ERR;
}
int ble_user_property_get_data_by_id(uint8_t id, char *buf, uint16_t buf_len)
{
int ret_len = 0;
POINTER_SANITY_CHECK(buf, BLE_QIOT_RS_ERR_PARA);
if (id >= BLE_QIOT_PROPERTY_ID_BUTT) {
ble_qiot_log_e("invalid property id %d", id);
return -1;
}
if (NULL != sg_ble_property_array[id].get_cb) {
if (!ble_check_space_enough_by_type(sg_ble_property_array[id].type, buf_len)) {
ble_qiot_log_e("not enough space get property id %d data", id);
return -1;
}
ret_len = sg_ble_property_array[id].get_cb(buf, buf_len);
if (ret_len < 0) {
ble_qiot_log_e("get property id %d data failed", id);
return -1;
} else {
if (ble_check_ret_value_by_type(sg_ble_property_array[id].type, buf_len, ret_len)) {
return ret_len;
} else {
ble_qiot_log_e("property id %d length invalid", id);
return -1;
}
}
}
ble_qiot_log_e("invalid callback, property id %d", id);
return 0;
}
int ble_user_property_report_reply_handle(uint8_t result)
{
ble_qiot_log_d("report reply result %d", result);
return BLE_QIOT_RS_OK;
}
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,163 @@
/*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* Unless required by applicable law or agreed to in writing, software distributed under the License is
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifndef BLE_QIOT_TEMPLATE_H_
#define BLE_QIOT_TEMPLATE_H_
#ifdef __cplusplus
extern "C"{
#endif
#include <stdint.h>
// data type in template, corresponding to type in json file
enum {
BLE_QIOT_DATA_TYPE_BOOL = 0,
BLE_QIOT_DATA_TYPE_INT,
BLE_QIOT_DATA_TYPE_STRING,
BLE_QIOT_DATA_TYPE_FLOAT,
BLE_QIOT_DATA_TYPE_ENUM,
BLE_QIOT_DATA_TYPE_TIME,
BLE_QIOT_DATA_TYPE_BUTT,
};
// message type, reference data template
enum {
BLE_QIOT_MSG_TYPE_PROPERTY = 0,
BLE_QIOT_MSG_TYPE_EVENT,
BLE_QIOT_MSG_TYPE_ACTION,
BLE_QIOT_MSG_TYPE_BUTT,
};
// define property authority, not used
enum {
BLE_QIOT_PROPERTY_AUTH_RW = 0,
BLE_QIOT_PROPERTY_AUTH_READ,
BLE_QIOT_PROPERTY_AUTH_BUTT,
};
// define reply result
enum {
BLE_QIOT_REPLY_SUCCESS = 0,
BLE_QIOT_REPLY_FAIL,
BLE_QIOT_REPLY_DATA_ERR,
BLE_QIOT_REPLY_BUTT,
};
// define message flow direction
enum {
BLE_QIOT_EFFECT_REQUEST = 0,
BLE_QIOT_EFFECT_REPLY,
BLE_QIOT_EFFECT_BUTT,
};
// define message type that from server to device
enum {
BLE_QIOT_DATA_DOWN_REPORT_REPLY = 0,
BLE_QIOT_DATA_DOWN_CONTROL,
BLE_QIOT_DATA_DOWN_GET_STATUS_REPLY,
BLE_QIOT_DATA_DOWN_ACTION,
BLE_QIOT_DATA_DOWN_EVENT_REPLY,
};
// define message type that from device to server
enum {
BLE_QIOT_EVENT_UP_PROPERTY_REPORT = 0,
BLE_QIOT_EVENT_UP_CONTROL_REPLY,
BLE_QIOT_EVENT_UP_GET_STATUS,
BLE_QIOT_EVENT_UP_EVENT_POST,
BLE_QIOT_EVENT_UP_ACTION_REPLY,
BLE_QIOT_EVENT_UP_BIND_SIGN_RET,
BLE_QIOT_EVENT_UP_CONN_SIGN_RET,
BLE_QIOT_EVENT_UP_UNBIND_SIGN_RET,
BLE_QIOT_EVENT_UP_REPORT_MTU,
BLE_QIOT_EVENT_UP_BUTT,
};
// msg header define, bit 7-6 is msg type, bit 5 means request or reply, bit 4 - 0 is id
#define BLE_QIOT_PARSE_MSG_HEAD_TYPE(_C) (((_C) & 0XFF) >> 6)
#define BLE_QIOT_PARSE_MSG_HEAD_EFFECT(_C) ((((_C) & 0XFF) & 0X20) ? BLE_QIOT_EFFECT_REPLY : BLE_QIOT_EFFECT_REQUEST)
#define BLE_QIOT_PARSE_MSG_HEAD_ID(_C) ((_C) & 0X1F)
#define BLE_QIOT_PACKAGE_MSG_HEAD(_TYPE, _REPLY, _ID) (((_TYPE) << 6) | (((_REPLY) == BLE_QIOT_EFFECT_REPLY) << 5) | ((_ID) & 0X1F))
// tlv header define, bit 7 - 5 is type, bit 4 - 0 depends on type of data template
#define BLE_QIOT_PARSE_TLV_HEAD_TYPE(_C) (((_C) & 0XFF) >> 5)
#define BLE_QIOT_PARSE_TLV_HEAD_ID(_C) ((_C) & 0X1F)
#define BLE_QIOT_PACKAGE_TLV_HEAD(_TYPE, _ID) (((_TYPE) << 5) | ((_ID) & 0X1F))
// define tlv struct
typedef struct{
uint8_t type;
uint8_t id;
uint16_t len;
char *val;
}e_ble_tlv;
#define BLE_QIOT_INCLUDE_PROPERTY
// define property id
enum {
BLE_QIOT_PROPERTY_ID_CH20_PPM_VALUE = 0,
BLE_QIOT_PROPERTY_ID_BUTT,
};
// define ch20_ppm_value attributes
#define BLE_QIOT_PROPERTY_CH20_PPM_VALUE_MIN (0)
#define BLE_QIOT_PROPERTY_CH20_PPM_VALUE_MAX (2)
#define BLE_QIOT_PROPERTY_CH20_PPM_VALUE_START (0)
#define BLE_QIOT_PROPERTY_CH20_PPM_VALUE_STEP (0.001)
// define property set handle return 0 if success, other is error
// sdk call the function that inform the server data to the device
typedef int (*property_set_cb)(const char *data, uint16_t len);
// define property get handle. return the data length obtained, -1 is error, 0 is no data
// sdk call the function fetch user data and send to the server, the data should wrapped by user adn skd just transmit
typedef int (*property_get_cb)(char *buf, uint16_t buf_len);
// each property have a struct ble_property_t, make up a array named sg_ble_property_array
typedef struct{
property_set_cb set_cb; //set callback
property_get_cb get_cb; //get callback
uint8_t authority; //property authority
uint8_t type; //data type
}ble_property_t;
// property module
#ifdef BLE_QIOT_INCLUDE_PROPERTY
uint8_t ble_get_property_type_by_id(uint8_t id);
int ble_user_property_set_data(const e_ble_tlv *tlv);
int ble_user_property_get_data_by_id(uint8_t id, char *buf, uint16_t buf_len);
int ble_user_property_report_reply_handle(uint8_t result);
#endif
// event module
#ifdef BLE_QIOT_INCLUDE_EVENT
int ble_event_get_id_array_size(uint8_t event_id);
uint8_t ble_event_get_param_id_type(uint8_t event_id, uint8_t param_id);
int ble_event_get_data_by_id(uint8_t event_id, uint8_t param_id, char *out_buf, uint16_t buf_len);
int ble_user_event_reply_handle(uint8_t event_id, uint8_t result);
#endif
// action module
#ifdef BLE_QIOT_INCLUDE_ACTION
uint8_t ble_action_get_intput_type_by_id(uint8_t action_id, uint8_t input_id);
uint8_t ble_action_get_output_type_by_id(uint8_t action_id, uint8_t output_id);
int ble_action_get_input_id_size(uint8_t action_id);
int ble_action_get_output_id_size(uint8_t action_id);
int ble_action_user_handle_input_param(uint8_t action_id, e_ble_tlv *input_param_array, uint8_t input_array_size, uint8_t *output_id_array);
int ble_action_user_handle_output_param(uint8_t action_id, uint8_t output_id, char *buf, uint16_t buf_len);
#endif
#ifdef __cplusplus
}
#endif
#endif //BLE_QIOT_TEMPLATE_H_

View File

@@ -0,0 +1,26 @@
{
"version": "1.0",
"profile": {
"ProductId": "1NBPCQ7L2O",
"CategoryId": "1"
},
"properties": [
{
"id": "ch20_ppm_value",
"name": "甲醛浓度值",
"desc": "",
"mode": "r",
"define": {
"type": "float",
"min": "0",
"max": "2",
"start": "0",
"step": "0.001",
"unit": "ppm(mg/m3)"
},
"required": false
}
],
"events": [],
"actions": []
}

View File

@@ -0,0 +1,114 @@
/*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* Unless required by applicable law or agreed to in writing, software distributed under the License is
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifdef __cplusplus
extern "C" {
#endif
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include "ble_qiot_export.h"
#include "ble_qiot_service.h"
#include "ble_qiot_import.h"
// add std head file here
#include <stdint.h>
// add ble qiot head file here
#include "ble_qiot_import.h"
#include "ble_qiot_config.h"
#include "esp_bt_device.h"
#include "esp_spi_flash.h"
// divece info which defined in explorer platform
#define PRODUCT_ID "1NBPCQ7L2O"
#define DEVICE_NAME "123"
#define SECRET_KEY "q/WQFemC2ejNZTNWMqHerA=="
int ble_get_product_id(char *product_id)
{
memcpy(product_id, PRODUCT_ID, strlen(PRODUCT_ID));
return 0;
}
int ble_get_device_name(char *device_name)
{
memcpy(device_name, DEVICE_NAME, strlen(DEVICE_NAME));
return strlen(DEVICE_NAME);
}
int ble_get_psk(char *psk)
{
memcpy(psk, SECRET_KEY, strlen(SECRET_KEY));
return 0;
}
int ble_get_mac(char *mac)
{
char *address = (char *)esp_bt_dev_get_address();
memcpy(mac, address, 6);
return 0;
}
int ble_write_flash(uint32_t flash_addr, const char *write_buf, uint16_t write_len)
{
int ret = spi_flash_erase_range(flash_addr, BLE_QIOT_RECORD_FLASH_PAGESIZE);
ret = spi_flash_write(flash_addr, write_buf, write_len);
return ret == ESP_OK ? write_len : ret;
}
int ble_read_flash(uint32_t flash_addr, char *read_buf, uint16_t read_len)
{
int ret = spi_flash_read(flash_addr, read_buf, read_len);
return ret == ESP_OK ? read_len : ret;
}
ble_timer_t ble_timer_create(uint8_t type, ble_timer_cb timeout_handle)
{
return NULL;
}
ble_qiot_ret_status_t ble_timer_start(ble_timer_t timer_id, uint32_t period)
{
return BLE_QIOT_RS_OK;
}
ble_qiot_ret_status_t ble_timer_stop(ble_timer_t timer_id)
{
return BLE_QIOT_RS_OK;
}
ble_qiot_ret_status_t ble_timer_delete(ble_timer_t timer_id)
{
return BLE_QIOT_RS_OK;
}
// should return ATT_MTU - 3
uint16_t ble_get_user_data_mtu_size(void)
{
// esp32 can not get mtuuse default mtu
return 20;
}
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,536 @@
/*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* Unless required by applicable law or agreed to in writing, software distributed under the License is
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifdef __cplusplus
extern "C" {
#endif
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "esp_bt.h"
#include "esp_gap_ble_api.h"
#include "esp_gatts_api.h"
#include "esp_bt_main.h"
#include "esp_gatt_common_api.h"
#include "ble_qiot_config.h"
#include "ble_qiot_export.h"
#include "ble_qiot_service.h"
#include "ble_qiot_import.h"
#define LLSYNC_LOG_TAG "LLSYNC"
/* Attributes State Machine */
enum
{
IDX_SVC,
IDX_CHAR_A,
IDX_CHAR_VAL_A,
IDX_CHAR_B,
IDX_CHAR_VAL_B,
IDX_CHAR_C,
IDX_CHAR_VAL_C,
IDX_CHAR_CFG_C,
HRS_IDX_NB,
};
#define PROFILE_NUM 1
#define PROFILE_APP_IDX 0
#define LLSYNC_APP_ID 0x55
#define SAMPLE_DEVICE_NAME "l"
#define SVC_INST_ID 0
/* The max length of characteristic value. When the GATT client performs a write or prepare write operation,
* the data length must be less than LLSYNC_CHAR_VAL_LEN_MAX.
*/
#define LLSYNC_CHAR_VAL_LEN_MAX 500
#define PREPARE_BUF_MAX_SIZE 1024
#define CHAR_DECLARATION_SIZE (sizeof(uint8_t))
#define ADV_CONFIG_FLAG (1 << 0)
static uint8_t adv_config_done = 0;
uint16_t llsync_handle_table[HRS_IDX_NB];
typedef struct {
uint8_t *prepare_buf;
int prepare_len;
uint16_t handle;
} prepare_type_env_t;
static prepare_type_env_t prepare_write_env;
static uint8_t raw_adv_data[32] = {
/* flags */
0x02, 0x01, 0x06,
/* service uuid */
0x03, 0x03, 0xE0, 0xFF,
};
static esp_ble_adv_params_t adv_params = {
.adv_int_min = 0x20,
.adv_int_max = 0x40,
.adv_type = ADV_TYPE_IND,
.own_addr_type = BLE_ADDR_TYPE_PUBLIC,
.channel_map = ADV_CHNL_ALL,
.adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY,
};
struct gatts_profile_inst {
esp_gatts_cb_t gatts_cb;
uint16_t gatts_if;
uint16_t app_id;
uint16_t conn_id;
uint16_t service_handle;
esp_gatt_srvc_id_t service_id;
uint16_t char_handle;
esp_bt_uuid_t char_uuid;
esp_gatt_perm_t perm;
esp_gatt_char_prop_t property;
uint16_t descr_handle;
esp_bt_uuid_t descr_uuid;
};
ble_qiot_ret_status_t ble_advertising_start(adv_info_s *adv)
{
uint8_t usr_adv_data[31] = {0};
uint8_t len = 0;
uint8_t index = 0;
memcpy(usr_adv_data, &adv->manufacturer_info.company_identifier, sizeof(uint16_t));
len = sizeof(uint16_t);
memcpy(usr_adv_data + len, adv->manufacturer_info.adv_data, adv->manufacturer_info.adv_data_len);
len += adv->manufacturer_info.adv_data_len;
index = 7;
raw_adv_data[index++] = len + 1;
raw_adv_data[index++] = 0xFF;
memcpy(raw_adv_data + index, usr_adv_data, len);
index += len;
raw_adv_data[index++] = strlen(SAMPLE_DEVICE_NAME) + 1;
raw_adv_data[index++] = 0x09;
memcpy(raw_adv_data + index, SAMPLE_DEVICE_NAME, strlen(SAMPLE_DEVICE_NAME));
index += strlen(SAMPLE_DEVICE_NAME);
esp_log_buffer_hex("adv", raw_adv_data, index);
//config adv data
esp_err_t ret = esp_ble_gap_config_adv_data_raw(raw_adv_data, index);
if (ret) {
ESP_LOGE(LLSYNC_LOG_TAG, "config adv data failed, error code = %x", ret);
}
adv_config_done |= ADV_CONFIG_FLAG;
ESP_LOGI(LLSYNC_LOG_TAG, "start advertising");
esp_ble_gap_start_advertising(&adv_params);
return 0;
}
ble_qiot_ret_status_t ble_advertising_stop(void)
{
esp_ble_gap_stop_advertising();
return 0;
}
static void gatts_profile_event_handler(esp_gatts_cb_event_t event,
esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param);
/* One gatt-based profile one app_id and one gatts_if, this array will store the gatts_if returned by ESP_GATTS_REG_EVT */
static struct gatts_profile_inst llsync_profile_tab[PROFILE_NUM] = {
[PROFILE_APP_IDX] = {
.gatts_cb = gatts_profile_event_handler,
.gatts_if = ESP_GATT_IF_NONE, /* Not get the gatt_if, so initial is ESP_GATT_IF_NONE */
},
};
ble_qiot_ret_status_t ble_send_notify(uint8_t *buf, uint8_t len)
{
esp_ble_gatts_send_indicate(llsync_profile_tab[PROFILE_APP_IDX].gatts_if, llsync_profile_tab[PROFILE_APP_IDX].conn_id,
llsync_handle_table[IDX_CHAR_VAL_C],len, buf, false);
return BLE_QIOT_RS_OK;
}
static const uint16_t primary_service_uuid = ESP_GATT_UUID_PRI_SERVICE;
static const uint16_t character_declaration_uuid = ESP_GATT_UUID_CHAR_DECLARE;
static const uint16_t character_client_config_uuid = ESP_GATT_UUID_CHAR_CLIENT_CONFIG;
static const uint8_t char_prop_write = ESP_GATT_CHAR_PROP_BIT_WRITE;
static const uint8_t char_prop_notify = ESP_GATT_CHAR_PROP_BIT_NOTIFY;
static const uint8_t heart_measurement_ccc[2] = {0x00, 0x00};
/* service_uuid and Characteristic_uuid*/
static uint8_t llsync_service_uuid[16] = {
0xe2, 0xa4, 0x1b, 0x54, 0x93, 0xe4, 0x6a, 0xb5, 0x20, 0x4e, 0xd0, 0x65, 0xe0, 0xff, 0x00, 0x00,
};
static uint8_t llsync_device_info_uuid[16] = {
0xe2, 0xa4, 0x1b, 0x54, 0x93, 0xe4, 0x6a, 0xb5, 0x20, 0x4e, 0xd0, 0x65, 0xe1, 0xff, 0x00, 0x00,
};
static uint8_t llsync_data_uuid[16] = {
0xe2, 0xa4, 0x1b, 0x54, 0x93, 0xe4, 0x6a, 0xb5, 0x20, 0x4e, 0xd0, 0x65, 0xe2, 0xff, 0x00, 0x00,
};
static uint8_t llsync_event_uuid[16] = {
0xe2, 0xa4, 0x1b, 0x54, 0x93, 0xe4, 0x6a, 0xb5, 0x20, 0x4e, 0xd0, 0x65, 0xe3, 0xff, 0x00, 0x00,
};
/* Full Database Description - Used to add attributes into the database */
static const esp_gatts_attr_db_t gatt_db[HRS_IDX_NB] =
{
// Service Declaration
[IDX_SVC] =
{{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&primary_service_uuid, ESP_GATT_PERM_READ,
sizeof(llsync_service_uuid), sizeof(llsync_service_uuid), (uint8_t *)llsync_service_uuid}},
/* Characteristic Declaration */
[IDX_CHAR_A] =
{{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ,
CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_write}},
/* Characteristic Value */
[IDX_CHAR_VAL_A] =
{{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_128, (uint8_t *)llsync_device_info_uuid, ESP_GATT_PERM_WRITE,
LLSYNC_CHAR_VAL_LEN_MAX, 0, NULL}},
/* Characteristic Declaration */
[IDX_CHAR_B] =
{{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ,
CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_write}},
/* Characteristic Value */
[IDX_CHAR_VAL_B] =
{{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_128, (uint8_t *)llsync_data_uuid, ESP_GATT_PERM_WRITE,
LLSYNC_CHAR_VAL_LEN_MAX, 0, NULL}},
/* Characteristic Declaration */
[IDX_CHAR_C] =
{{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ,
CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_notify}},
/* Characteristic Value */
[IDX_CHAR_VAL_C] =
{{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_128, (uint8_t *)llsync_event_uuid, 0,
LLSYNC_CHAR_VAL_LEN_MAX, 0, NULL}},
/* Characteristic User Descriptor */
[IDX_CHAR_CFG_C] =
{{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
sizeof(uint16_t), sizeof(heart_measurement_ccc), (uint8_t *)heart_measurement_ccc}},
};
static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)
{
switch (event) {
case ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT:
ESP_LOGI(LLSYNC_LOG_TAG, "ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT");
adv_config_done &= (~ADV_CONFIG_FLAG);
if (adv_config_done == 0) {
ble_qiot_advertising_start();
adv_config_done = 2;
}
break;
case ESP_GAP_BLE_ADV_START_COMPLETE_EVT:
/* advertising start complete event to indicate advertising start successfully or failed */
if (param->adv_start_cmpl.status != ESP_BT_STATUS_SUCCESS) {
ESP_LOGE(LLSYNC_LOG_TAG, "advertising start failed");
}else{
ESP_LOGI(LLSYNC_LOG_TAG, "advertising start successfully");
}
break;
case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT:
if (param->adv_stop_cmpl.status != ESP_BT_STATUS_SUCCESS) {
ESP_LOGE(LLSYNC_LOG_TAG, "Advertising stop failed");
}
else {
ESP_LOGI(LLSYNC_LOG_TAG, "Stop adv successfully\n");
}
break;
case ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT:
ESP_LOGI(LLSYNC_LOG_TAG, "update connection params status = %d, min_int = %d, max_int = %d,conn_int = %d,latency = %d, timeout = %d",
param->update_conn_params.status,
param->update_conn_params.min_int,
param->update_conn_params.max_int,
param->update_conn_params.conn_int,
param->update_conn_params.latency,
param->update_conn_params.timeout);
break;
default:
break;
}
}
void example_prepare_write_event_env(esp_gatt_if_t gatts_if, prepare_type_env_t *prepare_write_env, esp_ble_gatts_cb_param_t *param)
{
ESP_LOGI(LLSYNC_LOG_TAG, "prepare write, handle = %d, value len = %d", param->write.handle, param->write.len);
esp_gatt_status_t status = ESP_GATT_OK;
if (prepare_write_env->prepare_buf == NULL) {
prepare_write_env->prepare_buf = (uint8_t *)malloc(PREPARE_BUF_MAX_SIZE * sizeof(uint8_t));
prepare_write_env->prepare_len = 0;
prepare_write_env->handle = 0;
if (prepare_write_env->prepare_buf == NULL) {
ESP_LOGE(LLSYNC_LOG_TAG, "%s, Gatt_server prep no mem", __func__);
status = ESP_GATT_NO_RESOURCES;
}
} else {
if(param->write.offset > PREPARE_BUF_MAX_SIZE) {
status = ESP_GATT_INVALID_OFFSET;
} else if ((param->write.offset + param->write.len) > PREPARE_BUF_MAX_SIZE) {
status = ESP_GATT_INVALID_ATTR_LEN;
}
}
/*send response when param->write.need_rsp is true */
if (param->write.need_rsp){
esp_gatt_rsp_t *gatt_rsp = (esp_gatt_rsp_t *)malloc(sizeof(esp_gatt_rsp_t));
if (gatt_rsp != NULL){
gatt_rsp->attr_value.len = param->write.len;
gatt_rsp->attr_value.handle = param->write.handle;
gatt_rsp->attr_value.offset = param->write.offset;
gatt_rsp->attr_value.auth_req = ESP_GATT_AUTH_REQ_NONE;
memcpy(gatt_rsp->attr_value.value, param->write.value, param->write.len);
esp_err_t response_err = esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, status, gatt_rsp);
if (response_err != ESP_OK){
ESP_LOGE(LLSYNC_LOG_TAG, "Send response error");
}
free(gatt_rsp);
}else{
ESP_LOGE(LLSYNC_LOG_TAG, "%s, malloc failed", __func__);
}
}
if (status != ESP_GATT_OK){
return;
}
memcpy(prepare_write_env->prepare_buf + param->write.offset,
param->write.value,
param->write.len);
prepare_write_env->prepare_len += param->write.len;
prepare_write_env->handle = param->write.handle;
}
void example_exec_write_event_env(prepare_type_env_t *prepare_write_env, esp_ble_gatts_cb_param_t *param){
if (param->exec_write.exec_write_flag == ESP_GATT_PREP_WRITE_EXEC && prepare_write_env->prepare_buf){
if (prepare_write_env->handle == llsync_handle_table[IDX_CHAR_VAL_A]){
ESP_LOGI(LLSYNC_LOG_TAG, "ble_device_info_write_cb");
ble_device_info_write_cb(prepare_write_env->prepare_buf, prepare_write_env->prepare_len);
}else if (prepare_write_env->handle == llsync_handle_table[IDX_CHAR_VAL_B]){
ESP_LOGI(LLSYNC_LOG_TAG, "ble_lldata_write_cb");
ble_lldata_write_cb(prepare_write_env->prepare_buf, prepare_write_env->prepare_len);
}
esp_log_buffer_hex(LLSYNC_LOG_TAG, prepare_write_env->prepare_buf, prepare_write_env->prepare_len);
}else{
ESP_LOGI(LLSYNC_LOG_TAG,"ESP_GATT_PREP_WRITE_CANCEL");
}
if (prepare_write_env->prepare_buf) {
free(prepare_write_env->prepare_buf);
prepare_write_env->prepare_buf = NULL;
}
prepare_write_env->prepare_len = 0;
}
static void gatts_profile_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param)
{
switch (event) {
case ESP_GATTS_REG_EVT:
{
esp_err_t set_dev_name_ret = esp_ble_gap_set_device_name(SAMPLE_DEVICE_NAME);
if (set_dev_name_ret) {
ESP_LOGE(LLSYNC_LOG_TAG, "set device name failed, error code = %x", set_dev_name_ret);
}
esp_err_t raw_adv_ret = esp_ble_gap_config_adv_data_raw(raw_adv_data, 7);
if (raw_adv_ret){
ESP_LOGE(LLSYNC_LOG_TAG, "config raw adv data failed, error code = %x ", raw_adv_ret);
}
adv_config_done |= ADV_CONFIG_FLAG;
esp_err_t create_attr_ret = esp_ble_gatts_create_attr_tab(gatt_db, gatts_if, HRS_IDX_NB, SVC_INST_ID);
if (create_attr_ret) {
ESP_LOGE(LLSYNC_LOG_TAG, "create attr table failed, error code = %x", create_attr_ret);
}
}
break;
case ESP_GATTS_READ_EVT:
ESP_LOGI(LLSYNC_LOG_TAG, "ESP_GATTS_READ_EVT");
break;
case ESP_GATTS_WRITE_EVT:
if (!param->write.is_prep){
// the data length of gattc write must be less than LLSYNC_CHAR_VAL_LEN_MAX.
ESP_LOGI(LLSYNC_LOG_TAG, "GATT_WRITE_EVT, handle = %d, value len = %d, value :", param->write.handle, param->write.len);
esp_log_buffer_hex(LLSYNC_LOG_TAG, param->write.value, param->write.len);
if (param->write.handle == llsync_handle_table[IDX_CHAR_VAL_A]){
ESP_LOGI(LLSYNC_LOG_TAG, "ble_device_info_write_cb");
ble_device_info_write_cb(param->write.value, param->write.len);
}else if (param->write.handle == llsync_handle_table[IDX_CHAR_VAL_B]){
ESP_LOGI(LLSYNC_LOG_TAG, "ble_lldata_write_cb");
ble_lldata_write_cb(param->write.value, param->write.len);
}
ESP_LOGI(LLSYNC_LOG_TAG, "GATT_WRITE_EVT OVER");
/* send response when param->write.need_rsp is true*/
if (param->write.need_rsp){
esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, ESP_GATT_OK, NULL);
}
}else{
example_prepare_write_event_env(gatts_if, &prepare_write_env, param);
}
break;
case ESP_GATTS_EXEC_WRITE_EVT:
// the length of gattc prepare write data must be less than GATTS_DEMO_CHAR_VAL_LEN_MAX.
ESP_LOGI(LLSYNC_LOG_TAG, "ESP_GATTS_EXEC_WRITE_EVT");
example_exec_write_event_env(&prepare_write_env, param);
break;
case ESP_GATTS_MTU_EVT:
ESP_LOGI(LLSYNC_LOG_TAG, "ESP_GATTS_MTU_EVT, MTU %d", param->mtu.mtu);
break;
case ESP_GATTS_CONF_EVT:
ESP_LOGI(LLSYNC_LOG_TAG, "ESP_GATTS_CONF_EVT, status = %d, attr_handle %d", param->conf.status, param->conf.handle);
break;
case ESP_GATTS_START_EVT:
ESP_LOGI(LLSYNC_LOG_TAG, "SERVICE_START_EVT, status %d, service_handle %d", param->start.status, param->start.service_handle);
break;
case ESP_GATTS_CONNECT_EVT:
ESP_LOGI(LLSYNC_LOG_TAG, "ESP_GATTS_CONNECT_EVT, conn_id = %d", param->connect.conn_id);
esp_log_buffer_hex(LLSYNC_LOG_TAG, param->connect.remote_bda, 6);
esp_ble_conn_update_params_t conn_params = {0};
memcpy(conn_params.bda, param->connect.remote_bda, sizeof(esp_bd_addr_t));
/* For the iOS system, please refer to Apple official documents about the BLE connection parameters restrictions. */
conn_params.latency = 0;
conn_params.max_int = 0x20; // max_int = 0x20*1.25ms = 40ms
conn_params.min_int = 0x10; // min_int = 0x10*1.25ms = 20ms
conn_params.timeout = 400; // timeout = 400*10ms = 4000ms
//start sent the update connection parameters to the peer device.
esp_ble_gap_update_conn_params(&conn_params);
break;
case ESP_GATTS_DISCONNECT_EVT:
ESP_LOGI(LLSYNC_LOG_TAG, "ESP_GATTS_DISCONNECT_EVT, reason = 0x%x", param->disconnect.reason);
ble_qiot_advertising_start();
break;
case ESP_GATTS_CREAT_ATTR_TAB_EVT:{
if (param->add_attr_tab.status != ESP_GATT_OK){
ESP_LOGE(LLSYNC_LOG_TAG, "create attribute table failed, error code=0x%x", param->add_attr_tab.status);
}
else if (param->add_attr_tab.num_handle != HRS_IDX_NB){
ESP_LOGE(LLSYNC_LOG_TAG, "create attribute table abnormally, num_handle (%d) doesn't equal to HRS_IDX_NB(%d)", param->add_attr_tab.num_handle, HRS_IDX_NB);
}
else {
ESP_LOGI(LLSYNC_LOG_TAG, "create attribute table successfully, the number handle = %d\n",param->add_attr_tab.num_handle);
memcpy(llsync_handle_table, param->add_attr_tab.handles, sizeof(llsync_handle_table));
esp_ble_gatts_start_service(llsync_handle_table[IDX_SVC]);
}
break;
}
case ESP_GATTS_STOP_EVT:
case ESP_GATTS_OPEN_EVT:
case ESP_GATTS_CANCEL_OPEN_EVT:
case ESP_GATTS_CLOSE_EVT:
case ESP_GATTS_LISTEN_EVT:
case ESP_GATTS_CONGEST_EVT:
case ESP_GATTS_UNREG_EVT:
case ESP_GATTS_DELETE_EVT:
default:
break;
}
}
static void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param)
{
/* If event is register event, store the gatts_if for each profile */
if (event == ESP_GATTS_REG_EVT) {
if (param->reg.status == ESP_GATT_OK) {
llsync_profile_tab[PROFILE_APP_IDX].gatts_if = gatts_if;
} else {
ESP_LOGE(LLSYNC_LOG_TAG, "reg app failed, app_id %04x, status %d", param->reg.app_id, param->reg.status);
return;
}
}
do {
int idx;
for (idx = 0; idx < PROFILE_NUM; idx++) {
/* ESP_GATT_IF_NONE, not specify a certain gatt_if, need to call every profile cb function */
if (gatts_if == ESP_GATT_IF_NONE || gatts_if == llsync_profile_tab[idx].gatts_if) {
if (llsync_profile_tab[idx].gatts_cb) {
llsync_profile_tab[idx].gatts_cb(event, gatts_if, param);
}
}
}
} while (0);
}
void ble_services_add(const qiot_service_init_s *p_service)
{
// do nothing
return;
}
void ble_qiot_service_init(void)
{
esp_err_t ret;
ESP_ERROR_CHECK(esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT));
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
ret = esp_bt_controller_init(&bt_cfg);
if (ret) {
ESP_LOGE(LLSYNC_LOG_TAG, "%s enable controller failed: %s", __func__, esp_err_to_name(ret));
return;
}
ret = esp_bt_controller_enable(ESP_BT_MODE_BLE);
if (ret) {
ESP_LOGE(LLSYNC_LOG_TAG, "%s enable controller failed: %s", __func__, esp_err_to_name(ret));
return;
}
ret = esp_bluedroid_init();
if (ret) {
ESP_LOGE(LLSYNC_LOG_TAG, "%s init bluetooth failed: %s", __func__, esp_err_to_name(ret));
return;
}
ret = esp_bluedroid_enable();
if (ret) {
ESP_LOGE(LLSYNC_LOG_TAG, "%s enable bluetooth failed: %s", __func__, esp_err_to_name(ret));
return;
}
// init llsync sdk
ble_qiot_explorer_init();
ret = esp_ble_gatts_register_callback(gatts_event_handler);
if (ret){
ESP_LOGE(LLSYNC_LOG_TAG, "gatts register error, error code = %x", ret);
return;
}
ret = esp_ble_gap_register_callback(gap_event_handler);
if (ret){
ESP_LOGE(LLSYNC_LOG_TAG, "gap register error, error code = %x", ret);
return;
}
ret = esp_ble_gatts_app_register(LLSYNC_APP_ID);
if (ret){
ESP_LOGE(LLSYNC_LOG_TAG, "gatts app register error, error code = %x", ret);
return;
}
return;
}
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,71 @@
/*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* Unless required by applicable law or agreed to in writing, software distributed under the License is
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifndef QCLOUD_BLE_QIOT_CONFIG_H
#define QCLOUD_BLE_QIOT_CONFIG_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include <stdint.h>
#include "esp_log.h"
#define BLE_QIOT_SDK_VERSION "1.2.0" // sdk version
#define BLE_QIOT_SDK_DEBUG 0 // sdk debug switch
// the device broadcast is controlled by the user, but we provide a mechanism to help the device save more power.
// if you want broadcast is triggered by something like press a button instead of all the time, and the broadcast
// stopped automatically in a few minutes if the device is not bind, define BLE_QIOT_BUTTON_BROADCAST is 1 and
// BLE_QIOT_BIND_TIMEOUT is the period that broadcast stopped.
// if the device in the bound state, broadcast dose not stop automatically.
#define BLE_QIOT_BUTTON_BROADCAST 0
#if (1 == BLE_QIOT_BUTTON_BROADCAST)
#define BLE_QIOT_BIND_TIMEOUT (2 * 60 * 1000) // unit: ms
#endif
// some data like integer need to be transmitted in a certain byte order, defined it according to your device
#define __ORDER_LITTLE_ENDIAN__ 1234
#define __ORDER_BIG_ENDIAN__ 4321
#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
// in some BLE stack ble_qiot_log_hex() maybe not work, user can use there own hexdump function
#define BLE_QIOT_USER_DEFINE_HEDUMP 1
#if (1 == BLE_QIOT_USER_DEFINE_HEDUMP)
#define ble_qiot_log_hex(level, hex_name, data, data_len) \
do { \
esp_log_buffer_hex(hex_name, data, data_len); \
} while (0)
#endif // BLE_QIOT_USER_DEFINE_HEDUMP
// Macro for logging a formatted string, the function must printf raw string without any color, prefix, newline or
// timestamp
#define BLE_QIOT_LOG_PRINT(...) printf(__VA_ARGS__)
// nrf52832xxAA Flash size is 512KB, nrf52832xxAB Flash size is 512KB, be carefol of the address!
#define BLE_QIOT_RECORD_FLASH_ADDR 0xFE000 // qiot data storage address
#define BLE_QIOT_RECORD_FLASH_PAGESIZE 4096 // flash page size, see chip datasheet
// the following definition will affect the stack that LLSync usedthe minimum value tested is
// 2048BLE_QIOT_EVENT_MAX_SIZE is 128, BLE_QIOT_EVENT_BUF_SIZE is 23 the max length that llsync event data, depends
// on the length of user data reported to Tencent Lianlian at a time
#define BLE_QIOT_EVENT_MAX_SIZE (128)
// the minimum between BLE_QIOT_EVENT_MAX_SIZE and mtu
#define BLE_QIOT_EVENT_BUF_SIZE (23)
#ifdef __cplusplus
}
#endif
#endif // QCLOUD_BLE_QIOT_CONFIG_H

View File

@@ -0,0 +1 @@
idf_component_register(SRCS "app_main.c" INCLUDE_DIRS "")

View File

@@ -0,0 +1,54 @@
/*
* ESPRESSIF MIT License
*
* Copyright (c) 2017 <ESPRESSIF SYSTEMS (SHANGHAI) PTE LTD>
*
* Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP32 only, in which case,
* it is free of charge, to any person obtaining a copy of this software and associated
* documentation files (the "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "ble_qiot_export.h"
extern void ble_qiot_service_init(void);
extern float sg_ch20_ppm;
static void test_task(void *pvParameters)
{
while (1) {
sg_ch20_ppm += 0.001;
printf("report ppm %.3f\n", sg_ch20_ppm);
ble_event_report_property();
vTaskDelay(10000 / portTICK_PERIOD_MS);
}
}
void app_main()
{
nvs_flash_init();
ble_qiot_service_init();
xTaskCreate(test_task, "tsk1", 4 * 1024, NULL, 5, NULL);
}

View File

@@ -0,0 +1,6 @@
# Name, Type, SubType, Offset, Size
phy_init, data, phy, 0xf000, 0x1000
otadata,data,ota, 0x10000, 8K
nvs,data,nvs, 0x12000, 56K
ota_0,app, ota_0, 0x100000,0x180000
ota_1,app, ota_1, 0x280000,0x180000
1 # Name Type SubType Offset Size
2 phy_init data phy 0xf000 0x1000
3 otadata data ota 0x10000 8K
4 nvs data nvs 0x12000 56K
5 ota_0 app ota_0 0x100000 0x180000
6 ota_1 app ota_1 0x280000 0x180000

View File

@@ -0,0 +1,36 @@
## 说明
本工程模拟了一个甲醛监测场景ESP32任务定期模拟甲醛数据(也可以通过甲醛监测传感器实时获取)ESP32通过BLE和腾讯连连小程序连接使用LLSync协议传输数据由腾讯连连小程序将甲醛数据上传到物联网开发平台。
## 使用说明
1. 安装`ESP-IDF`,请参考[官网文档](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/index.html#step-2-get-esp-idf)
```c
mkdir -p ~/esp
cd ~/esp
git clone --recursive https://github.com/espressif/esp-idf.git
```
2. 抽取`qcloud-iot-ble-esp32`组件
```c
cd scripts
python3 code_extract/code_extract.py esp32
```
3. 拷贝`qcloud-iot-ble-esp32`组件到`ESP-IDF`目录下
```c
cp -r scripts/code_extract/qcloud-iot-ble-esp32 $IDF_PATH
cd $IDF_PATH/qcloud-iot-ble-esp32
```
4. 登陆[物联网开发平台](https://cloud.tencent.com/product/iotexplorer), 使用`qcloud_llsync/date_template/esp32.json`作为数据模版创建设备。
使用新设备的三元信息替换`qcloud_llsync/hal/ble_qiot_ble_device.c`中宏定义中的设备信息,编译并烧录到开发板。
```c
idf.py flash
```
5. 打开腾讯连连小程序,添加设备,观察串口输出和小程序界面,串口输出如下:
```c
report ppm 0.028
I (271165) post data: 00 00 05 60 43 60 e5 3c
I (271165) LLSYNC: ESP_GATTS_CONF_EVT, status = 0, attr_handle 46
I (271445) LLSYNC: GATT_WRITE_EVT, handle = 44, value len = 2, value :
I (271445) LLSYNC: 20 00
I (271445) LLSYNC: ble_lldata_write_cb
I (271445) LLSYNC: GATT_WRITE_EVT OVER
```
可以观察到小程序界面甲醛数据同步变化。

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff