Compare commits
21 Commits
e73dfd0be0
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
| a97d04e90c | |||
| ad6c6f805f | |||
| fd2c98033c | |||
| 496f52a39e | |||
| 59b083d7c1 | |||
| 2975c2cb45 | |||
| 109f09eea0 | |||
| 8069460f15 | |||
| f68889e72e | |||
| b018bbd516 | |||
| 69b5b8adbd | |||
| cb2d1168ca | |||
| af50698084 | |||
| 27f7025987 | |||
| cbcc5ac273 | |||
| 80ca57758a | |||
| 52a75c35a3 | |||
| 637a25bcee | |||
| ec2f0ae7b9 | |||
| be74a1f1e1 | |||
| 7346346920 |
@@ -0,0 +1,11 @@
|
|||||||
|
build/
|
||||||
|
sdkconfig
|
||||||
|
*.local
|
||||||
|
*.tmp
|
||||||
|
*.old
|
||||||
|
*.bak*
|
||||||
|
*.csv
|
||||||
|
*~
|
||||||
|
*.vscode
|
||||||
|
dependencies.lock
|
||||||
|
secrets.json
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
[submodule "GoogleFindMyTools"]
|
||||||
|
path = GoogleFindMyTools
|
||||||
|
url = https://github.com/leonboe1/GoogleFindMyTools.git
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
# For more information about build system see
|
||||||
|
# https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html
|
||||||
|
# The following five 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)
|
||||||
|
# trim to only enable and only enable and include dependancies and nothing else
|
||||||
|
idf_build_set_property(MINIMAL_BUILD ON)
|
||||||
|
project(PrincessPiTracker)
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
# Notes
|
||||||
|
* using esp-idf v5.5.1 for testin
|
||||||
|
## Wireshark
|
||||||
|
* filter for finding these adverts by mac is `btle.advertising_address == xx:xx:xx:xx:xx || btle.scanning_address == xx:xx:xx:xx:xx || btle.target_address == xx:xx:xx:xx:xx`
|
||||||
|
* filter for narrowing to without mac is `(btcommon.eir_ad.entry.type == 0x01) && (btle.advertising_header == 0x2506)`
|
||||||
|
## Voltage reading
|
||||||
|

