Create a new plain-Bluetooth field survey exercise for my LilyGO T-Beam SUPREME ESP32-S3 boards.
Repository context:
- This is my existing microReticulumTbeam / T-Beam SUPREME PlatformIO project.
- Follow the style of the existing exercises.
- Do not modify working Reticulum BLE-interface exercises.
- This new exercise is intentionally NOT Reticulum.
- This exercise is only a BLE neighborhood sounder / RSSI gauge to help me place T-Beams before later Reticulum mesh testing.
- The target board is LilyGO T-Beam SUPREME, ESP32-S3FN8, SH1106 128x64 OLED, Bluetooth LE capable.
- Use the existing board support found under /usr/local/src/microreticulum/microreticulumTbeam/lig, OLED initialization, PMU setup, time discipline, GPS and utilities already present in the repo where possible. The unit should require a disciplined clock within 24 hours of the last time the clock was disciplined, and a the ability to obtain coordinates. All units, except AMY, can write to their SD card; AMY's card reader is defective.
- If useful, inspect nearby staged Meshtastic code, /usr/local/src/meshtastic, only for board/display initialization patterns, not for protocol design.
Goal:
Build a firmware image that each T-Beam can run. Each unit continuously advertises a small BLE beacon identifying itself, while also scanning for other beacons from my known T-Beam units. My units are: AMY, BOB, CY, DAN, ED, FLO & GUY and identifications using those names should be used to distinguish them form other Bluetooth advertisements. The OLED should display only my units, with RSSI and age/last-seen information, so I can walk around my property and determine where a node can hear zero, one, or several other nodes. I have several neighbors who have Bluetooth advertisements including some other devices I control: all those should be ignored.
Functional requirements:
1. Each device shall have a compile-time NODE_NAME, e.g. AMY, BOB, CY, DAN, ED, FLO, GUY.
2. Each device shall advertise using BLE advertising only. No pairing requirement. No phone app requirement. No GATT connection requirement unless absolutely necessary; I do not think GATT connections will be necessary for this discovery only exercise.
3. The advertised payload must include a project-specific identifier so scanners can ignore neighbors' Bluetooth devices.
4. The advertised payload must include:
- magic/project prefix, e.g. "TBMSND"
- protocol version, e.g. 1
- NODE_NAME
- optional monotonically increasing sequence number
- optional short uptime counter
5. The scanner shall filter advertisements strictly:
- accept only advertisements containing the project prefix "TBMSND"
- accept only NODE_NAME values from a fixed allow-list: AMY, BOB, CY, DAN, ED, FLO, GUY
- ignore everything else
6. For each known unit heard, maintain:
- node name
- last RSSI
- rolling average RSSI, preferably over the last 5 samples
- number of advertisements seen
- seconds since last seen
- optional sequence number if present
7. OLED display:
- top line: this unit name and mode, e.g. "AMY BLE SOUNDER"
- subsequent lines: heard nodes sorted by strongest rolling RSSI first
- each line compact, e.g. "BOB -71 avg-68 2s"
- show "none heard" when no allowed unit has been seen recently
- show stale entries differently or drop them after a configurable timeout, e.g. 20 seconds
8. Serial output:
- emit timestamp-ish millis, this NODE_NAME, seen NODE_NAME, RSSI, avg RSSI, age, count, sequence
- make the output easy to tee into logs
- include a boot banner with compile-time settings
- serial output will only be used during validation of the builds, since the units will be mobile for testing, serial output then is irrelevant
9. Button behavior:
- BOOT button may cycle display modes if easy:
a. strongest nodes
b. all known nodes with heard/not-heard status
c. diagnostic raw count
- Do not make button handling complicated in the first version.
10. Keep LoRa disabled in this exercise.
11. We are not using microReticulum in this explorer exercise.
12. Avoid heap-heavy behavior. This should run indefinitely.
13. Use NimBLE-Arduino if already available or easy to add; otherwise use the ESP32 Arduino BLE library. Prefer NimBLE if it reduces memory use and supports concurrent advertising/scanning cleanly.
14. The ESP32-S3 is BLE-only; do not use Classic Bluetooth APIs.
15. Document any known limitations, especially:
- RSSI is not a precise distance measurement.
- body position and antenna orientation matter.
- BLE advertisements are not guaranteed delivery.
- scan/advertise duty cycle choices affect detection latency and power.
16. Provide build and upload commands at the top of the source file as comments, matching my usual style.
18. Add logging on the SD card using YYYYMMDD_HHMISS_[UNIT NAME]_ble_search.log. Logging should include date + time, both epoch high precision and regular human readable (not high precision), GPS coordinates of current receiving unit, the advertisement received, the RSSI strength of the received transmission.
19. Include web interface such as in Exercise 18, or later -- I cannot remember for sure, that allows downloading of the log files and deletion of the log files. We had a system where each unit had a unique IP for it, use that.
Implementation details:
- Use directory: exercises/26_Bluetooth_discover.
- Add a README.md explaining the test procedure.
- Add source code for the exercise.
- You can copy the platformio.ini into the exercises/26_Bluetooth_discover folder from either exercise 18... or 306...
- Provide a clear way to compile different node images by passing NODE_NAME at build time, for just as we did on exercises 306 and 18.
- If C/C++ quoting through PlatformIO is awkward, implement a simple node_config.h file with NODE_NAME and document that I should change it per build.
Suggested field procedure to document:
1. Flash all units with this sounder image, each with a unique NODE_NAME.
2. Place one unit at the intended origin, prefereable center to all other which will be in a start topology
3. Carry another unit and watch the OLED.
4. Find a position where it hears only the intended neighbor with weak/moderate RSSI.
5. Place it there.
6. Repeat outward to create a chain.
7. Record the topology manually before switching to the Reticulum BLE-interface binary.
Acceptance test:
- With AMY and BOB on the bench, AMY displays BOB with RSSI and age, and BOB displays AMY.
- With a third random Bluetooth device nearby, it does not appear on the OLED or in accepted serial records.
- If BOB is powered off, AMY shows BOB aging out after the stale timeout.
- Serial output can be captured with:
pio device monitor -b 115200 -p /dev/ttytAMY | tee logs/ble_sounder_AMY_YYYYMMDD_HHMMSS.log
Please implement the smallest reliable version first. Do not add Reticulum, LoRa logging, encryption, pairing, or routing in this exercise.
Before you write, please identify anything area you need direction or confliction resolution on and await my instruction and confirmation to proceed. I want to iron out any areas so expectations coincide with your understanding.
# Response:
I found a few decision points before writing `exercises/26_Bluetooth_discover`:
1.**BLE library**
Existing BLE exercises use the ESP32 Arduino BLE library, not NimBLE. I recommend using the existing ESP32 BLE stack for the first version to avoid adding a new dependency.
2.**Clock/GPS requirement**
The prompt says the unit should require a disciplined clock within 24 hours and coordinates. For field usefulness, I recommend:
- BLE advertise/scan/OLED always runs.
- SD logging starts only when RTC/GPS position are valid enough.
- OLED/serial clearly show `NO GPS/NO CLOCK/NO SD` status.
3.**AMY SD card**
Since AMY’s SD reader is defective, I recommend keeping the same firmware for AMY but treating missing SD as non-fatal. AMY still sounders and shows OLED; it just does not write logs.
4.**Web interface**
WiFi AP plus BLE scanning/advertising can affect BLE timing and power. I recommend implementing the shared `TBeamWeb` log download/delete interface now, but making logging/web opportunistic: if SD mounts, web starts; if not, BLE still works.
5.**Payload format**
I recommend advertising a compact manufacturer-data string:
`TBMSND|1|AMY|seq|uptime`
and filtering only that prefix plus the fixed allow-list.
6.**Build setup**
I recommend using per-node PlatformIO environments like exercise 18: `amy`, `bob`, `cy`, `dan`, `ed`, `flo`, `guy`, with `BOARD_ID`/`NODE_NAME` and `LOG_AP_IP_OCTET`.
Confirm those choices and I’ll implement the smallest reliable version in `exercises/26_Bluetooth_discover` with `platformio.ini`, `src/main.cpp`, and `README.md`, then build at least one environment.
# Further Instructions after 1st reply:
1. BLE Library: okay.
2. No. I want Clock/GPS to be working so I do not waste time thinking I'm gather userful data when they are not. It forces me to be assiduous in getting everything coordinated at the start.
3. AMY SD Card. Your proposal is fine.
4. Web Interface: Yes, especially since AMY cannot offer logs.
5. Payload format: Looks good.
6. Build setup: Yes, all settings in a single platformio.ini file, though.
Please proceed unless the above creates a gating factor.