From e5b72bbb20fa2c59486d8c077615abaf294ddcee Mon Sep 17 00:00:00 2001 From: Patedam Date: Sat, 28 Mar 2026 15:38:38 -0400 Subject: [PATCH] updated tdd for http client --- Provider/tdd/http_client_component.md | 60 +++++++++++++++++++++++---- 1 file changed, 52 insertions(+), 8 deletions(-) diff --git a/Provider/tdd/http_client_component.md b/Provider/tdd/http_client_component.md index 9781fb3..9b19454 100644 --- a/Provider/tdd/http_client_component.md +++ b/Provider/tdd/http_client_component.md @@ -168,16 +168,34 @@ menu "Calendink Client" endmenu ``` -#### main.cpp Test Flow +#### Client File Structure -After WiFi connects successfully: +Provider communication logic is in its own file, not in `main.cpp`: ``` -1. Resolve Provider IP via mdns_query_host("calendink", timeout) - - On success: use resolved IP - - On failure: fall back to CONFIG_CALENDINK_PROVIDER_FALLBACK_IP if set, else abort +Client/main/ +├── CMakeLists.txt # SRCS: main.cpp, provider.cpp +├── Kconfig.projbuild # Provider connection settings +├── idf_component.yml # Dependencies: network, led, http_client, espressif/mdns +├── main.cpp # Boot, NVS, WiFi connect → calls test_provider_communication() +├── provider.hpp # Header for provider communication +└── provider.cpp # mDNS resolution, device registration, screen fetch +``` -2. Get own MAC: esp_wifi_get_mac(WIFI_IF_STA, mac_bytes) → format "XX:XX:XX:XX:XX:XX" +#### provider.cpp Test Flow + +After network connects (WiFi or Ethernet): + +``` +1. Resolve Provider IP via mdns_query_a("calendink", 5000, &addr) + - On success: use resolved IP + - On failure: runtime check strlen(CONFIG_CALENDINK_PROVIDER_FALLBACK_IP) > 0 + - If set: use fallback IP + - If empty: abort with error log + +2. Get own MAC via get_mac_address(mac_bytes) from the network component + - Returns Ethernet MAC if connected via Ethernet, WiFi MAC if via WiFi + - Format as "XX:XX:XX:XX:XX:XX" 3. POST /api/devices/register - Body: {"mac": "XX:XX:XX:XX:XX:XX"} @@ -185,17 +203,22 @@ After WiFi connects successfully: - Free response 4. GET /api/devices/screen.png?mac=XX:XX:XX:XX:XX:XX + - Download full PNG into memory - Log: status code + received byte count - - Free response (we don't use the image data yet) + - Free response ``` #### Dependencies Added to Client | File | Change | |---|---| -| `Client/main/idf_component.yml` | Add `http_client: path: "../../components/http_client"` | +| `Client/main/idf_component.yml` | Add `http_client` (local path) + `espressif/mdns: ^1.4.1` (managed) | | `Client/main/CMakeLists.txt` | Add `http_client` and `mdns` to `PRIV_REQUIRES` | +#### Network Component Changes + +`get_mac_address(uint8_t *mac_out)` was added to `network.hpp` / `network.cpp`. It uses `esp_netif_get_mac()` on whichever interface is active — Ethernet preferred, WiFi fallback. This keeps all `esp_wifi` usage inside the network component. + ### 3.5. Component Build Configuration ```cmake @@ -232,5 +255,26 @@ Error: 400 if missing mac param, 404 if device not registered, 500 on render We add a new shared component `http_client` that wraps `esp_http_client` in a simple synchronous API with `http_get_text()`, `http_get_binary()`, and `http_post_json()`. The component is generic — it takes host/port/path and knows nothing about mDNS or Kconfig. The Client firmware integrates it by resolving the Provider via mDNS (`calendink.local`), registering itself, and fetching its screen image as a connectivity test. No Provider-side changes are needed. +## 5. Implementation Notes (Post-Development) + +### Decisions Made During Implementation + +1. **File separation** — Provider communication logic was extracted from `main.cpp` into `provider.cpp`/`provider.hpp` to keep `main.cpp` focused on boot/init (~78 lines). This follows the pattern of keeping `main` lean. + +2. **Fallback IP check** — The original plan used a `#if` preprocessor check to test if the fallback IP string was non-empty. This doesn't work because Kconfig string values can't be indexed in preprocessor expressions. Changed to a runtime `strlen()` check, which the compiler optimizes away when the string is a compile-time constant. + +3. **Interface-agnostic MAC** — `get_mac_address()` was added to the `network` component using `esp_netif_get_mac()` (instead of `esp_wifi_get_mac()`). It checks `s_eth_netif` first, then `s_wifi_netif`, making it work for both Ethernet and WiFi connections without the caller needing to know which is active. + +4. **mDNS as managed component** — The Client uses `espressif/mdns: ^1.4.1` from the ESP-IDF component registry (specified in `idf_component.yml`) rather than a local path, since it's an official Espressif component. + +5. **No `esp_wifi` in Client** — The Client project has no direct dependency on `esp_wifi`. All WiFi/Ethernet access goes through the `network` component. This was a deliberate architectural decision to keep the Client decoupled from transport details. + +### Verified On-Device + +- mDNS resolution of `calendink.local` → Provider IP ✅ +- `POST /api/devices/register` → 200 with device MAC ✅ +- `GET /api/devices/screen.png?mac=XX` → 200 with PNG binary data ✅ + --- *Created by Antigravity (Claude Opus 4.6) - 2026-03-28* +*Updated: 2026-03-28 — Post-implementation notes added*