|
||||||
|
1. 2x 200k resistor
|
||||||
|
1. bat\+ -> adc0
|
||||||
|
2. bat\- -> adc0
|
||||||
|
2. [adc oneshot read esp-idf](https://github.com/espressif/esp-idf/tree/v5.5.1/examples/peripherals/adc/oneshot_read)
|
||||||
|
3. [battery usage Xiao C6](https://wiki.seeedstudio.com/xiao_esp32c6_getting_started/#battery-usage)
|
||||||
|
4. [battery usage Xiao C3](https://wiki.seeedstudio.com/XIAO_ESP32C3_Getting_Started/#battery-usage)
|
||||||
|
* max usable interval 4000ms seems like
|
||||||
|
* 2000ms seems moar stable? idk
|
||||||
|
# Scratch
|
||||||
|
## test protocol
|
||||||
|
rebuildfull
|
||||||
|
erase flash
|
||||||
|
set setgings
|
||||||
|
flash
|
||||||
|
plug into usb-c meter
|
||||||
|
measure power usage over 10 minutes (600 seconds)
|
||||||
|
export to excel
|
||||||
|
name like:
|
||||||
|
(progress markers: b built, f flashed, m measuring, l logged, d done)
|
||||||
|
bfmld burst-60s-200ms-10ms-3b-nousb-ant-109f09e-
|
||||||
|
bfmld normal-10.230s-10ms-nousb-ant-109f09e-
|
||||||
|
bfmld normal-10.230s-10ms-nousb-noant-109f09e-
|
||||||
|
bfm burst-60s-200ms-10ms-3b-nousb-noant-109f09e-
|
||||||
|
next
|
||||||
|
burst-120s-40ms-0ms-4b-nousb-noant-2975c2c-
|
||||||
|
get values with (EXCEL paste into cell D1)
|
||||||
|
<table border="1">
|
||||||
|
<tr>
|
||||||
|
<th>avg V</th>
|
||||||
|
<th>avg A</th>
|
||||||
|
<th>avg W</th>
|
||||||
|
<th>avg mW</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>=AVERAGE(B1:B1000)</td>
|
||||||
|
<td>=AVERAGE(C1:C1000)</td>
|
||||||
|
<td>=D2*E2</td>
|
||||||
|
<td>=F2*1000</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
# Performance Notes
|
||||||
|
* log level info seems to be the same size as no output level, at least for bootloader, so defaulting to setting app and bootloader to log level info
|
||||||
|
## Builds
|
||||||
|
* trim minimal config
|
||||||
|
* bootloader compiled for performance
|
||||||
|
* bootloader log level info
|
||||||
|
* app compiled for performance
|
||||||
|
* app log level info
|
||||||
|
### ESP32
|
||||||
|
* 698080 bytes total image size
|
||||||
|
### ESP32-C6
|
||||||
|
* 635138 bytes total image size
|
||||||
|
### ESP32-C3
|
||||||
|
* 583696 bytes total image size
|
||||||
|
### ESP32-S3
|
||||||
|
* 554747 bytes total image size
|
||||||
@@ -1,2 +1,38 @@
|
|||||||
# PrincessPiTracker
|
# PrincessPiTracker
|
||||||
|
**here be dragons**
|
||||||
|
btle tracking via esp32 but with more support for chips, more options, radical power shaving and nun of da suck
|
||||||
|
|
||||||
|
i hvae become one with the build system, the toolchain, the sdk :Scuffled_Flustered: the ephmeral metaphysicaL Cconcept of esp-idf has adopted me as one of its own i shall soon know the true name of compuilauion
|
||||||
|
|
||||||
|

|
||||||
|
# Original reaDME below
|
||||||
|
# Find My Device ESP32 Firmware
|
||||||
|
This code enables you to use an ESP32-device as a custom Google Find My Device tracker. Note that the firmware is very experimental.
|
||||||
|
|
||||||
|
The firmware works differently to regular Find My Device trackers. It is made to be as simple as possible. It has no Fast Pair support, MAC rotation, advertisement rotation, etc.
|
||||||
|
|
||||||
|
Currently known working devices include the ESP32 (Dev Module V1), the ESP32-CAM, ESP32-C3, ESP32-C6, and ESP32-S3. If you use a different board and it works/doesn't work, feel free to message me, I'll update this README then.
|
||||||
|
|
||||||
|
Tested on ESP-IDF v5.5.1
|
||||||
|
|
||||||
|
## How to use
|
||||||
|
- Run the Python Script [`main.py`](../main.py) in the parent folder. Follow the instructions of the [README of the parent folder](../README.md).
|
||||||
|
- When the device list is displayed, press 'r' to register a new ESP32/Zephyr device in your account. Copy the displayed advertisement key.
|
||||||
|
- Install Visual Studio Code [here](https://code.visualstudio.com/download)
|
||||||
|
- Go to Visual Studio Code Extensions, search, install and open 'ESP-IDF' by Espressif
|
||||||
|
- Open the folder containing this README file in Visual Studio Code
|
||||||
|
- Run ESP-IDF set target from the command pallete (Ctrl+Shift+P) and add your model of esp32 (esp32, esp32s3, esp32c3, and esp32c6 currently supported)
|
||||||
|
- Run ESP-IDF menuconfig from the command pallete in VS Code (Ctrl+Shift+P)
|
||||||
|
- Under "GoogleFindMyTools Config" add your advertisement key
|
||||||
|
- Connect your ESP32 to your system with USB
|
||||||
|
- On the bottom left of Visual Studio Code, click the 'plug' icon and select your ESP32, it should be named '/dev/tty.usbserial-0001' (Linux), COM5 (Windows) or similar
|
||||||
|
- Click the 'Fire' icon to build and flash the firmware
|
||||||
|
- If asked, use UART as flash method
|
||||||
|
- After flashing, the ESP32 will restart and start advertising as the Find My Device tracker previously registered
|
||||||
|
|
||||||
|
## Known Issues
|
||||||
|
- You need to run [`main.py`](../main.py) every 4 days to keep receiving location reports from the server. This is because the advertisements have to be "announced" to Google.
|
||||||
|
- Might not work with 'fresh' Google accounts: "Your encryption data is locked on your device" is shown if you have never paired a Find My Device tracker with an Android device. Solution: See [README of the parent folder](../README.md).
|
||||||
|
- You cannot view locations for the ESP32 in the Google Find My Device app. You will need to use the Python script to do so.
|
||||||
|
- No privacy features such as rotating MAC addresses are implemented
|
||||||
|
- The firmware was built to receive as many network reports as possible. Therefore, it might consume more power than necessary. To fix this, you can tweak the parameters (TX Power and advertising interval) in [`main.c`](main/main.c)
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
todo:
|
||||||
|
x clean up sdkconfig.defaults.esp32
|
||||||
|
x clean up README re esp-idf
|
||||||
|
x esp32s3 support
|
||||||
|
x power optimize all boards
|
||||||
|
debug usb for power
|
||||||
|
measure life
|
||||||
|
sleep then wake up on loop for power savings
|
||||||
|
new interval
|
||||||
|
sleep duration
|
||||||
|
light sleep
|
||||||
|
deep sleep
|
||||||
|
secure boot/flash/nvs encryption
|
||||||
|
note
|
||||||
|
method
|
||||||
|
xiao c6 build instructions and hardware links
|
||||||
|
figure out optimal dbm setting for da antenna ~line 191
|
||||||
|
testing
|
||||||
|
legend: b builds, f flashes, w works
|
||||||
|
b esp32s3
|
||||||
|
b esp32c6
|
||||||
|
b esp32
|
||||||
|
b esp32c3
|
||||||
|
After Width: | Height: | Size: 49 KiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 3.0 MiB |
|
After Width: | Height: | Size: 152 KiB |
|
After Width: | Height: | Size: 9.1 MiB |
|
After Width: | Height: | Size: 1.5 MiB |
|
After Width: | Height: | Size: 76 KiB |
@@ -0,0 +1,33 @@
|
|||||||
|
import asyncio
|
||||||
|
from bleak import BleakScanner
|
||||||
|
import time
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
def initalize_file(log_file):
|
||||||
|
with open(log_file, 'w') as f:
|
||||||
|
f.write("mac_address,RSSI,epoch_time,iso_time\n")
|
||||||
|
|
||||||
|
async def scan(mac_to_listen_for = '54:32:04:33:0d:4a', log_file = f"{time.time()}_mac_date_log.csv", timeout = 300):
|
||||||
|
initalize_file(log_file)
|
||||||
|
print(f"Listening for MAC: {mac_to_listen_for} every {timeout} seconds. Logging to {log_file}")
|
||||||
|
|
||||||
|
while True:
|
||||||
|
btle_device = await BleakScanner.find_device_by_address(mac_to_listen_for, timeout)
|
||||||
|
|
||||||
|
if btle_device is not None:
|
||||||
|
# timestamps
|
||||||
|
current_time = time.time()
|
||||||
|
current_iso = datetime.fromtimestamp(current_time).isoformat()
|
||||||
|
|
||||||
|
# extract RSSI and Address
|
||||||
|
RSSI = btle_device.details['props']['RSSI']
|
||||||
|
address = btle_device.details['props']['Address']
|
||||||
|
|
||||||
|
# append to file
|
||||||
|
with open(log_file, 'a') as f:
|
||||||
|
print(f"{address},{RSSI},{current_time},{current_iso}")
|
||||||
|
f.write(f"{address},{RSSI},{current_time},{current_iso}\n")
|
||||||
|
# sleep for the specified timeout duration
|
||||||
|
await asyncio.sleep(timeout)
|
||||||
|
|
||||||
|
asyncio.run(scan())
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
idf_component_register(SRCS "PrincessPiTracker.c"
|
||||||
|
INCLUDE_DIRS "."
|
||||||
|
PRIV_REQUIRES nvs_flash bt esp_driver_usb_serial_jtag
|
||||||
|
)
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
menu "PrincessPiTracker Config"
|
||||||
|
config ADVERTISEMENT_INTERVAL
|
||||||
|
int "Interval between advertisements in milliseconds"
|
||||||
|
default 100
|
||||||
|
range 12 10240
|
||||||
|
help
|
||||||
|
Int number of milliseconds (ms) in between advertisements min 12 max 10240
|
||||||
|
100 for max delay with 10ms random
|
||||||
|
200 for deep sleep burst mode
|
||||||
|
|
||||||
|
config ADVERTISEMENT_INTERVAL_JITTER_MS
|
||||||
|
int "Max Jitter to add to Advertisement Interval in milliseconds"
|
||||||
|
default 10
|
||||||
|
range 0 500
|
||||||
|
help
|
||||||
|
Int number of milliseconds (ms) max jitter to add to advertisement interval min 0 max 2000
|
||||||
|
|
||||||
|
config ADVERTISEMENT_KEY
|
||||||
|
string "Your Advertisement Key"
|
||||||
|
default ""
|
||||||
|
help
|
||||||
|
Your advertisement key, see https://github.com/leonboe1/GoogleFindMyTools
|
||||||
|
|
||||||
|
config DISABLE_USB_WHILE_CHARGING
|
||||||
|
bool "Disable USB Serial and Broadcasting While Charging"
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
Enable this option to disable USB Serial and Broadcasting while charging to save power.
|
||||||
|
|
||||||
|
config DEVICE_NAME
|
||||||
|
string "BLE Device Name"
|
||||||
|
default "PrincesiPiTracker"
|
||||||
|
help
|
||||||
|
The Bluetooth device name that will be broadcasted.
|
||||||
|
|
||||||
|
config TAG
|
||||||
|
string "Logging Tag"
|
||||||
|
default "PrincessPiTracker"
|
||||||
|
help
|
||||||
|
The tag used in logging messages.
|
||||||
|
|
||||||
|
config RANDOM_MAC_ADDRESS
|
||||||
|
bool "Use Random MAC Address"
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Enable this option to use a random MAC address for BLE advertising instead of the public MAC address.
|
||||||
|
|
||||||
|
config DEEP_SLEEP_BURST_MODE
|
||||||
|
bool "Enable Deep Sleep Burst Mode"
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
Enable this option to wake up, send multiple advertisements in a burst, then go back to deep sleep.
|
||||||
|
|
||||||
|
config DEEP_SLEEP_BURST_COUNT
|
||||||
|
int "Number of Advertisements per Burst"
|
||||||
|
default 4
|
||||||
|
range 1 100
|
||||||
|
depends on DEEP_SLEEP_BURST_MODE
|
||||||
|
help
|
||||||
|
Int number of advertisements to send per burst min 1 max 100
|
||||||
|
|
||||||
|
config DEEP_SLEEP_DURATION_S
|
||||||
|
int "Deep Sleep Duration in seconds"
|
||||||
|
default 120
|
||||||
|
range 0 86400
|
||||||
|
depends on DEEP_SLEEP_BURST_MODE
|
||||||
|
help
|
||||||
|
Int number of seconds (s) to deep sleep between advertisement cycles min 0 max 86400 (24 hours)
|
||||||
|
|
||||||
|
config STARTUP_DELAY_MS
|
||||||
|
int "Startup Delay in milliseconds"
|
||||||
|
default 1000
|
||||||
|
range 0 60000
|
||||||
|
help
|
||||||
|
Int number of milliseconds (ms) to delay startup to allow peripherals to initialize min 0 max 60000
|
||||||
|
endmenu
|
||||||
@@ -0,0 +1,329 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <math.h> // for the round function
|
||||||
|
#include "esp_log.h" // For ESP_LOGI and other logging functions
|
||||||
|
#include "nvs_flash.h" // For NVS functions like nvs_flash_init
|
||||||
|
#include "esp_err.h" // For error handling
|
||||||
|
|
||||||
|
#if CONFIG_DISABLE_USB_WHILE_CHARGING
|
||||||
|
#include "driver/usb_serial_jtag.h" // dis is da heacder fopr usb_serial_jtag_is_connected()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CONFIG_DEEP_SLEEP_BURST_MODE
|
||||||
|
#include "soc/soc_caps.h" // malloc and shit if lmao
|
||||||
|
#include "esp_sleep.h" // For deep sleep functions
|
||||||
|
#include "freertos/FreeRTOS.h" // freertosbullshit
|
||||||
|
#include "freertos/task.h"
|
||||||
|
|
||||||
|
// calculate da burst delay live and burst delay microseconds
|
||||||
|
#define DEEP_SLEEP_BURST_DELAY_LIVE_MS ((CONFIG_DEEP_SLEEP_BURST_COUNT * CONFIG_ADVERTISEMENT_INTERVAL) + ((CONFIG_DEEP_SLEEP_BURST_COUNT + 1) * CONFIG_ADVERTISEMENT_INTERVAL_JITTER_MS)) // +CONFIG_ADVERTISEMENT_INTERVAL so the silly thing will be sure to boadcast dem all and not die before, using CONFIG_ADVERTISEMENT_INTERVAL because presumably it'll keep the extra time in rough check with the interval ig
|
||||||
|
#define DEEP_SLEEP_BURST_DELAY_MICROS (CONFIG_DEEP_SLEEP_DURATION_S * 1000000)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// macro to round float to int
|
||||||
|
#define ROUND(x) ((int)((x) >= 0.0 ? floor((x) + 0.5) : ceil((x) - 0.5)))
|
||||||
|
|
||||||
|
// handle da minutes config and round to da nearest integer
|
||||||
|
#define ADVERTISE_INTERVAL_MIN ROUND((CONFIG_ADVERTISEMENT_INTERVAL / 0.625))
|
||||||
|
#define ADVERTISE_INTERVAL_MAX (ADVERTISE_INTERVAL_MIN + ROUND((CONFIG_ADVERTISEMENT_INTERVAL_JITTER_MS / 0.625)))
|
||||||
|
|
||||||
|
// repoting tag
|
||||||
|
#define TAG CONFIG_TAG
|
||||||
|
|
||||||
|
// module configs
|
||||||
|
//// esp32 classic
|
||||||
|
#if defined(CONFIG_IDF_TARGET_ESP32)
|
||||||
|
#include "esp_bt.h" // For esp_bt_controller_* functions
|
||||||
|
#include "esp_bt_main.h" // For esp_bluedroid_* functions
|
||||||
|
#include "esp_gap_ble_api.h"
|
||||||
|
//// esp32c3
|
||||||
|
#elif defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||||
|
#include "esp_nimble_hci.h"
|
||||||
|
#include "nimble/nimble_port.h"
|
||||||
|
#include "nimble/nimble_port_freertos.h"
|
||||||
|
#include "host/ble_hs.h"
|
||||||
|
#include "host/util/util.h"
|
||||||
|
#include "services/gap/ble_svc_gap.h"
|
||||||
|
//// esp32c6 and esp32s3
|
||||||
|
#elif defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||||
|
#include "nimble/nimble_port.h"
|
||||||
|
#include "nimble/nimble_port_freertos.h"
|
||||||
|
#include "host/ble_hs.h"
|
||||||
|
#include "host/util/util.h"
|
||||||
|
#include "services/gap/ble_svc_gap.h"
|
||||||
|
//// unsupported
|
||||||
|
#else
|
||||||
|
#error "Unsupported target"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// RTC_SLOW_ATTR static struct timeval sleep_enter_time;
|
||||||
|
|
||||||
|
// This is the advertisement key / EID. Change it to your own EID.
|
||||||
|
const char *eid_string = CONFIG_ADVERTISEMENT_KEY;
|
||||||
|
// // This is the advertisement key / EID. Change it to your own EID.
|
||||||
|
// const char *eid_string = CONFIG_ADVERTISEMENT_KEY;
|
||||||
|
// #define EID_STRING_LENGTH STRLENT((CONFIG_ADVERTISEMENT_KEY))
|
||||||
|
// #if EID_STRING_LENGTH != 40
|
||||||
|
// #error "EID string must be 40 hexadecimal characters (20 bytes)"
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// Find My Device Network (FMDN) advertisement
|
||||||
|
// Octet Value Description
|
||||||
|
// 0 0x02 Length
|
||||||
|
// 1 0x01 Flags data type value
|
||||||
|
// 2 0x06 Flags data
|
||||||
|
// 3 0x18 or 0x19 Length
|
||||||
|
// 4 0x16 Service data data type value
|
||||||
|
// 5 0xAA 16-bit service UUID
|
||||||
|
// 6 0xFE 16-bit service UUID
|
||||||
|
// 7 0x40 or 0x41 FMDN frame type with unwanted tracking protection mode indication
|
||||||
|
// 8..27 Random 20-byte ephemeral identifier
|
||||||
|
// 28 Hashed flags
|
||||||
|
|
||||||
|
uint8_t adv_raw_data[31] = {
|
||||||
|
0x02, // Length
|
||||||
|
0x01, // Flags data type value
|
||||||
|
0x06, // Flags data
|
||||||
|
0x19, // Length
|
||||||
|
0x16, // Service data data type value
|
||||||
|
0xAA, // 16-bit service UUID
|
||||||
|
0xFE, // 16-bit service UUID
|
||||||
|
0x41, // FMDN frame type with unwanted tracking protection mode indication
|
||||||
|
// 20-byte ephemeral identifier (inserted below)
|
||||||
|
// Hashed flags (implicitly initialized to 0)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Function to convert a hex string into a byte array
|
||||||
|
void hex_string_to_bytes(const char *hex, uint8_t *bytes, size_t len) {
|
||||||
|
for (size_t i = 0; i < len; i++) {
|
||||||
|
sscanf(hex + 2 * i, "%2hhx", &bytes[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// esp32c3, esp32c6, and esp32s3
|
||||||
|
#if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||||
|
|
||||||
|
// BLE advertising callback
|
||||||
|
static int ble_advertise_cb(struct ble_gap_event *event, void *arg) {
|
||||||
|
switch (event->type) {
|
||||||
|
case BLE_GAP_EVENT_ADV_COMPLETE:
|
||||||
|
ESP_LOGI(TAG, "Advertising completed");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up and start advertising
|
||||||
|
static void ble_start_advertising(uint8_t *adv_raw_data, size_t adv_raw_data_len) {
|
||||||
|
struct ble_gap_adv_params adv_params = {
|
||||||
|
.conn_mode = BLE_GAP_CONN_MODE_NON,
|
||||||
|
.disc_mode = BLE_GAP_DISC_MODE_GEN,
|
||||||
|
// use calculated interval depending on config
|
||||||
|
.itvl_min = ADVERTISE_INTERVAL_MIN,
|
||||||
|
.itvl_max = ADVERTISE_INTERVAL_MAX,
|
||||||
|
// for testing purposes, use fixed 32 cycles as interval (20ms)
|
||||||
|
//// .itvl_min = 0x20,
|
||||||
|
//// .itvl_max = 0x20
|
||||||
|
};
|
||||||
|
|
||||||
|
// set name
|
||||||
|
ble_svc_gap_device_name_set(CONFIG_DEVICE_NAME);
|
||||||
|
|
||||||
|
// set da data
|
||||||
|
ble_gap_adv_set_data(adv_raw_data, adv_raw_data_len);
|
||||||
|
|
||||||
|
// Start advertising
|
||||||
|
#if CONFIG_RANDOM_MAC_ADDRESS
|
||||||
|
ESP_LOGI(TAG, "Using Random MAC Address for advertising");
|
||||||
|
ble_gap_adv_start(BLE_OWN_ADDR_RANDOM, NULL, BLE_HS_FOREVER, &adv_params, ble_advertise_cb, NULL);
|
||||||
|
#else
|
||||||
|
ESP_LOGI(TAG, "Using Public MAC Address for advertising");
|
||||||
|
ble_gap_adv_start(BLE_OWN_ADDR_PUBLIC, NULL, BLE_HS_FOREVER, &adv_params, ble_advertise_cb, NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Started advertising with interval %d ms", CONFIG_ADVERTISEMENT_INTERVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ble_host_task(void *param)
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, "BLE Host Task Started");
|
||||||
|
// run advertisement
|
||||||
|
nimble_port_run();
|
||||||
|
nimble_port_freertos_deinit();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sync callback
|
||||||
|
static void on_sync(void) {
|
||||||
|
// Set device name
|
||||||
|
ble_svc_gap_device_name_set(CONFIG_DEVICE_NAME);
|
||||||
|
|
||||||
|
// Start advertising
|
||||||
|
ble_start_advertising(adv_raw_data, sizeof(adv_raw_data));
|
||||||
|
|
||||||
|
//print adv raw data
|
||||||
|
ESP_LOGI(TAG, "adv_raw_data: %s", adv_raw_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ble_init(void) {
|
||||||
|
ESP_LOGI(TAG, "Initializing BLE");
|
||||||
|
|
||||||
|
// 20-byte ephemeral identifier
|
||||||
|
uint8_t eid_bytes[20];
|
||||||
|
hex_string_to_bytes(eid_string, eid_bytes, 20);
|
||||||
|
memcpy(&adv_raw_data[8], eid_bytes, 20);
|
||||||
|
|
||||||
|
// Initialize NimBLE - ESP-IDF v5.3 style
|
||||||
|
ESP_ERROR_CHECK(nimble_port_init());
|
||||||
|
|
||||||
|
// Initialize the NimBLE host configuration
|
||||||
|
ble_hs_cfg.sync_cb = on_sync;
|
||||||
|
|
||||||
|
// Initialize GAP service
|
||||||
|
ble_svc_gap_init();
|
||||||
|
|
||||||
|
// Create host task
|
||||||
|
nimble_port_freertos_init(ble_host_task);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if CONFIG_DEEP_SLEEP_BURST_MODE
|
||||||
|
static void ble_deinit(void) {
|
||||||
|
ESP_LOGI(TAG, "Deinitializing BLE");
|
||||||
|
nimble_port_stop();
|
||||||
|
nimble_port_deinit();
|
||||||
|
nimble_port_freertos_deinit();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void deep_sleep_register_rtc_timer_wakeup(void) {
|
||||||
|
ESP_LOGI(TAG, "Woke up deep sleep, re-initializing BLE");
|
||||||
|
ble_init();
|
||||||
|
// const int wakeup_time_sec = CONFIG_DEEP_SLEEP_DURATION_S;
|
||||||
|
// ESP_LOGI(TAG, "Enabling timer wakeup, %ds\n", CONFIG_DEEP_SLEEP_DURATION_S);
|
||||||
|
// ESP_ERROR_CHECK(esp_sleep_enable_timer_wakeup(DEEP_SLEEP_BURST_DELAY_MICROS));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void deep_sleep_wait_to_sleep() {
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(DEEP_SLEEP_BURST_DELAY_LIVE_MS));
|
||||||
|
ESP_LOGI(TAG, "Waited %d ms, preparing to enter deep sleep\n", DEEP_SLEEP_BURST_DELAY_LIVE_MS);
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Deiniting BTLE before deep sleep");
|
||||||
|
ble_deinit();
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Entering deep sleep\n\tDuration %d ms\n\tburst count %d\n\tburst delay %d ms\n", CONFIG_DEEP_SLEEP_DURATION_S * 1000, CONFIG_DEEP_SLEEP_BURST_COUNT, DEEP_SLEEP_BURST_DELAY_LIVE_MS);
|
||||||
|
ESP_ERROR_CHECK(esp_sleep_enable_timer_wakeup(DEEP_SLEEP_BURST_DELAY_MICROS));
|
||||||
|
esp_deep_sleep_start();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void app_main() {
|
||||||
|
// delay to make shit to actually fookin work holy shit fuck you asshole bitch
|
||||||
|
// i spit on you
|
||||||
|
// i spit on your mom
|
||||||
|
// if your mom is dead i spit on her grave
|
||||||
|
// shame
|
||||||
|
// shame
|
||||||
|
// anus
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(CONFIG_STARTUP_DELAY_MS));
|
||||||
|
|
||||||
|
// validate eid_string length
|
||||||
|
const size_t length = strlen(eid_string);
|
||||||
|
if (length == 0) {
|
||||||
|
ESP_LOGE(TAG, "Advertisement Key is not set. Please set CONFIG_ADVERTISEMENT_KEY in the project configuration.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (length != 40) {
|
||||||
|
ESP_LOGE(TAG, "Invalid Advertisement Key length. It must be 40 hexadecimal characters (20 bytes) Length given: %d", length);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// only show the key in debug mode
|
||||||
|
ESP_LOGD(TAG, "Advertisement Key (EID): \"%s\"\n", eid_string);
|
||||||
|
|
||||||
|
// interval infors
|
||||||
|
#if CONFIG_DEEP_SLEEP_BURST_MODE
|
||||||
|
ESP_LOGI(TAG, "Deep sleep burst mode enabled (not normal mode)\n");
|
||||||
|
#else
|
||||||
|
ESP_LOGI(TAG, "Normal mode enabled (no deep sleep burst mode)\n");
|
||||||
|
#endif
|
||||||
|
ESP_LOGI(TAG, "Advertisement Calculated Interval Cycles: %d cycles\n", ADVERTISE_INTERVAL_MIN);
|
||||||
|
ESP_LOGI(TAG, "Advertisement Interval Min: %d Milliseconds\n", CONFIG_ADVERTISEMENT_INTERVAL);
|
||||||
|
ESP_LOGI(TAG, "Advertisement Interval Max: %d Milliseconds (%d ms jitter)\n", CONFIG_ADVERTISEMENT_INTERVAL + CONFIG_ADVERTISEMENT_INTERVAL_JITTER_MS, CONFIG_ADVERTISEMENT_INTERVAL_JITTER_MS);
|
||||||
|
ESP_LOGI(TAG, "BLE Device Name: %s\n", CONFIG_DEVICE_NAME);
|
||||||
|
ESP_LOGI(TAG, "Burst duration %d milliseconds", DEEP_SLEEP_BURST_DELAY_LIVE_MS);
|
||||||
|
#if CONFIG_RANDOM_MAC_ADDRESS
|
||||||
|
ESP_LOGI(TAG, "Using Random MAC Address for advertising\n");
|
||||||
|
#else
|
||||||
|
ESP_LOGI(TAG, "Using Public MAC Address for advertising\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Initialize NVS (required for BLE initialization)
|
||||||
|
esp_err_t ret = nvs_flash_init();
|
||||||
|
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
|
||||||
|
ESP_ERROR_CHECK(nvs_flash_erase());
|
||||||
|
ret = nvs_flash_init();
|
||||||
|
}
|
||||||
|
ESP_ERROR_CHECK(ret);
|
||||||
|
|
||||||
|
// esp32c3, esp32c6, and esp32s3
|
||||||
|
#if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||||
|
#if CONFIG_DEEP_SLEEP_BURST_MODE
|
||||||
|
|
||||||
|
#if CONFIG_DISABLE_USB_WHILE_CHARGING
|
||||||
|
// check if usb is connectedddd
|
||||||
|
bool usb_connected = usb_serial_jtag_is_connected();
|
||||||
|
if (usb_connected) {
|
||||||
|
ESP_LOGI(TAG, "USB Serial JTAG is connected\nDefaulting to Charging and Flashing Mode");
|
||||||
|
return; // exit app_main to prevent BLE initialization
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Initialize sleep wait task
|
||||||
|
ESP_LOGI(TAG, "Initializing sleep wait task");
|
||||||
|
xTaskCreate(deep_sleep_wait_to_sleep, "deep_sleep_wait_to_sleep", 4096, NULL, 6, NULL);
|
||||||
|
|
||||||
|
// INIt timer wakeup
|
||||||
|
ESP_LOGI(TAG, "Initializing Timer Wakeup");
|
||||||
|
deep_sleep_register_rtc_timer_wakeup();
|
||||||
|
#else
|
||||||
|
ble_init(); // initialize BLE normally without deep sleep
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// esp32 classic
|
||||||
|
#elif defined(CONFIG_IDF_TARGET_ESP32)
|
||||||
|
// Initialize Bluetooth controller
|
||||||
|
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
|
||||||
|
ESP_ERROR_CHECK(esp_bt_controller_init(&bt_cfg));
|
||||||
|
ESP_ERROR_CHECK(esp_bt_controller_enable(ESP_BT_MODE_BLE));
|
||||||
|
|
||||||
|
// Initialize Bluedroid stack
|
||||||
|
ESP_ERROR_CHECK(esp_bluedroid_init());
|
||||||
|
ESP_ERROR_CHECK(esp_bluedroid_enable());
|
||||||
|
|
||||||
|
// Set BLE TX power to 9 dBm
|
||||||
|
ESP_ERROR_CHECK(esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_DEFAULT, ESP_PWR_LVL_P9));
|
||||||
|
ESP_ERROR_CHECK(esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_ADV, ESP_PWR_LVL_P9));
|
||||||
|
ESP_LOGI(TAG, "Set BLE TX Power to 9 dBm");
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(esp_ble_gap_config_adv_data_raw(adv_raw_data, sizeof(adv_raw_data)));
|
||||||
|
|
||||||
|
// Configure advertisement parameters
|
||||||
|
esp_ble_adv_params_t adv_params = {
|
||||||
|
// change those if you want to save power
|
||||||
|
.adv_int_min = ADVERTISE_INTERVAL_MIN,
|
||||||
|
.adv_int_max = ADVERTISE_INTERVAL_MAX,
|
||||||
|
.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,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Start advertising
|
||||||
|
ESP_ERROR_CHECK(esp_ble_gap_start_advertising(&adv_params));
|
||||||
|
ESP_LOGI(TAG, "BLE advertising started.");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
## IDF Component Manager Manifest File
|
||||||
|
dependencies:
|
||||||
|
## Required IDF version
|
||||||
|
idf:
|
||||||
|
version: ">=4.1.0"
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
# manuallyc created
|
||||||
|
CONFIG_BT_ENABLED=y
|
||||||
|
CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_PERF=y
|
||||||
|
CONFIG_BOOTLOADER_LOG_COLORS=y
|
||||||
|
CONFIG_APP_RETRIEVE_LEN_ELF_SHA=16
|
||||||
|
CONFIG_ESPTOOLPY_HEADER_FLASHSIZE_UPDATE=y
|
||||||
|
CONFIG_COMPILER_OPTIMIZATION_PERF=y
|
||||||
|
CONFIG_PM_ENABLE=y
|
||||||
|
CONFIG_PM_DFS_INIT_AUTO=y
|
||||||
|
CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=y
|
||||||
|
CONFIG_LOG_VERSION_2=y
|
||||||
|
CONFIG_LOG_COLORS=y
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
# manually created
|
||||||
|
# bootloader too big for sum fuckin reason on esp32 only so now we optimize this one alone for space and not size
|
||||||
|
## gotta disable the performance one and enable da size one for safety
|
||||||
|
CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_PERF=n
|
||||||
|
CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y
|
||||||
|
|
||||||
|
CONFIG_ESPTOOLPY_FLASHFREQ_20M=y
|
||||||
|
CONFIG_ESPTOOLPY_HEADER_FLASHSIZE_UPDATE=y
|
||||||
|
CONFIG_BT_BTU_TASK_STACK_SIZE=4096
|
||||||
|
CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_80=y
|
||||||
|
CONFIG_LWIP_TCP_SND_BUF_DEFAULT=5744
|
||||||
|
CONFIG_LWIP_TCP_WND_DEFAULT=5744
|
||||||
|
CONFIG_LWIP_HOOK_IP6_INPUT_NONE=y
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# manually created
|
||||||
|
CONFIG_BT_NIMBLE_ENABLED=y
|
||||||
|
CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_80=y
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
# manually created
|
||||||
|
CONFIG_BT_NIMBLE_ENABLED=y
|
||||||
|
CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_80=y
|
||||||
|
CONFIG_LWIP_TCP_SND_BUF_DEFAULT=5744
|
||||||
|
CONFIG_LWIP_TCP_WND_DEFAULT=5744
|
||||||
|
CONFIG_LWIP_HOOK_IP6_INPUT_NONE=y
|
||||||
|
CONFIG_MBEDTLS_SSL_KEEP_PEER_CERTIFICATE=y
|
||||||
|
CONFIG_VFS_SUPPORT_TERMIOS=y
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
# manually created
|
||||||
|
CONFIG_BT_NIMBLE_ENABLED=y
|
||||||
|
CONFIG_ESPTOOLPY_FLASHFREQ_20M=y
|
||||||
|
CONFIG_BT_BTU_TASK_STACK_SIZE=4096
|
||||||
|
CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_80=y
|
||||||
|
CONFIG_LWIP_TCP_SND_BUF_DEFAULT=5744
|
||||||
|
CONFIG_LWIP_TCP_WND_DEFAULT=5744
|
||||||
|
CONFIG_LWIP_HOOK_IP6_INPUT_NONE=y
|
||||||
|
CONFIG_MBEDTLS_SSL_KEEP_PEER_CERTIFICATE=y
|
||||||
|
CONFIG_VFS_SUPPORT_TERMIOS=y
|
||||||