mirror of
https://gitee.com/beecue/fastbee.git
synced 2025-12-20 09:55:54 +08:00
添加智能灯固件代码
This commit is contained in:
@@ -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(ble_eddystone_demo)
|
||||
@@ -0,0 +1,11 @@
|
||||
#
|
||||
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
|
||||
# project subdirectory.
|
||||
#
|
||||
|
||||
PROJECT_NAME := ble_eddystone_demo
|
||||
|
||||
COMPONENT_ADD_INCLUDEDIRS := components/include
|
||||
|
||||
include $(IDF_PATH)/make/project.mk
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
| Supported Targets | ESP32 |
|
||||
| ----------------- | ----- |
|
||||
|
||||
ESP-IDF Eddystone demo
|
||||
========================
|
||||
This example demonstrates Eddystone-compatible BLE scanning of eddystone frame,including UID,URL.
|
||||
|
||||
Eddystone is an open beacon protocol specification from Google aimed at improving “proximity-based experiences”
|
||||
with support for both Android and iOS smart device platforms.
|
||||
|
||||
Learn more on https://developers.google.com/beacons and https://github.com/google/eddystone.
|
||||
|
||||
esp_eddystone_protocol.h
|
||||
==========================
|
||||
This header file includes some eddystone-protocol related definitions.
|
||||
|
||||
esp_eddystone_api.h & esp_eddystone_api.c
|
||||
===========================================
|
||||
These files contains the decoding and decoded result of an eddystone frame packet.
|
||||
|
||||
You just need to include esp_eddystone_protocol.h, esp_eddystone_api.h and esp_eddystone_api.c for development.
|
||||
|
||||
esp_eddystone_demo.c
|
||||
======================
|
||||
This is an example/demo of using esp_eddystone_protocol.h, esp_eddystone_api.h and esp_eddystone_api.c files to resolve eddystone packet.
|
||||
@@ -0,0 +1,3 @@
|
||||
idf_component_register(SRCS "esp_eddystone_api.c"
|
||||
"esp_eddystone_demo.c"
|
||||
INCLUDE_DIRS "")
|
||||
@@ -0,0 +1,4 @@
|
||||
#
|
||||
# "main" pseudo-component makefile.
|
||||
#
|
||||
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
|
||||
@@ -0,0 +1,254 @@
|
||||
/*
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* This file is used to decode eddystone information.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "esp_err.h"
|
||||
#include "esp_gap_ble_api.h"
|
||||
#include "esp_eddystone_protocol.h"
|
||||
#include "esp_eddystone_api.h"
|
||||
|
||||
|
||||
/* Declare static functions */
|
||||
static esp_err_t esp_eddystone_uid_received(const uint8_t* buf, uint8_t len, esp_eddystone_result_t* res);
|
||||
static esp_err_t esp_eddystone_url_received(const uint8_t* buf, uint8_t len, esp_eddystone_result_t* res);
|
||||
static char* esp_eddystone_resolve_url_scheme(const uint8_t* url_start, const uint8_t* url_end);
|
||||
static esp_err_t esp_eddystone_tlm_received(const uint8_t* buf, uint8_t len, esp_eddystone_result_t* res);
|
||||
static esp_err_t esp_eddystone_get_inform(const uint8_t* buf, uint8_t len, esp_eddystone_result_t* res);
|
||||
|
||||
/* Eddystone-URL scheme prefixes */
|
||||
static const char* eddystone_url_prefix[4] = {
|
||||
"http://www.",
|
||||
"https://www.",
|
||||
"http://",
|
||||
"https://"
|
||||
};
|
||||
|
||||
/* Eddystone-URL HTTP URL encoding */
|
||||
static const char* eddystone_url_encoding[14] = {
|
||||
".com/",
|
||||
".org/",
|
||||
".edu/",
|
||||
".net/",
|
||||
".info/",
|
||||
".biz/",
|
||||
".gov/",
|
||||
".com",
|
||||
".org",
|
||||
".edu",
|
||||
".net",
|
||||
".info",
|
||||
".biz",
|
||||
".gov"
|
||||
};
|
||||
|
||||
/****************** Eddystone-UID **************
|
||||
Byte offset Field Description
|
||||
0 Frame Type Value = 0x00
|
||||
1 Ranging Data Calibrated Tx power at 0 m
|
||||
2 NID[0] 10-byte Namespace
|
||||
3 NID[1]
|
||||
4 NID[2]
|
||||
5 NID[3]
|
||||
6 NID[4]
|
||||
7 NID[5]
|
||||
8 NID[6]
|
||||
9 NID[7]
|
||||
10 NID[8]
|
||||
11 NID[9]
|
||||
12 BID[0] 6-byte Instance
|
||||
13 BID[1]
|
||||
14 BID[2]
|
||||
15 BID[3]
|
||||
16 BID[4]
|
||||
17 BID[5]
|
||||
18 RFU Reserved for future use, must be0x00
|
||||
19 RFU Reserved for future use, must be0x00
|
||||
*********************************************/
|
||||
/* decode and store received UID */
|
||||
static esp_err_t esp_eddystone_uid_received(const uint8_t* buf, uint8_t len, esp_eddystone_result_t* res)
|
||||
{
|
||||
uint8_t pos = 0;
|
||||
//1-byte Ranging Data + 10-byte Namespace + 6-byte Instance
|
||||
if((len != EDDYSTONE_UID_DATA_LEN) && (len != (EDDYSTONE_UID_RFU_LEN+EDDYSTONE_UID_DATA_LEN))) {
|
||||
//ERROR:uid len wrong
|
||||
return -1;
|
||||
}
|
||||
res->inform.uid.ranging_data = buf[pos++];
|
||||
for(int i=0; i<EDDYSTONE_UID_NAMESPACE_LEN; i++) {
|
||||
res->inform.uid.namespace_id[i] = buf[pos++];
|
||||
}
|
||||
for(int i=0; i<EDDYSTONE_UID_INSTANCE_LEN; i++) {
|
||||
res->inform.uid.instance_id[i] = buf[pos++];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* resolve received URL to url_res pointer */
|
||||
static char* esp_eddystone_resolve_url_scheme(const uint8_t *url_start, const uint8_t *url_end)
|
||||
{
|
||||
int pos = 0;
|
||||
static char url_buf[100] = {0};
|
||||
const uint8_t *p = url_start;
|
||||
|
||||
pos += sprintf(&url_buf[pos], "%s", eddystone_url_prefix[*p++]);
|
||||
|
||||
for (; p <= url_end; p++) {
|
||||
if (esp_eddystone_is_char_invalid((*p))) {
|
||||
pos += sprintf(&url_buf[pos], "%s", eddystone_url_encoding[*p]);
|
||||
} else {
|
||||
pos += sprintf(&url_buf[pos], "%c", *p);
|
||||
}
|
||||
}
|
||||
return url_buf;
|
||||
}
|
||||
|
||||
/************************** Eddystone-URL *************
|
||||
Frame Specification
|
||||
Byte offset Field Description
|
||||
0 Frame Type Value = 0x10
|
||||
1 TX Power Calibrated Tx power at 0 m
|
||||
2 URL Scheme Encoded Scheme Prefix
|
||||
3+ Encoded URL Length 1-17
|
||||
*******************************************************/
|
||||
/* decode and store received URL, the pointer url_res points to the resolved url */
|
||||
static esp_err_t esp_eddystone_url_received(const uint8_t* buf, uint8_t len, esp_eddystone_result_t* res)
|
||||
{
|
||||
char *url_res = NULL;
|
||||
uint8_t pos = 0;
|
||||
if(len-EDDYSTONE_URL_TX_POWER_LEN > EDDYSTONE_URL_MAX_LEN) {
|
||||
//ERROR:too long url
|
||||
return -1;
|
||||
}
|
||||
res->inform.url.tx_power = buf[pos++];
|
||||
url_res = esp_eddystone_resolve_url_scheme(buf+pos, buf+len-1);
|
||||
memcpy(&res->inform.url.url, url_res, strlen(url_res));
|
||||
res->inform.url.url[strlen(url_res)] = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************** eddystone-tlm ***************
|
||||
* Unencrypted TLM Frame Specification
|
||||
Byte offset Field Description
|
||||
0 Frame Type Value = 0x20
|
||||
1 Version TLM version, value = 0x00
|
||||
2 VBATT[0] Battery voltage, 1 mV/bit
|
||||
3 VBATT[1]
|
||||
4 TEMP[0] Beacon temperature
|
||||
5 TEMP[1]
|
||||
6 ADV_CNT[0] Advertising PDU count
|
||||
7 ADV_CNT[1]
|
||||
8 ADV_CNT[2]
|
||||
9 ADV_CNT[3]
|
||||
10 SEC_CNT[0] Time since power-on or reboot
|
||||
11 SEC_CNT[1]
|
||||
12 SEC_CNT[2]
|
||||
13 SEC_CNT[3]
|
||||
************************************************/
|
||||
/* decode and store received TLM */
|
||||
static esp_err_t esp_eddystone_tlm_received(const uint8_t* buf, uint8_t len, esp_eddystone_result_t* res)
|
||||
{
|
||||
uint8_t pos = 0;
|
||||
if(len > EDDYSTONE_TLM_DATA_LEN) {
|
||||
//ERROR:TLM too long
|
||||
return -1;
|
||||
}
|
||||
res->inform.tlm.version = buf[pos++];
|
||||
res->inform.tlm.battery_voltage = big_endian_read_16(buf, pos);
|
||||
pos += 2;
|
||||
uint16_t temp = big_endian_read_16(buf, pos);
|
||||
int8_t temp_integral = (int8_t)((temp >> 8) & 0xff);
|
||||
float temp_decimal = (temp & 0xff) / 256.0;
|
||||
res->inform.tlm.temperature = temp_integral + temp_decimal;
|
||||
pos += 2;
|
||||
res->inform.tlm.adv_count = big_endian_read_32(buf, pos);
|
||||
pos += 4;
|
||||
res->inform.tlm.time = big_endian_read_32(buf, pos);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static esp_err_t esp_eddystone_get_inform(const uint8_t* buf, uint8_t len, esp_eddystone_result_t* res)
|
||||
{
|
||||
static esp_err_t ret=-1;
|
||||
switch(res->common.frame_type)
|
||||
{
|
||||
case EDDYSTONE_FRAME_TYPE_UID: {
|
||||
ret = esp_eddystone_uid_received(buf, len, res);
|
||||
break;
|
||||
}
|
||||
case EDDYSTONE_FRAME_TYPE_URL: {
|
||||
ret = esp_eddystone_url_received(buf, len, res);
|
||||
break;
|
||||
}
|
||||
case EDDYSTONE_FRAME_TYPE_TLM: {
|
||||
ret = esp_eddystone_tlm_received(buf, len, res);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_eddystone_decode(const uint8_t* buf, uint8_t len, esp_eddystone_result_t* res)
|
||||
{
|
||||
if (len == 0 || buf == NULL || res == NULL) {
|
||||
return -1;
|
||||
}
|
||||
uint8_t pos=0;
|
||||
while(res->common.srv_data_type != EDDYSTONE_SERVICE_UUID)
|
||||
{
|
||||
pos++;
|
||||
if(pos >= len ) {
|
||||
return -1;
|
||||
}
|
||||
uint8_t ad_type = buf[pos++];
|
||||
switch(ad_type)
|
||||
{
|
||||
case ESP_BLE_AD_TYPE_FLAG: {
|
||||
res->common.flags = buf[pos++];
|
||||
break;
|
||||
}
|
||||
case ESP_BLE_AD_TYPE_16SRV_CMPL: {
|
||||
uint16_t uuid = little_endian_read_16(buf, pos);
|
||||
if(uuid != EDDYSTONE_SERVICE_UUID) {
|
||||
return -1;
|
||||
}
|
||||
res->common.srv_uuid = uuid;
|
||||
pos += 2;
|
||||
break;
|
||||
}
|
||||
case ESP_BLE_AD_TYPE_SERVICE_DATA: {
|
||||
uint16_t type = little_endian_read_16(buf, pos);
|
||||
pos += 2;
|
||||
uint8_t frame_type = buf[pos++];
|
||||
if(type != EDDYSTONE_SERVICE_UUID || !(frame_type == EDDYSTONE_FRAME_TYPE_UID || frame_type == EDDYSTONE_FRAME_TYPE_URL ||
|
||||
frame_type == EDDYSTONE_FRAME_TYPE_TLM)) {
|
||||
return -1;
|
||||
}
|
||||
res->common.srv_data_type = type;
|
||||
res->common.frame_type = frame_type;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return esp_eddystone_get_inform(buf+pos, len-pos, res);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __ESP_EDDYSTONE_API_H__
|
||||
#define __ESP_EDDYSTONE_API_H__
|
||||
|
||||
typedef struct {
|
||||
struct {
|
||||
uint8_t flags; /*<! AD flags data */
|
||||
uint16_t srv_uuid; /*<! complete list of 16-bit service uuid*/
|
||||
uint16_t srv_data_type; /*<! service data type */
|
||||
uint8_t frame_type; /*<! Eddystone UID, URL or TLM */
|
||||
} common;
|
||||
union {
|
||||
struct {
|
||||
/*<! Eddystone-UID */
|
||||
int8_t ranging_data; /*<! calibrated Tx power at 0m */
|
||||
uint8_t namespace_id[10];
|
||||
uint8_t instance_id[6];
|
||||
} uid;
|
||||
struct {
|
||||
/*<! Eddystone-URL */
|
||||
int8_t tx_power; /*<! calibrated Tx power at 0m */
|
||||
char url[EDDYSTONE_URL_MAX_LEN]; /*<! the decoded URL */
|
||||
} url;
|
||||
struct {
|
||||
/*<! Eddystone-TLM */
|
||||
uint8_t version; /*<! TLM version,0x00 for now */
|
||||
uint16_t battery_voltage; /*<! battery voltage in mV */
|
||||
float temperature; /*<! beacon temperature in degrees Celsius */
|
||||
uint32_t adv_count; /*<! adv pdu count since power-up */
|
||||
uint32_t time; /*<! time since power-up, a 0.1 second resolution counter */
|
||||
} tlm;
|
||||
} inform;
|
||||
} esp_eddystone_result_t;
|
||||
|
||||
/* utils */
|
||||
static inline uint16_t little_endian_read_16(const uint8_t *buffer, uint8_t pos)
|
||||
{
|
||||
return ((uint16_t)buffer[pos]) | (((uint16_t)buffer[(pos)+1]) << 8);
|
||||
}
|
||||
|
||||
static inline uint16_t big_endian_read_16(const uint8_t *buffer, uint8_t pos)
|
||||
{
|
||||
return (((uint16_t)buffer[pos]) << 8) | ((uint16_t)buffer[(pos)+1]);
|
||||
}
|
||||
|
||||
static inline uint32_t big_endian_read_32(const uint8_t *buffer, uint8_t pos)
|
||||
{
|
||||
return (((uint32_t)buffer[pos]) << 24) | (((uint32_t)buffer[(pos)+1]) << 16) | (((uint32_t)buffer[(pos)+2]) << 8) | ((uint32_t)buffer[(pos)+3]);
|
||||
}
|
||||
|
||||
/*
|
||||
* The esp eddystone API.
|
||||
* This function is called to decode eddystone information from adv_data.
|
||||
* The res points to the result struct.
|
||||
*
|
||||
*/
|
||||
esp_err_t esp_eddystone_decode(const uint8_t* buf, uint8_t len, esp_eddystone_result_t* res);
|
||||
|
||||
//bool esp_eddystone_is_eddystone_packet(.....);
|
||||
|
||||
#endif /* __ESP_EDDYSTONE_API_H__ */
|
||||
|
||||
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* This file is used for eddystone receiver.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "esp_bt.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_bt_defs.h"
|
||||
#include "esp_bt_main.h"
|
||||
#include "esp_gatt_defs.h"
|
||||
#include "esp_gattc_api.h"
|
||||
#include "esp_gap_ble_api.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
|
||||
#include "esp_eddystone_protocol.h"
|
||||
#include "esp_eddystone_api.h"
|
||||
|
||||
static const char* DEMO_TAG = "EDDYSTONE_DEMO";
|
||||
|
||||
/* declare static functions */
|
||||
static void esp_gap_cb(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t* param);
|
||||
static void esp_eddystone_show_inform(const esp_eddystone_result_t* res);
|
||||
|
||||
static esp_ble_scan_params_t ble_scan_params = {
|
||||
.scan_type = BLE_SCAN_TYPE_ACTIVE,
|
||||
.own_addr_type = BLE_ADDR_TYPE_PUBLIC,
|
||||
.scan_filter_policy = BLE_SCAN_FILTER_ALLOW_ALL,
|
||||
.scan_interval = 0x50,
|
||||
.scan_window = 0x30,
|
||||
.scan_duplicate = BLE_SCAN_DUPLICATE_DISABLE
|
||||
};
|
||||
|
||||
static void esp_eddystone_show_inform(const esp_eddystone_result_t* res)
|
||||
{
|
||||
switch(res->common.frame_type)
|
||||
{
|
||||
case EDDYSTONE_FRAME_TYPE_UID: {
|
||||
ESP_LOGI(DEMO_TAG, "Eddystone UID inform:");
|
||||
ESP_LOGI(DEMO_TAG, "Measured power(RSSI at 0m distance):%d dbm", res->inform.uid.ranging_data);
|
||||
ESP_LOGI(DEMO_TAG, "EDDYSTONE_DEMO: Namespace ID:0x");
|
||||
esp_log_buffer_hex(DEMO_TAG, res->inform.uid.namespace_id, 10);
|
||||
ESP_LOGI(DEMO_TAG, "EDDYSTONE_DEMO: Instance ID:0x");
|
||||
esp_log_buffer_hex(DEMO_TAG, res->inform.uid.instance_id, 6);
|
||||
break;
|
||||
}
|
||||
case EDDYSTONE_FRAME_TYPE_URL: {
|
||||
ESP_LOGI(DEMO_TAG, "Eddystone URL inform:");
|
||||
ESP_LOGI(DEMO_TAG, "Measured power(RSSI at 0m distance):%d dbm", res->inform.url.tx_power);
|
||||
ESP_LOGI(DEMO_TAG, "URL: %s", res->inform.url.url);
|
||||
break;
|
||||
}
|
||||
case EDDYSTONE_FRAME_TYPE_TLM: {
|
||||
ESP_LOGI(DEMO_TAG, "Eddystone TLM inform:");
|
||||
ESP_LOGI(DEMO_TAG, "version: %d", res->inform.tlm.version);
|
||||
ESP_LOGI(DEMO_TAG, "battery voltage: %d mV", res->inform.tlm.battery_voltage);
|
||||
ESP_LOGI(DEMO_TAG, "beacon temperature in degrees Celsius: %6.1f", res->inform.tlm.temperature);
|
||||
ESP_LOGI(DEMO_TAG, "adv pdu count since power-up: %d", res->inform.tlm.adv_count);
|
||||
ESP_LOGI(DEMO_TAG, "time since power-up: %d s", (res->inform.tlm.time)/10);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void esp_gap_cb(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t* param)
|
||||
{
|
||||
esp_err_t err;
|
||||
|
||||
switch(event)
|
||||
{
|
||||
case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT: {
|
||||
uint32_t duration = 0;
|
||||
esp_ble_gap_start_scanning(duration);
|
||||
break;
|
||||
}
|
||||
case ESP_GAP_BLE_SCAN_START_COMPLETE_EVT: {
|
||||
if((err = param->scan_start_cmpl.status) != ESP_BT_STATUS_SUCCESS) {
|
||||
ESP_LOGE(DEMO_TAG,"Scan start failed: %s", esp_err_to_name(err));
|
||||
}
|
||||
else {
|
||||
ESP_LOGI(DEMO_TAG,"Start scanning...");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ESP_GAP_BLE_SCAN_RESULT_EVT: {
|
||||
esp_ble_gap_cb_param_t* scan_result = (esp_ble_gap_cb_param_t*)param;
|
||||
switch(scan_result->scan_rst.search_evt)
|
||||
{
|
||||
case ESP_GAP_SEARCH_INQ_RES_EVT: {
|
||||
esp_eddystone_result_t eddystone_res;
|
||||
memset(&eddystone_res, 0, sizeof(eddystone_res));
|
||||
esp_err_t ret = esp_eddystone_decode(scan_result->scan_rst.ble_adv, scan_result->scan_rst.adv_data_len, &eddystone_res);
|
||||
if (ret) {
|
||||
// error:The received data is not an eddystone frame packet or a correct eddystone frame packet.
|
||||
// just return
|
||||
return;
|
||||
} else {
|
||||
// The received adv data is a correct eddystone frame packet.
|
||||
// Here, we get the eddystone infomation in eddystone_res, we can use the data in res to do other things.
|
||||
// For example, just print them:
|
||||
ESP_LOGI(DEMO_TAG, "--------Eddystone Found----------");
|
||||
esp_log_buffer_hex("EDDYSTONE_DEMO: Device address:", scan_result->scan_rst.bda, ESP_BD_ADDR_LEN);
|
||||
ESP_LOGI(DEMO_TAG, "RSSI of packet:%d dbm", scan_result->scan_rst.rssi);
|
||||
esp_eddystone_show_inform(&eddystone_res);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT:{
|
||||
if((err = param->scan_stop_cmpl.status) != ESP_BT_STATUS_SUCCESS) {
|
||||
ESP_LOGE(DEMO_TAG,"Scan stop failed: %s", esp_err_to_name(err));
|
||||
}
|
||||
else {
|
||||
ESP_LOGI(DEMO_TAG,"Stop scan successfully");
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void esp_eddystone_appRegister(void)
|
||||
{
|
||||
esp_err_t status;
|
||||
|
||||
ESP_LOGI(DEMO_TAG,"Register callback");
|
||||
|
||||
/*<! register the scan callback function to the gap module */
|
||||
if((status = esp_ble_gap_register_callback(esp_gap_cb)) != ESP_OK) {
|
||||
ESP_LOGE(DEMO_TAG,"gap register error: %s", esp_err_to_name(status));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void esp_eddystone_init(void)
|
||||
{
|
||||
esp_bluedroid_init();
|
||||
esp_bluedroid_enable();
|
||||
esp_eddystone_appRegister();
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
ESP_ERROR_CHECK(nvs_flash_init());
|
||||
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();
|
||||
esp_bt_controller_init(&bt_cfg);
|
||||
esp_bt_controller_enable(ESP_BT_MODE_BLE);
|
||||
|
||||
esp_eddystone_init();
|
||||
|
||||
/*<! set scan parameters */
|
||||
esp_ble_gap_set_scan_params(&ble_scan_params);
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#ifndef __ESP_EDDYSTONE_PROTOCOL_H__
|
||||
#define __ESP_EDDYSTONE_PROTOCOL_H__
|
||||
|
||||
#include "stdbool.h"
|
||||
#include "stdint.h"
|
||||
|
||||
/* Eddystone definitions */
|
||||
#define EDDYSTONE_SERVICE_UUID 0xFEAA
|
||||
|
||||
#define EDDYSTONE_FRAME_TYPE_UID 0x00
|
||||
#define EDDYSTONE_FRAME_TYPE_URL 0x10
|
||||
#define EDDYSTONE_FRAME_TYPE_TLM 0x20
|
||||
#define EDDYSTONE_FRAME_TYPE_EID 0x30
|
||||
//UID
|
||||
#define EDDYSTONE_UID_RANG_DATA_LEN 1
|
||||
#define EDDYSTONE_UID_NAMESPACE_LEN 10
|
||||
#define EDDYSTONE_UID_INSTANCE_LEN 6
|
||||
#define EDDYSTONE_UID_RFU_LEN 2
|
||||
#define EDDYSTONE_UID_DATA_LEN (EDDYSTONE_UID_RANG_DATA_LEN + EDDYSTONE_UID_NAMESPACE_LEN + EDDYSTONE_UID_INSTANCE_LEN)
|
||||
//TLM
|
||||
#define EDDYSTONE_TLM_VERSION_LEN 1
|
||||
#define EDDYSTONE_TLM_BATTERY_VOLTAGE_LEN 2
|
||||
#define EDDYSTONE_TLM_TEMPERATURE_LEN 2
|
||||
#define EDDYSTONE_TLM_ADV_COUNT_LEN 4
|
||||
#define EDDYSTONE_TLM_TIME_LEN 4
|
||||
#define EDDYSTONE_TLM_DATA_LEN (EDDYSTONE_TLM_VERSION_LEN + EDDYSTONE_TLM_BATTERY_VOLTAGE_LEN + \
|
||||
EDDYSTONE_TLM_TEMPERATURE_LEN + EDDYSTONE_TLM_ADV_COUNT_LEN + EDDYSTONE_TLM_TIME_LEN)
|
||||
//URL
|
||||
#define EDDYSTONE_URL_SCHEME_LEN 1
|
||||
#define EDDYSTONE_URL_ENCODED_MAX_LEN 17
|
||||
#define EDDYSTONE_URL_MAX_LEN (EDDYSTONE_URL_SCHEME_LEN + EDDYSTONE_URL_ENCODED_MAX_LEN)
|
||||
#define EDDYSTONE_URL_TX_POWER_LEN 1
|
||||
|
||||
|
||||
/* Eddystone UID frame */
|
||||
typedef struct {
|
||||
int8_t ranging_data; /*<! calibrated Tx power at 0m */
|
||||
uint8_t namespace_id[10];
|
||||
uint8_t instance_id[6];
|
||||
uint8_t reserved[2];
|
||||
} __attribute__((packed))esp_eddystone_uid_t;
|
||||
|
||||
/* Eddystone URL frame */
|
||||
typedef struct {
|
||||
int8_t tx_power; /*<! calibrated Tx power at 0m */
|
||||
uint8_t url_scheme; /*<! encoded scheme prefix */
|
||||
uint8_t encoded_url[0]; /*<! length 1-17 */
|
||||
} __attribute__((packed))esp_eddystone_url_t;
|
||||
|
||||
/* Eddystone TLM frame */
|
||||
typedef struct {
|
||||
uint8_t version; /*<! TLM version,0x00 for now */
|
||||
uint16_t batt; /*<! battery voltage, 1mV/bit */
|
||||
uint16_t temp; /*<! beacon temperature */
|
||||
uint32_t adv_count; /*<! adv pdu count since power-on or reboot */
|
||||
uint32_t time; /*<! time sence power-on or reboot, a 0.1 second resolution counter */
|
||||
} __attribute__((packed)) esp_eddystone_tlm_t;
|
||||
|
||||
/* AD Structure of flags */
|
||||
typedef struct {
|
||||
uint8_t len;
|
||||
uint8_t type;
|
||||
uint8_t flags;
|
||||
} __attribute__((packed)) esp_eddystone_flags_t;
|
||||
|
||||
/* AD Structure of complete 16-bit service uuid */
|
||||
typedef struct {
|
||||
uint8_t len;
|
||||
uint8_t type;
|
||||
uint16_t uuid; /*<! complete list of 16-bit service UUIDs data type value */
|
||||
} __attribute__((packed)) esp_eddystone_uuid_t;
|
||||
|
||||
/* AD Structure of eddystone frame*/
|
||||
typedef struct {
|
||||
uint8_t len; /*<! length of eddystone data */
|
||||
uint8_t type; /*<! service data type,must be 0x16 */
|
||||
uint16_t uuid; /*<! 16-bit eddystone uuid */
|
||||
uint8_t frame_type;
|
||||
union {
|
||||
esp_eddystone_uid_t uid;
|
||||
esp_eddystone_url_t url;
|
||||
esp_eddystone_tlm_t tlm;
|
||||
} u[0];
|
||||
} __attribute__((packed)) esp_eddystone_frame_t;
|
||||
|
||||
/* eddystone packet type */
|
||||
typedef struct {
|
||||
esp_eddystone_flags_t flags;
|
||||
esp_eddystone_uuid_t uuid;
|
||||
esp_eddystone_frame_t frame;
|
||||
} __attribute__((packed)) esp_eddystone_packet_t;
|
||||
|
||||
/*
|
||||
* URLs are written only with the graphic printable characters of the US-ASCII coded character set.
|
||||
* The octets 00-20 and 7F-FF hexadecimal are not used.
|
||||
* See “Excluded US-ASCII Characters” in RFC 2936.
|
||||
*
|
||||
*/
|
||||
static inline bool esp_eddystone_is_char_invalid(int ch)
|
||||
{
|
||||
return (ch >= 0x00 && ch <= 0x20) || (ch >= 0x7f && ch <= 0xff);
|
||||
}
|
||||
|
||||
#endif /* __ESP_EDDYSTONE_PROTOCOL_H__ */
|
||||
@@ -0,0 +1,6 @@
|
||||
# Override some defaults so BT stack is enabled
|
||||
# and WiFi disabled by default in this example
|
||||
CONFIG_BT_ENABLED=y
|
||||
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
|
||||
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
|
||||
CONFIG_BTDM_CTRL_MODE_BTDM=n
|
||||
Reference in New Issue
Block a user