diff options
| author | Your Name <you@example.com> | 2026-05-19 01:10:06 +0530 |
|---|---|---|
| committer | Your Name <you@example.com> | 2026-05-19 01:10:06 +0530 |
| commit | 42902a36bc52e009a1e8d3c371741e30a9cb4c33 (patch) | |
| tree | 46db33710a3650b2267933a8375d3598af11319a /main/tollgate_main.c | |
| parent | fe7c3be2fd9d464dbc837d1913409d2691bd50f5 (diff) | |
feat: ContextVM (MCP over Nostr) server with full integration
Complete CVM implementation: persistent WebSocket relay listener,
kind 25910 event subscription, MCP protocol handlers, CEP-6 announcements,
10 MCP tools, per-board hardware locks, WiFi EU regulatory fix.
Architecture:
- cvm_server.c: WS relay listener, kind 25910 subscription, MCP dispatch
- mcp_handler.c/h: 10 MCP tools (get_config, set_config, get_balance,
wallet_send, get_sessions, get_usage, set_payout, set_metric,
set_price, wallet_melt)
- Responses published via existing WS connection (not new TLS)
- Auth check: only owner npub accepted
- CEP-6: kinds 11316 (server), 11317 (tools), 10002 (relay list)
- WS ping/pong keepalive every 30s, 60s TLS read timeout
Critical fixes:
- WiFi country code DE (ESP-IDF defaults to CN, breaks EU APs)
- Subscription #p filter must be array not string
- Use-after-free: tags_str freed before nostr_event_to_json
- MCP responses via existing WS (ESP32 can't open multiple TLS)
- EVENT msg buffer underflow, WS frame masking, TLS write loop
Per-board hardware locks:
- Lock files in physical-router-test-automation/locks/
- lock-a/b/c, unlock-a/b/c targets in 3 Makefiles
- All hardware-touching targets require board lock
Verified on Board B via relay.primal.net:
- 282 unit tests passing (61 CVM + 60 MCP + 161 existing)
- MCP initialize roundtrip: PASS
- tools/list: PASS
- tools/call get_config: PASS
- tools/call get_balance: PASS
- tools/call set_price: PASS (write operation)
- CEP-6 announcements (11316, 11317, 10002): all accepted by relay
- WiFi STA connection (EnterSSID-2.4GHz): PASS with country code DE
- Board A WiFi confirmed hardware issue (not firmware)
Diffstat (limited to 'main/tollgate_main.c')
| -rw-r--r-- | main/tollgate_main.c | 21 |
1 files changed, 21 insertions, 0 deletions
diff --git a/main/tollgate_main.c b/main/tollgate_main.c index 1350d70..ad5211a 100644 --- a/main/tollgate_main.c +++ b/main/tollgate_main.c | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include "esp_netif.h" | 9 | #include "esp_netif.h" |
| 10 | #include "lwip/netif.h" | 10 | #include "lwip/netif.h" |
| 11 | #include "lwip/dns.h" | 11 | #include "lwip/dns.h" |
| 12 | #include "esp_sntp.h" | ||
| 12 | #include "dhcpserver/dhcpserver.h" | 13 | #include "dhcpserver/dhcpserver.h" |
| 13 | #include "config.h" | 14 | #include "config.h" |
| 14 | #include "identity.h" | 15 | #include "identity.h" |
| @@ -22,6 +23,7 @@ | |||
| 22 | #include "tollgate_client.h" | 23 | #include "tollgate_client.h" |
| 23 | #include "lightning_payout.h" | 24 | #include "lightning_payout.h" |
| 24 | #include "cvm_server.h" | 25 | #include "cvm_server.h" |
| 26 | #include "display.h" | ||
| 25 | 27 | ||
| 26 | #define MAX_STA_RETRY 5 | 28 | #define MAX_STA_RETRY 5 |
| 27 | static const char *TAG = "tollgate_main"; | 29 | static const char *TAG = "tollgate_main"; |
| @@ -54,6 +56,7 @@ static void wifi_event_handler(void *arg, esp_event_base_t event_base, | |||
| 54 | tollgate_client_on_sta_disconnected(); | 56 | tollgate_client_on_sta_disconnected(); |
| 55 | if (s_services_running) stop_services(); | 57 | if (s_services_running) stop_services(); |
| 56 | if (s_retry_count < MAX_STA_RETRY) { | 58 | if (s_retry_count < MAX_STA_RETRY) { |
| 59 | vTaskDelay(pdMS_TO_TICKS(2000)); | ||
| 57 | esp_wifi_connect(); | 60 | esp_wifi_connect(); |
| 58 | } else { | 61 | } else { |
| 59 | wifi_config_t wifi_cfg; | 62 | wifi_config_t wifi_cfg; |
| @@ -94,6 +97,13 @@ static void ip_event_handler(void *arg, esp_event_base_t event_base, | |||
| 94 | s_retry_count = 0; | 97 | s_retry_count = 0; |
| 95 | xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT); | 98 | xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT); |
| 96 | 99 | ||
| 100 | esp_sntp_stop(); | ||
| 101 | esp_sntp_setoperatingmode(SNTP_OPMODE_POLL); | ||
| 102 | esp_sntp_setservername(0, "pool.ntp.org"); | ||
| 103 | esp_sntp_setservername(1, "time.google.com"); | ||
| 104 | esp_sntp_init(); | ||
| 105 | ESP_LOGI(TAG, "SNTP time sync started"); | ||
| 106 | |||
| 97 | char gw_ip_str[16]; | 107 | char gw_ip_str[16]; |
| 98 | snprintf(gw_ip_str, sizeof(gw_ip_str), IPSTR, IP2STR(&event->ip_info.gw)); | 108 | snprintf(gw_ip_str, sizeof(gw_ip_str), IPSTR, IP2STR(&event->ip_info.gw)); |
| 99 | tollgate_client_on_sta_connected(gw_ip_str); | 109 | tollgate_client_on_sta_connected(gw_ip_str); |
| @@ -160,6 +170,11 @@ static void start_services(void) | |||
| 160 | s_services_running = true; | 170 | s_services_running = true; |
| 161 | if (s_services_mutex) xSemaphoreGive(s_services_mutex); | 171 | if (s_services_mutex) xSemaphoreGive(s_services_mutex); |
| 162 | ESP_LOGI(TAG, "=== TollGate services started ==="); | 172 | ESP_LOGI(TAG, "=== TollGate services started ==="); |
| 173 | |||
| 174 | display_set_state(DISPLAY_READY); | ||
| 175 | char portal_url[128]; | ||
| 176 | snprintf(portal_url, sizeof(portal_url), "http://%s/", cfg->ap_ip_str); | ||
| 177 | display_update(cfg->ap_ssid, 0, 0, portal_url); | ||
| 163 | } | 178 | } |
| 164 | 179 | ||
| 165 | static void stop_services(void) | 180 | static void stop_services(void) |
| @@ -240,6 +255,9 @@ void app_main(void) | |||
| 240 | { | 255 | { |
| 241 | ESP_LOGI(TAG, "=== TollGate ESP32 Starting ==="); | 256 | ESP_LOGI(TAG, "=== TollGate ESP32 Starting ==="); |
| 242 | 257 | ||
| 258 | display_init(); | ||
| 259 | display_set_state(DISPLAY_BOOT); | ||
| 260 | |||
| 243 | esp_err_t ret = nvs_flash_init(); | 261 | esp_err_t ret = nvs_flash_init(); |
| 244 | if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { | 262 | if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { |
| 245 | ESP_ERROR_CHECK(nvs_flash_erase()); | 263 | ESP_ERROR_CHECK(nvs_flash_erase()); |
| @@ -288,6 +306,9 @@ void app_main(void) | |||
| 288 | ESP_LOGI(TAG, "STA configured for SSID: %s", tcfg2->networks[tcfg2->current_network].ssid); | 306 | ESP_LOGI(TAG, "STA configured for SSID: %s", tcfg2->networks[tcfg2->current_network].ssid); |
| 289 | } | 307 | } |
| 290 | 308 | ||
| 309 | ESP_ERROR_CHECK(esp_wifi_set_country_code("DE", false)); | ||
| 310 | ESP_LOGI(TAG, "WiFi country code set to DE (EU regulatory domain)"); | ||
| 311 | |||
| 291 | ESP_ERROR_CHECK(esp_wifi_start()); | 312 | ESP_ERROR_CHECK(esp_wifi_start()); |
| 292 | 313 | ||
| 293 | ESP_LOGI(TAG, "WiFi AP+STA started, waiting for connection..."); | 314 | ESP_LOGI(TAG, "WiFi AP+STA started, waiting for connection..."); |