client can connect to provider and download an image.

Updated network component to add get mac address
This commit is contained in:
2026-03-28 14:59:49 -04:00
parent 46d1ab6358
commit 2ced2f0b0a
10 changed files with 229 additions and 14 deletions
+21 -1
View File
@@ -121,6 +121,24 @@ dependencies:
registry_url: https://components.espressif.com/
type: service
version: 3.0.3
espressif/mdns:
component_hash: 1ebe3bd675bb9d1c58f52bc0b609b32f74e572b01c328f9e61282040c775495c
dependencies:
- name: idf
require: private
version: '>=5.0'
source:
registry_url: https://components.espressif.com/
type: service
version: 1.11.0
http_client:
dependencies:
- name: idf
version: '>=5.0.0'
source:
path: C:\Dev\Classified\Calendink\components\http_client
type: local
version: 1.0.0
idf:
source:
type: idf
@@ -146,9 +164,11 @@ dependencies:
type: local
version: 1.0.0
direct_dependencies:
- espressif/mdns
- http_client
- idf
- led
- network
manifest_hash: 82be8e1c72b7c09d777d347050aba296d424314ce0b7f7642b5bd08a5e276e54
manifest_hash: 097f2b35eb7bfe4a05687f2391f9fd078cab6437b8459fd420c47d1fa7a3c3d4
target: esp32c6
version: 2.0.0
+4 -3
View File
@@ -1,4 +1,5 @@
idf_component_register(SRCS "main.cpp"
PRIV_REQUIRES driver nvs_flash driver
esp_event esp_timer led network
idf_component_register(SRCS "main.cpp" "provider.cpp"
PRIV_REQUIRES driver nvs_flash
esp_event esp_timer
led network http_client mdns
INCLUDE_DIRS ".")
+23
View File
@@ -0,0 +1,23 @@
menu "Calendink Client"
config CALENDINK_PROVIDER_MDNS_HOSTNAME
string "Provider mDNS Hostname"
default "calendink"
help
The mDNS hostname of the Provider device.
The Client resolves <hostname>.local to find the Provider IP.
config CALENDINK_PROVIDER_PORT
int "Provider HTTP Port"
default 80
help
The HTTP port of the Calendink Provider device.
config CALENDINK_PROVIDER_FALLBACK_IP
string "Provider Fallback IP (if mDNS fails)"
default ""
help
Static IP to use if mDNS resolution fails.
Leave empty to disable fallback.
endmenu
+4 -1
View File
@@ -2,7 +2,10 @@
dependencies:
idf:
version: '>=4.1.0'
espressif/mdns: ^1.4.1
network:
path: "../../components/network"
led:
path: "../../components/led"
path: "../../components/led"
http_client:
path: "../../components/http_client"
+6 -8
View File
@@ -1,19 +1,17 @@
#include <stdio.h>
#include <cstdio>
#include "esp_event.h"
#include "esp_log.h"
#include "esp_pm.h"
#include "esp_system.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "nvs.h"
#include "nvs_flash.h"
#include "sdkconfig.h"
#include "soc/gpio_num.h"
#include "led.hpp"
#include "network.hpp"
#include "types.hpp"
#include "provider.hpp"
static const char *TAG = "ClientMain";
@@ -21,8 +19,7 @@ extern "C" void app_main()
{
ESP_LOGI(TAG, "Hello, Calendink Client!");
// Initialize NVS (required for some Wi-Fi configurations and network
// features)
// Initialize NVS
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND)
{
@@ -35,7 +32,8 @@ extern "C" void app_main()
setup_led();
// Connect to WiFi ESP_LOGI(TAG, "Initializing WiFi connection");
// Connect to WiFi
ESP_LOGI(TAG, "Initializing WiFi connection");
initialize_network();
esp_err_t err = connect_wifi(CONFIG_CALENDINK_WIFI_SSID,
@@ -51,7 +49,6 @@ extern "C" void app_main()
{
ESP_LOGW(TAG, "WiFi connection check timeout, retrying... (%d)",
retries);
led_blink_number(3, 255, 0, 0);
}
retries++;
@@ -62,6 +59,7 @@ extern "C" void app_main()
if (err == ESP_OK)
{
ESP_LOGI(TAG, "Successfully connected to WiFi!");
test_provider_communication();
}
else
{
+142
View File
@@ -0,0 +1,142 @@
// Provider communication — mDNS discovery, device registration, screen fetch.
#include "provider.hpp"
#include <cstdio>
#include <cstring>
#include "esp_log.h"
#include "mdns.h"
#include "sdkconfig.h"
#include "http_client.hpp"
#include "network.hpp"
static const char *TAG = "Provider";
// ── mDNS Provider Discovery ────────────────────────────────────────────────
// Resolve the Provider's IP via mDNS. Returns true and fills `out_ip` on
// success. Falls back to CONFIG_CALENDINK_PROVIDER_FALLBACK_IP if set.
static bool resolve_provider_ip(char *out_ip, size_t out_ip_len)
{
ESP_LOGI(TAG, "Resolving Provider via mDNS: %s.local",
CONFIG_CALENDINK_PROVIDER_MDNS_HOSTNAME);
esp_err_t err = mdns_init();
if (err != ESP_OK)
{
ESP_LOGE(TAG, "mDNS init failed: %s", esp_err_to_name(err));
goto fallback;
}
{
esp_ip4_addr_t addr = {};
err = mdns_query_a(CONFIG_CALENDINK_PROVIDER_MDNS_HOSTNAME, 5000, &addr);
if (err == ESP_OK)
{
snprintf(out_ip, out_ip_len, IPSTR, IP2STR(&addr));
ESP_LOGI(TAG, "Provider resolved: %s", out_ip);
return true;
}
ESP_LOGW(TAG, "mDNS resolution failed: %s", esp_err_to_name(err));
}
fallback:
if (strlen(CONFIG_CALENDINK_PROVIDER_FALLBACK_IP) > 0)
{
strlcpy(out_ip, CONFIG_CALENDINK_PROVIDER_FALLBACK_IP, out_ip_len);
ESP_LOGW(TAG, "Using fallback IP: %s", out_ip);
return true;
}
ESP_LOGE(TAG, "No fallback IP configured. Cannot reach Provider.");
return false;
}
// ── Provider Communication Test ─────────────────────────────────────────────
void test_provider_communication(void)
{
// 1. Resolve Provider IP
char provider_ip[16] = {};
if (!resolve_provider_ip(provider_ip, sizeof(provider_ip)))
{
return;
}
uint16_t provider_port = CONFIG_CALENDINK_PROVIDER_PORT;
// 2. Get our own MAC address
uint8_t mac_bytes[6] = {};
esp_err_t err = get_mac_address(mac_bytes);
if (err != ESP_OK)
{
ESP_LOGE(TAG, "Failed to get WiFi MAC: %s", esp_err_to_name(err));
return;
}
char mac_str[18] = {};
snprintf(mac_str, sizeof(mac_str), "%02X:%02X:%02X:%02X:%02X:%02X",
mac_bytes[0], mac_bytes[1], mac_bytes[2], mac_bytes[3], mac_bytes[4],
mac_bytes[5]);
ESP_LOGI(TAG, "Client MAC: %s", mac_str);
// 3. Register with Provider: POST /api/devices/register
{
char *url =
http_build_url(provider_ip, provider_port, "/api/devices/register");
if (url == nullptr)
{
return;
}
char json_body[64] = {};
snprintf(json_body, sizeof(json_body), "{\"mac\":\"%s\"}", mac_str);
http_text_response_t resp = {};
err = http_post_json(url, json_body, &resp);
if (err == ESP_OK)
{
ESP_LOGI(TAG, "Register response (%d): %s", resp.status_code,
resp.body ? resp.body : "(empty)");
}
else
{
ESP_LOGE(TAG, "Register request failed: %s", esp_err_to_name(err));
}
free(resp.body);
free(url);
}
// 4. Fetch screen image: GET /api/devices/screen.png?mac=XX:XX:XX:XX:XX:XX
{
char path[80] = {};
snprintf(path, sizeof(path), "/api/devices/screen.png?mac=%s", mac_str);
char *url = http_build_url(provider_ip, provider_port, path);
if (url == nullptr)
{
return;
}
http_binary_response_t resp = {};
err = http_get_binary(url, &resp);
if (err == ESP_OK)
{
ESP_LOGI(TAG, "Screen image response (%d): %zu bytes", resp.status_code,
resp.data_len);
}
else
{
ESP_LOGE(TAG, "Screen image request failed: %s", esp_err_to_name(err));
}
free(resp.data);
free(url);
}
}
+5
View File
@@ -0,0 +1,5 @@
#pragma once
// Resolve the Provider's IP and run the device registration + screen fetch
// test flow. Call once after WiFi is connected.
void test_provider_communication(void);
+1 -1
View File
@@ -3,4 +3,4 @@ description: "Calendink HTTP Client Component"
dependencies:
idf:
version: '>=5.0.0'
version: '>=5.0.0'
+19
View File
@@ -452,3 +452,22 @@ internal void blink_last_ip_octet()
}
}
#endif
// === MAC Address ===
esp_err_t get_mac_address(uint8_t *mac_out)
{
// Prefer Ethernet if connected, fall back to WiFi
if (s_eth_netif != nullptr)
{
return esp_netif_get_mac(s_eth_netif, mac_out);
}
if (s_wifi_netif != nullptr)
{
return esp_netif_get_mac(s_wifi_netif, mac_out);
}
ESP_LOGE("NET", "No active network interface for MAC address");
return ESP_ERR_INVALID_STATE;
}
+4
View File
@@ -15,3 +15,7 @@ esp_err_t connect_wifi(const char *ssid, const char *password,
bool blockUntilIPAcquired);
void disconnect_wifi();
esp_err_t check_wifi_connection(uint32_t timeoutSeconds);
// Get the MAC address of the active network interface (WiFi STA).
// mac_out must point to a buffer of at least 6 bytes.
esp_err_t get_mac_address(uint8_t *mac_out);