Skip to content

Commit fb7669b

Browse files
committed
chore: add format, ignore secrets
1 parent a1751d5 commit fb7669b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+2324
-2654
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
.vscode/settings.json
2+
secrets/secrets.yaml
3+
pgpemu-esp32/.cache

pgpemu-esp32/.clang-format

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
BasedOnStyle: Google
2+
IndentWidth: 4
3+
ColumnLimit: 100
4+
AllowShortIfStatementsOnASingleLine: false
5+
SortIncludes: true
6+
DerivePointerAlignment: false
7+
PointerAlignment: Left

pgpemu-esp32/.clangd

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
CompileFlags:
2+
Remove: [-f*, -m*]
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# Copilot Instructions for `pgpemu-esp32`
2+
3+
## Project Overview
4+
- **Purpose:** Emulates a Pokémon GO Plus device on ESP32-C3 hardware, providing BLE, button, LED, and WiFi captive portal functionality.
5+
- **Structure:**
6+
- All main logic is in `main/` (e.g., `pgp_gatts.c`, `pgp_gap.c`, `pgp_handshake.c`, `config_portal.c`).
7+
- Uses ESP-IDF build system (CMake/Makefile) and ESP-IDF APIs for BLE, WiFi, NVS, etc.
8+
- `build/` is generated; do not edit.
9+
10+
## Key Components
11+
- **BLE GATT Server:** `pgp_gatts.c`, `pgp_gap.c`, `pgp_gatts_debug.c` handle BLE services and device advertising.
12+
- **Button/LED:** `button_input.c`, `led_output.c`, `pgp_led_handler.c` manage hardware I/O.
13+
- **WiFi Setup Portal:** `config_portal.c`, `captive_dns.c` provide a captive portal for device configuration.
14+
- **Secrets/Settings:** `config_secrets.c`, `settings.c`, `nvs_helper.c` manage persistent storage in NVS.
15+
- **Certificates:** `pgp_cert.c` and related files handle device certificates for authentication.
16+
- **PC Test Harness:** `main/pc/` and `Makefile.test` allow building a test binary (`cert-test`) for handshake/cert logic on a PC.
17+
18+
19+
## Build, Flash & Format
20+
- **Build:** Use VS Code tasks or run `idf.py build` (see `.vscode/tasks.json`).
21+
- **Flash:** Use `idf.py -p <PORT> flash` or the VS Code "Flash - Flash the device" task.
22+
- **Monitor:** Use `idf.py -p <PORT> monitor` or the "Monitor: Start the monitor" task.
23+
- **Clean:** Use `idf.py fullclean` or the "Clean - Clean the project" task.
24+
- **Set Target:** Use the "Set ESP-IDF Target" task if switching ESP32 variants.
25+
- **Format/Lint:** Run `make -f Makefile.format format` to apply `clang-format` to all C/H files in `main/` (uses `.clang-format` style).
26+
27+
## Project Conventions
28+
- **All C source files in `main/` are auto-included in the build.**
29+
- **Component registration:** See `main/CMakeLists.txt` and `main/component.mk` for build inclusion.
30+
- **Logging:** Uses ESP-IDF logging (`esp_log.h`). Tag constants are in `log_tags.h`.
31+
- **Secrets:** Never hardcode secrets; use NVS helpers and `config_secrets.h` API.
32+
- **Partition Table:** Custom partition table in `partitions.csv`.
33+
- **No C++/RTTI/exceptions:** Project is C-only, no C++ features enabled in config.
34+
- **API Documentation:** Public APIs in headers (e.g., `nvs_helper.h`) use Doxygen-style comments for clarity.
35+
36+
## Integration & Patterns
37+
- **BLE and WiFi run concurrently.** BLE GATT server is always active; WiFi captive portal is started for setup.
38+
- **NVS is used for all persistent config/secrets.**
39+
- **PC test harness** (`cert-test`) is for validating handshake/cert logic outside ESP32.
40+
- **Unit tests for helpers:** Add C unit tests in `main/pc/` and build with `make -f Makefile.test test-nvs-helper` (see `main/pc/test_nvs_helper.c`).
41+
- **All hardware abstraction is in `main/` (no `components/` folder used).**
42+
43+
## Examples
44+
- To add a new BLE service: see `pgp_gatts.c` and follow the pattern for service/characteristic registration.
45+
- To persist new config: add NVS helpers in `nvs_helper.c` and expose via `settings.c` or `config_secrets.c`.
46+
- To add a new helper unit test: create a test in `main/pc/`, add a target to `Makefile.test`, and document in `main/pc/README.md`.
47+
48+
## Do/Don't
49+
- **Do**: Use ESP-IDF APIs, follow file/module patterns, keep all logic in `main/`.
50+
- **Do**: Use `clang-format` and Doxygen-style comments for new code/APIs.
51+
- **Don't**: Add new folders at top-level, use C++/RTTI, hardcode secrets, or edit `build/`.
52+
53+
For more, see source comments in each file. Update this file if project structure or conventions change.

