ibeacon implementation
This commit is contained in:
parent
64564023ca
commit
f83fd97ca8
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
*
|
||||||
|
* This file is for iBeacon APIs. It supports both iBeacon encode and decode.
|
||||||
|
*
|
||||||
|
* iBeacon is a trademark of Apple Inc. Before building devices which use iBeacon technology,
|
||||||
|
* visit https://developer.apple.com/ibeacon/ to obtain a license.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "esp_gap_ble_api.h"
|
||||||
|
#include "esp_ibeacon_api.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
const uint8_t uuid_zeros[ESP_UUID_LEN_128] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||||
|
|
||||||
|
/* For iBeacon packet format, please refer to Apple "Proximity Beacon Specification" doc */
|
||||||
|
/* Constant part of iBeacon data */
|
||||||
|
esp_ble_ibeacon_head_t ibeacon_common_head = {
|
||||||
|
.flags = {0x02, 0x01, 0x06},
|
||||||
|
.length = 0x1A,
|
||||||
|
.type = 0xFF,
|
||||||
|
.company_id = 0x004C,
|
||||||
|
.beacon_type = 0x1502
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Vendor part of iBeacon data*/
|
||||||
|
esp_ble_ibeacon_vendor_t vendor_config = {
|
||||||
|
.proximity_uuid = ESP_UUID,
|
||||||
|
.major = ENDIAN_CHANGE_U16(ESP_MAJOR), //Major=ESP_MAJOR
|
||||||
|
.minor = ENDIAN_CHANGE_U16(ESP_MINOR), //Minor=ESP_MINOR
|
||||||
|
.measured_power = static_cast<int8_t>(0xC5)
|
||||||
|
};
|
||||||
|
|
||||||
|
bool esp_ble_is_ibeacon_packet (uint8_t *adv_data, uint8_t adv_data_len){
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
if ((adv_data != NULL) && (adv_data_len == 0x1E)){
|
||||||
|
if (!memcmp(adv_data, (uint8_t*)&ibeacon_common_head, sizeof(ibeacon_common_head))){
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_ble_config_ibeacon_data (esp_ble_ibeacon_vendor_t *vendor_config, esp_ble_ibeacon_t *ibeacon_adv_data){
|
||||||
|
if ((vendor_config == NULL) || (ibeacon_adv_data == NULL) || (!memcmp(vendor_config->proximity_uuid, uuid_zeros, sizeof(uuid_zeros)))){
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(&ibeacon_adv_data->ibeacon_head, &ibeacon_common_head, sizeof(esp_ble_ibeacon_head_t));
|
||||||
|
memcpy(&ibeacon_adv_data->ibeacon_vendor, vendor_config, sizeof(esp_ble_ibeacon_vendor_t));
|
||||||
|
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
*
|
||||||
|
* This file is for iBeacon definitions. It supports both iBeacon sender and receiver
|
||||||
|
* which is distinguished by macros IBEACON_SENDER and IBEACON_RECEIVER,
|
||||||
|
*
|
||||||
|
* iBeacon is a trademark of Apple Inc. Before building devices which use iBeacon technology,
|
||||||
|
* visit https://developer.apple.com/ibeacon/ to obtain a license.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "esp_gap_ble_api.h"
|
||||||
|
#include "esp_gattc_api.h"
|
||||||
|
|
||||||
|
#define IBEACON_SENDER 0
|
||||||
|
#define IBEACON_RECEIVER 1
|
||||||
|
#define IBEACON_MODE CONFIG_IBEACON_MODE
|
||||||
|
|
||||||
|
/* Major and Minor part are stored in big endian mode in iBeacon packet,
|
||||||
|
* need to use this macro to transfer while creating or processing
|
||||||
|
* iBeacon data */
|
||||||
|
#define ENDIAN_CHANGE_U16(x) ((((x)&0xFF00)>>8) + (((x)&0xFF)<<8))
|
||||||
|
|
||||||
|
/* Espressif WeChat official account can be found using WeChat "Yao Yi Yao Zhou Bian",
|
||||||
|
* if device advertises using ESP defined UUID.
|
||||||
|
* Please refer to http://zb.weixin.qq.com for further information. */
|
||||||
|
#define ESP_UUID {0xFD, 0xA5, 0x06, 0x93, 0xA4, 0xE2, 0x4F, 0xB1, 0xAF, 0xCF, 0xC6, 0xEB, 0x07, 0x64, 0x78, 0x25}
|
||||||
|
#define ESP_MAJOR 10167
|
||||||
|
#define ESP_MINOR 61958
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t flags[3];
|
||||||
|
uint8_t length;
|
||||||
|
uint8_t type;
|
||||||
|
uint16_t company_id;
|
||||||
|
uint16_t beacon_type;
|
||||||
|
}__attribute__((packed)) esp_ble_ibeacon_head_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t proximity_uuid[16];
|
||||||
|
uint16_t major;
|
||||||
|
uint16_t minor;
|
||||||
|
int8_t measured_power;
|
||||||
|
}__attribute__((packed)) esp_ble_ibeacon_vendor_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
esp_ble_ibeacon_head_t ibeacon_head;
|
||||||
|
esp_ble_ibeacon_vendor_t ibeacon_vendor;
|
||||||
|
}__attribute__((packed)) esp_ble_ibeacon_t;
|
||||||
|
|
||||||
|
|
||||||
|
/* For iBeacon packet format, please refer to Apple "Proximity Beacon Specification" doc */
|
||||||
|
/* Constant part of iBeacon data */
|
||||||
|
extern esp_ble_ibeacon_head_t ibeacon_common_head;
|
||||||
|
|
||||||
|
bool esp_ble_is_ibeacon_packet (uint8_t *adv_data, uint8_t adv_data_len);
|
||||||
|
|
||||||
|
esp_err_t esp_ble_config_ibeacon_data (esp_ble_ibeacon_vendor_t *vendor_config, esp_ble_ibeacon_t *ibeacon_adv_data);
|
|
@ -0,0 +1,6 @@
|
||||||
|
# Name, Type, SubType, Offset, Size, Flags
|
||||||
|
nvs, data, nvs, 0x9000, 0x5000,
|
||||||
|
otadata, data, ota, 0xe000, 0x2000,
|
||||||
|
app0, app, factory, 0x10000, 0x1E0000,
|
||||||
|
app1, app, ota_0, 0x1F0000, 0x1E0000,
|
||||||
|
spiffs, data, spiffs, 0x3D0000, 0x20000,
|
|
|
@ -15,6 +15,7 @@ board = wt32-eth01
|
||||||
framework = arduino
|
framework = arduino
|
||||||
lib_deps = siwats/ESPMegaPROR3@^2.9.4
|
lib_deps = siwats/ESPMegaPROR3@^2.9.4
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
|
board_build.partitions = partitions_custom.csv
|
||||||
build_flags = -DCORE_DEBUG_LEVEL=0 -DSW_VERSION='"cud-3.0.5-duct"' -DBOARD_MODEL='"ESPMegaPRO R3.3c"' -DAC_TYPE=AC_TYPE_DUCTED
|
build_flags = -DCORE_DEBUG_LEVEL=0 -DSW_VERSION='"cud-3.0.5-duct"' -DBOARD_MODEL='"ESPMegaPRO R3.3c"' -DAC_TYPE=AC_TYPE_DUCTED
|
||||||
|
|
||||||
; Ceiling A/C Variant (and newer ducted models)
|
; Ceiling A/C Variant (and newer ducted models)
|
||||||
|
@ -24,4 +25,5 @@ board = wt32-eth01
|
||||||
framework = arduino
|
framework = arduino
|
||||||
lib_deps = siwats/ESPMegaPROR3@^2.9.4
|
lib_deps = siwats/ESPMegaPROR3@^2.9.4
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
|
board_build.partitions = partitions_custom.csv
|
||||||
build_flags = -DCORE_DEBUG_LEVEL=0 -DSW_VERSION='"cud-3.0.5-ceiling"' -DBOARD_MODEL='"ESPMegaPRO R3.3c"' -DAC_TYPE=AC_TYPE_CEILING
|
build_flags = -DCORE_DEBUG_LEVEL=0 -DSW_VERSION='"cud-3.0.5-ceiling"' -DBOARD_MODEL='"ESPMegaPRO R3.3c"' -DAC_TYPE=AC_TYPE_CEILING
|
|
@ -25,6 +25,14 @@
|
||||||
#define MOSQUITO_ZAPPER_PIN 8
|
#define MOSQUITO_ZAPPER_PIN 8
|
||||||
// There are one power relay for the socket
|
// There are one power relay for the socket
|
||||||
#define SOCKET_CONTACTOR_PIN 9
|
#define SOCKET_CONTACTOR_PIN 9
|
||||||
|
|
||||||
|
/***********************************************
|
||||||
|
* iBeacon Settings *
|
||||||
|
***********************************************/
|
||||||
|
#define ESP_MAJOR 10167
|
||||||
|
#define ESP_MINOR 61958
|
||||||
|
// UUID is now dynamically generated per device from MAC address
|
||||||
|
|
||||||
/***********************************************
|
/***********************************************
|
||||||
* Air Conditioner *
|
* Air Conditioner *
|
||||||
***********************************************/
|
***********************************************/
|
||||||
|
@ -88,4 +96,4 @@
|
||||||
#define AQI_REQUEST_TOPIC "/iqair/request"
|
#define AQI_REQUEST_TOPIC "/iqair/request"
|
||||||
#define AC_LOCK_RELATIVE_TOPIC "/ac/lock"
|
#define AC_LOCK_RELATIVE_TOPIC "/ac/lock"
|
||||||
#define AC_TEMP_LOWER_BOUND_RELATIVE_TOPIC "/ac/temp_bound/lower"
|
#define AC_TEMP_LOWER_BOUND_RELATIVE_TOPIC "/ac/temp_bound/lower"
|
||||||
#define AC_TEMP_UPPER_BOUND_RELATIVE_TOPIC "/ac/temp_bound/upper"
|
#define AC_TEMP_UPPER_BOUND_RELATIVE_TOPIC "/ac/temp_bound/upper"
|
89
src/main.cpp
89
src/main.cpp
|
@ -36,10 +36,46 @@ CUDDisplay cudDisplay = CUDDisplay(&cud_display_conf);
|
||||||
ESPMegaDisplayOTA cudDisplayOTA = ESPMegaDisplayOTA();
|
ESPMegaDisplayOTA cudDisplayOTA = ESPMegaDisplayOTA();
|
||||||
ESPMegaDisplayOTA internalDisplayOTA = ESPMegaDisplayOTA();
|
ESPMegaDisplayOTA internalDisplayOTA = ESPMegaDisplayOTA();
|
||||||
|
|
||||||
|
// iBeacon configuration
|
||||||
|
static esp_ble_adv_params_t ble_adv_params = {
|
||||||
|
.adv_int_min = 0x20,
|
||||||
|
.adv_int_max = 0x40,
|
||||||
|
.adv_type = ADV_TYPE_NONCONN_IND,
|
||||||
|
.own_addr_type = BLE_ADDR_TYPE_PUBLIC,
|
||||||
|
.channel_map = ADV_CHNL_ALL,
|
||||||
|
.adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY,
|
||||||
|
};
|
||||||
|
|
||||||
|
esp_ble_ibeacon_vendor_t vendor_config_custom;
|
||||||
|
|
||||||
/************************************************
|
/************************************************
|
||||||
* End of Global Variables *
|
* End of Global Variables *
|
||||||
************************************************/
|
************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a unique UUID based on ESP32's chip ID
|
||||||
|
* @param uuid Output buffer for the UUID (16 bytes)
|
||||||
|
*/
|
||||||
|
void generate_unique_uuid(uint8_t *uuid) {
|
||||||
|
// Get ESP32 chip ID (6 bytes)
|
||||||
|
uint8_t mac[6];
|
||||||
|
esp_efuse_mac_get_default(mac);
|
||||||
|
|
||||||
|
// Use a fixed prefix (8 bytes)
|
||||||
|
static const uint8_t prefix[8] = {0xFD, 0xA5, 0x06, 0x93, 0xA4, 0xE2, 0x4F, 0xB1};
|
||||||
|
|
||||||
|
// Copy prefix to first 8 bytes of UUID
|
||||||
|
memcpy(uuid, prefix, 8);
|
||||||
|
|
||||||
|
// Copy MAC address to next 6 bytes
|
||||||
|
memcpy(uuid + 8, mac, 6);
|
||||||
|
|
||||||
|
// Fill the remaining 2 bytes with a hash of the MAC
|
||||||
|
uint16_t hash = mac[0] + (mac[1] << 8) + mac[2] + (mac[3] << 8) + mac[4] + (mac[5] << 8);
|
||||||
|
uuid[14] = hash & 0xFF;
|
||||||
|
uuid[15] = (hash >> 8) & 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
void setup()
|
void setup()
|
||||||
{
|
{
|
||||||
// Initialize both displayports
|
// Initialize both displayports
|
||||||
|
@ -122,6 +158,30 @@ void setup()
|
||||||
espmega.iot->registerMqttCallback(handle_mqtt_message);
|
espmega.iot->registerMqttCallback(handle_mqtt_message);
|
||||||
cudDisplayOTA.begin("/cuddisp", &cudDisplay, espmega.webServer);
|
cudDisplayOTA.begin("/cuddisp", &cudDisplay, espmega.webServer);
|
||||||
internalDisplayOTA.begin("/intdisp", espmega.display, espmega.webServer);
|
internalDisplayOTA.begin("/intdisp", espmega.display, espmega.webServer);
|
||||||
|
|
||||||
|
// Initialize iBeacon with unique UUID
|
||||||
|
ESP_LOGV("CUD IoT OS", "Initializing iBeacon");
|
||||||
|
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_bluedroid_init();
|
||||||
|
esp_bluedroid_enable();
|
||||||
|
esp_ble_gap_register_callback(esp_gap_cb);
|
||||||
|
|
||||||
|
// Generate unique UUID for this device
|
||||||
|
uint8_t uuid[16];
|
||||||
|
generate_unique_uuid(uuid);
|
||||||
|
|
||||||
|
// Configure iBeacon with unique UUID
|
||||||
|
memcpy(vendor_config_custom.proximity_uuid, uuid, sizeof(uuid));
|
||||||
|
vendor_config_custom.major = ENDIAN_CHANGE_U16(ESP_MAJOR);
|
||||||
|
vendor_config_custom.minor = ENDIAN_CHANGE_U16(ESP_MINOR);
|
||||||
|
vendor_config_custom.measured_power = static_cast<int8_t>(0xC5);
|
||||||
|
|
||||||
|
esp_ble_ibeacon_t ibeacon_adv_data;
|
||||||
|
esp_ble_config_ibeacon_data(&vendor_config_custom, &ibeacon_adv_data);
|
||||||
|
esp_ble_gap_config_adv_data_raw((uint8_t *)&ibeacon_adv_data, sizeof(ibeacon_adv_data));
|
||||||
|
|
||||||
#ifdef TAMPER_DETECTION
|
#ifdef TAMPER_DETECTION
|
||||||
espmega.display->registerPageChangeCallback(pageChangeCallback);
|
espmega.display->registerPageChangeCallback(pageChangeCallback);
|
||||||
espmega.display->registerTouchCallback(touchCallback);
|
espmega.display->registerTouchCallback(touchCallback);
|
||||||
|
@ -156,6 +216,35 @@ void handle_mqtt_message(char *topic, char *payload)
|
||||||
ESP_LOGD("CUD IoT OS", "MQTT Message Received: %s, %s", topic, payload);
|
ESP_LOGD("CUD IoT OS", "MQTT Message Received: %s, %s", topic, payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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_ADV_DATA_RAW_SET_COMPLETE_EVT: {
|
||||||
|
esp_ble_gap_start_advertising(&ble_adv_params);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ESP_GAP_BLE_ADV_START_COMPLETE_EVT:
|
||||||
|
// adv start complete event to indicate adv start successfully or failed
|
||||||
|
if ((err = param->adv_start_cmpl.status) != ESP_BT_STATUS_SUCCESS) {
|
||||||
|
ESP_LOGE("iBeacon", "Advertising start failed, error %s", esp_err_to_name(err));
|
||||||
|
} else {
|
||||||
|
ESP_LOGI("iBeacon", "Advertising start successfully");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT:
|
||||||
|
if ((err = param->adv_stop_cmpl.status) != ESP_BT_STATUS_SUCCESS) {
|
||||||
|
ESP_LOGE("iBeacon", "Advertising stop failed, error %s", esp_err_to_name(err));
|
||||||
|
} else {
|
||||||
|
ESP_LOGI("iBeacon", "Advertising stop successfully");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef TAMPER_DETECTION
|
#ifdef TAMPER_DETECTION
|
||||||
void pageChangeCallback(uint8_t page)
|
void pageChangeCallback(uint8_t page)
|
||||||
{
|
{
|
||||||
|
|
|
@ -14,6 +14,10 @@
|
||||||
#include <ETH.h>
|
#include <ETH.h>
|
||||||
#include <RemoteVariable.hpp>
|
#include <RemoteVariable.hpp>
|
||||||
#include <ESPMegaDisplayOTA.hpp>
|
#include <ESPMegaDisplayOTA.hpp>
|
||||||
|
#include <esp_gap_ble_api.h>
|
||||||
|
#include <esp_bt_main.h>
|
||||||
|
#include <esp_bt.h>
|
||||||
|
#include <esp_ibeacon_api.hpp>
|
||||||
#include "lcd_elements.hpp"
|
#include "lcd_elements.hpp"
|
||||||
#include "ir_codes.hpp"
|
#include "ir_codes.hpp"
|
||||||
#include "display.hpp"
|
#include "display.hpp"
|
||||||
|
@ -27,6 +31,7 @@ void loop();
|
||||||
void send_stop_bytes(HardwareSerial &uart);
|
void send_stop_bytes(HardwareSerial &uart);
|
||||||
void handle_input_change(uint8_t pin, bool state);
|
void handle_input_change(uint8_t pin, bool state);
|
||||||
void handle_mqtt_message(char *topic, char *payload);
|
void handle_mqtt_message(char *topic, char *payload);
|
||||||
|
static void esp_gap_cb(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param);
|
||||||
|
|
||||||
#ifdef TAMPER_DETECTION
|
#ifdef TAMPER_DETECTION
|
||||||
void pageChangeCallback(uint8_t page);
|
void pageChangeCallback(uint8_t page);
|
||||||
|
|
Loading…
Reference in New Issue