kopia lustrzana https://github.com/espressif/esp-idf
Merge branch 'feature/btdm_eddystone' into 'master'
component/bt: Add eddystone demo See merge request !1076pull/1128/head
commit
276034354e
|
@ -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,22 @@
|
|||
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,4 @@
|
|||
#
|
||||
# "main" pseudo-component makefile.
|
||||
#
|
||||
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
|
|
@ -0,0 +1,203 @@
|
|||
// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// 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.
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* 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"
|
||||
};
|
||||
|
||||
/* 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;
|
||||
if(len+4 != EDDYSTONE_UID_FRAME_LEN) {
|
||||
//ERROR:uid len wrong
|
||||
return -1;
|
||||
}
|
||||
res->inform.uid.ranging_data = buf[pos++];
|
||||
for(int i=0; i<10; i++) {
|
||||
res->inform.uid.namespace_id[i] = buf[pos++];
|
||||
}
|
||||
for(int i=0; i<6; 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;
|
||||
}
|
||||
|
||||
/* 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-1 > 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));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 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+4 > EDDYSTONE_TLM_FRAME_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)
|
||||
{
|
||||
static uint8_t pos=0;
|
||||
while(res->common.srv_data_type != EDDYSTONE_SERVICE_UUID)
|
||||
{
|
||||
pos++;
|
||||
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,76 @@
|
|||
// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// 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 __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,177 @@
|
|||
// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// 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.
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* This file is used for eddystone receiver.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "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
|
||||
};
|
||||
|
||||
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);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void esp_gap_cb(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t* param)
|
||||
{
|
||||
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(param->scan_start_cmpl.status != ESP_BT_STATUS_SUCCESS) {
|
||||
ESP_LOGE(DEMO_TAG,"Scan start failed");
|
||||
}
|
||||
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(param->scan_stop_cmpl.status != ESP_BT_STATUS_SUCCESS) {
|
||||
ESP_LOGE(DEMO_TAG,"Scan stop failed");
|
||||
}
|
||||
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,error code = %x",status);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void esp_eddystone_init(void)
|
||||
{
|
||||
esp_bluedroid_init();
|
||||
esp_bluedroid_enable();
|
||||
esp_eddystone_appRegister();
|
||||
}
|
||||
|
||||
void app_main()
|
||||
{
|
||||
ESP_ERROR_CHECK(nvs_flash_init());
|
||||
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_BTDM);
|
||||
|
||||
esp_eddystone_init();
|
||||
|
||||
/*<! set scan parameters */
|
||||
esp_ble_gap_set_scan_params(&ble_scan_params);
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// 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 __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
|
||||
|
||||
#define EDDYSTONE_UID_FRAME_LEN 0x17
|
||||
#define EDDYSTONE_TLM_FRAME_LEN 0x11
|
||||
#define EDDYSTONE_URL_MAX_LEN 18
|
||||
|
||||
|
||||
/* 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,4 @@
|
|||
# Override some defaults so BT stack is enabled
|
||||
# and WiFi disabled by default in this example
|
||||
CONFIG_BT_ENABLED=y
|
||||
CONFIG_WIFI_ENABLED=n
|
Ładowanie…
Reference in New Issue