pgpemu-esp32/Makefile

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,5 @@
1-
#
2-
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
3-
# project subdirectory.
4-
#
5-
61
PROJECT_NAME := pgpemu
72

83
COMPONENT_ADD_INCLUDEDIRS := components/include
94

105
include $(IDF_PATH)/make/project.mk
11-

pgpemu-esp32/Makefile.format

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Format all C source files in the project using clang-format
2+
3+
CLANG_FORMAT ?= clang-format
4+
5+
format:
6+
find main -name '*.c' -o -name '*.h' | xargs $(CLANG_FORMAT) -i --style=file
7+
8+
.PHONY: format

pgpemu-esp32/Makefile.test

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
1+
12
# build cert-test for PC to test app/device handshake
23
cert-test: main/pc/*.c main/pgp_cert.c main/secrets.c
34
gcc -Wall -Imain $^ -o cert-test
45

6+
# build and run nvs_helper unit test
7+
test-nvs-helper: main/pc/test_nvs_helper.c main/nvs_helper.c
8+
gcc -Wall -Imain $^ -o test-nvs-helper
9+
10+
511
.PHONY: clean
612
clean:
7-
rm -f cert-test
13+
rm -f cert-test test-nvs-helper

pgpemu-esp32/main/button_input.c

Lines changed: 17 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,31 @@
1+
#include "button_input.h"
2+
13
#include "driver/gpio.h"
24
#include "esp_err.h"
35
#include "esp_log.h"
46
#include "freertos/FreeRTOS.h"
57
#include "freertos/FreeRTOSConfig.h"
68
#include "freertos/queue.h"
79
#include "freertos/task.h"
8-
9-
#include "button_input.h"
10-
#include "pgp_handshake_multi.h"
11-
#include "pgp_gap.h"
1210
#include "led_output.h"
1311
#include "log_tags.h"
12+
#include "pgp_gap.h"
13+
#include "pgp_handshake_multi.h"
1414
#include "settings.h"
1515

1616
static const int CONFIG_GPIO_INPUT_BUTTON0 = GPIO_NUM_3;
1717

18-
static void button_input_task(void *pvParameters);
18+
static void button_input_task(void* pvParameters);
1919
static QueueHandle_t button_input_queue;
2020

21-
int get_button_gpio()
22-
{
23-
return CONFIG_GPIO_INPUT_BUTTON0;
24-
}
21+
int get_button_gpio() { return CONFIG_GPIO_INPUT_BUTTON0; }
2522

26-
static void IRAM_ATTR gpio_isr_handler(void *arg)
27-
{
23+
static void IRAM_ATTR gpio_isr_handler(void* arg) {
2824
uint32_t gpio_num = (uint32_t)arg;
2925
xQueueSendFromISR(button_input_queue, &gpio_num, NULL);
3026
}
3127

32-
void init_button_input()
33-
{
28+
void init_button_input() {
3429
// create a queue to handle gpio event from isr
3530
// use size 1 to drop further button events while a press is being handled in the task
3631
button_input_queue = xQueueCreate(1, sizeof(uint32_t));
@@ -47,28 +42,25 @@ void init_button_input()
4742
// install gpio isr service
4843
gpio_install_isr_service(0);
4944
// hook isr handler for specific gpio pin
50-
gpio_isr_handler_add(CONFIG_GPIO_INPUT_BUTTON0, gpio_isr_handler, (void *)CONFIG_GPIO_INPUT_BUTTON0);
45+
gpio_isr_handler_add(CONFIG_GPIO_INPUT_BUTTON0, gpio_isr_handler,
46+
(void*)CONFIG_GPIO_INPUT_BUTTON0);
5147

5248
// start gpio task
5349
xTaskCreate(button_input_task, "button_input", 2048, NULL, 15, NULL);
5450
}
5551

56-
static void button_input_task(void *pvParameters)
57-
{
52+
static void button_input_task(void* pvParameters) {
5853
uint32_t button_event;
5954

6055
ESP_LOGI(BUTTON_INPUT_TAG, "task start");
6156

62-
while (true)
63-
{
64-
if (xQueueReceive(button_input_queue, &button_event, portMAX_DELAY))
65-
{
57+
while (true) {
58+
if (xQueueReceive(button_input_queue, &button_event, portMAX_DELAY)) {
6659
ESP_LOGV(BUTTON_INPUT_TAG, "button0 down");
6760

6861
// debounce
6962
vTaskDelay(200 / portTICK_PERIOD_MS);
70-
if (gpio_get_level(CONFIG_GPIO_INPUT_BUTTON0) != 0)
71-
{
63+
if (gpio_get_level(CONFIG_GPIO_INPUT_BUTTON0) != 0) {
7264
// not pressed anymore
7365
continue;
7466
}
@@ -78,22 +70,17 @@ static void button_input_task(void *pvParameters)
7870

7971
int target_active_connections = get_setting_uint8(&settings.target_active_connections);
8072
int active_connections = get_active_connections();
81-
if (active_connections < target_active_connections)
82-
{
73+
if (active_connections < target_active_connections) {
8374
// target connections not reached, so we should be advertising currently
8475
ESP_LOGI(BUTTON_INPUT_TAG, "button -> don't advertise");
8576
pgp_advertise_stop();
8677
show_rgb_event(false, false, false, 0);
87-
}
88-
else if (active_connections + 1 <= CONFIG_BT_ACL_CONNECTIONS)
89-
{
78+
} else if (active_connections + 1 <= CONFIG_BT_ACL_CONNECTIONS) {
9079
// target connections reached but more connections still possible
9180
ESP_LOGI(BUTTON_INPUT_TAG, "button -> advertise");
9281
pgp_advertise();
9382
show_rgb_event(false, false, true, 0);
94-
}
95-
else
96-
{
83+
} else {
9784
ESP_LOGW(BUTTON_INPUT_TAG, "button -> max. BT connections reached");
9885
show_rgb_event(true, false, false, 200);
9986
}

pgpemu-esp32/main/captive_dns.c

Lines changed: 40 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -6,69 +6,76 @@
66
*/
77
#include "captive_dns.h"
88

9+
#include <string.h>
10+
911
#include "esp_err.h"
1012
#include "esp_log.h"
11-
12-
#include "lwip/udp.h"
13-
#include "lwip/ip_addr.h"
1413
#include "lwip/inet.h"
14+
#include "lwip/ip_addr.h"
1515
#include "lwip/pbuf.h"
16-
#include <string.h>
16+
#include "lwip/udp.h"
1717

18-
static const char *TAG = "captive_dns";
18+
static const char* TAG = "captive_dns";
1919

20-
static struct udp_pcb *s_pcb; // UDP handle
21-
static ip_addr_t s_target_ip; // IP we point every host to
20+
static struct udp_pcb* s_pcb; // UDP handle
21+
static ip_addr_t s_target_ip; // IP we point every host to
2222

2323
/* ---------- very small DNS helper ---------- */
2424

25-
static void dns_recv_cb(void *arg, struct udp_pcb *pcb,
26-
struct pbuf *p, const ip_addr_t *addr, u16_t port)
27-
{
28-
if (!p) return;
25+
static void dns_recv_cb(void* arg, struct udp_pcb* pcb, struct pbuf* p, const ip_addr_t* addr,
26+
u16_t port) {
27+
if (!p)
28+
return;
2929

3030
/* copy the whole packet into RAM (max 512 B for DNS over UDP) */
3131
uint8_t buf[512];
32-
if (p->tot_len > sizeof(buf)) { // ignore oversize queries
32+
if (p->tot_len > sizeof(buf)) { // ignore oversize queries
3333
pbuf_free(p);
3434
return;
3535
}
3636
pbuf_copy_partial(p, buf, p->tot_len, 0);
3737
uint16_t qdcount = (buf[4] << 8) | buf[5];
38-
if (qdcount == 0) { // malformed – drop
38+
if (qdcount == 0) { // malformed – drop
3939
pbuf_free(p);
4040
return;
4141
}
4242

4343
/* build DNS response in-place --------------------------------- */
44-
buf[2] = 0x81; // QR=1, Opcode=0, AA=1
45-
buf[3] = 0x80; // RA=0, RCODE=0
46-
buf[6] = buf[4]; // ANCOUNT = QDCOUNT
44+
buf[2] = 0x81; // QR=1, Opcode=0, AA=1
45+
buf[3] = 0x80; // RA=0, RCODE=0
46+
buf[6] = buf[4]; // ANCOUNT = QDCOUNT
4747
buf[7] = buf[5];
48-
buf[8] = buf[9] = buf[10] = buf[11] = 0; // NSCOUNT, ARCOUNT = 0
48+
buf[8] = buf[9] = buf[10] = buf[11] = 0; // NSCOUNT, ARCOUNT = 0
4949

50-
size_t idx = 12; // skip header
50+
size_t idx = 12; // skip header
5151
/* skip over all questions */
5252
for (uint16_t q = 0; q < qdcount; ++q) {
53-
while (idx < p->tot_len && buf[idx] != 0) // labels
53+
while (idx < p->tot_len && buf[idx] != 0) // labels
5454
idx += buf[idx] + 1;
55-
idx += 5; // zero + type + class
55+
idx += 5; // zero + type + class
5656
}
5757
/* append one answer per question */
5858
for (uint16_t q = 0; q < qdcount; ++q) {
59-
buf[idx++] = 0xC0; buf[idx++] = 0x0C; // name pointer to 0x0c
60-
buf[idx++] = 0x00; buf[idx++] = 0x01; // TYPE = A
61-
buf[idx++] = 0x00; buf[idx++] = 0x01; // CLASS = IN
62-
buf[idx++] = 0x00; buf[idx++] = 0x00; buf[idx++] = 0x00; buf[idx++] = 0x1E; // TTL 30 s
63-
buf[idx++] = 0x00; buf[idx++] = 0x04; // RDLEN = 4
59+
buf[idx++] = 0xC0;
60+
buf[idx++] = 0x0C; // name pointer to 0x0c
61+
buf[idx++] = 0x00;
62+
buf[idx++] = 0x01; // TYPE = A
63+
buf[idx++] = 0x00;
64+
buf[idx++] = 0x01; // CLASS = IN
65+
buf[idx++] = 0x00;
66+
buf[idx++] = 0x00;
67+
buf[idx++] = 0x00;
68+
buf[idx++] = 0x1E; // TTL 30 s
69+
buf[idx++] = 0x00;
70+
buf[idx++] = 0x04; // RDLEN = 4
6471
uint32_t ip_be = lwip_htonl( /* RDATA must be big-endian */
65-
ip4_addr_get_u32( /* get uint32_t */
66-
ip_2_ip4(&s_target_ip)));
67-
memcpy(&buf[idx], &ip_be, sizeof(ip_be)); // RDATA = target IPv4
72+
ip4_addr_get_u32(/* get uint32_t */
73+
ip_2_ip4(&s_target_ip)));
74+
memcpy(&buf[idx], &ip_be, sizeof(ip_be)); // RDATA = target IPv4
6875
idx += 4;
6976
}
7077

71-
struct pbuf *resp = pbuf_alloc(PBUF_TRANSPORT, idx, PBUF_RAM);
78+
struct pbuf* resp = pbuf_alloc(PBUF_TRANSPORT, idx, PBUF_RAM);
7279
if (resp) {
7380
pbuf_take(resp, buf, idx);
7481
udp_sendto(pcb, resp, addr, port);
@@ -79,8 +86,7 @@ static void dns_recv_cb(void *arg, struct udp_pcb *pcb,
7986

8087
/* ---------- public API ------------------------------------------ */
8188

82-
esp_err_t captive_dns_start(const char *ip_str)
83-
{
89+
esp_err_t captive_dns_start(const char* ip_str) {
8490
if (s_pcb) {
8591
ESP_LOGW(TAG, "already running");
8692
return ESP_OK;
@@ -90,7 +96,8 @@ esp_err_t captive_dns_start(const char *ip_str)
9096
}
9197

9298
s_pcb = udp_new_ip_type(IPADDR_TYPE_V4);
93-
if (!s_pcb) return ESP_ERR_NO_MEM;
99+
if (!s_pcb)
100+
return ESP_ERR_NO_MEM;
94101

95102
err_t err = udp_bind(s_pcb, IP_ADDR_ANY, 53);
96103
if (err != ERR_OK) {
@@ -105,8 +112,7 @@ esp_err_t captive_dns_start(const char *ip_str)
105112
return ESP_OK;
106113
}
107114

108-
void captive_dns_stop(void)
109-
{
115+
void captive_dns_stop(void) {
110116
if (s_pcb) {
111117
udp_remove(s_pcb);
112118
s_pcb = NULL;

pgpemu-esp32/main/captive_dns.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@
44
/* Start a wildcard DNS server that redirects every domain to ip_str
55
* (must be dotted-decimal, e.g. "192.168.4.1").
66
*/
7-
esp_err_t captive_dns_start(const char *ip_str);
7+
esp_err_t captive_dns_start(const char* ip_str);
88

9-
void captive_dns_stop(void);
9+
void captive_dns_stop(void);

0 commit comments

Comments
 (0)