Add internet radio streaming with runtime API, modernize web UI, remove auto-tune/beep at boot
Streaming (main feature this session): - New WebRadioConfig/WebRadioJson core types, ISecureStore-backed persistence - New webradio::WebRadioService (thread-safe live config) + GET/POST /api/streaming - web_radio_stream task now runtime-toggleable (no reboot), no hardcoded URL - Content-Type diagnostic: warns clearly when a URL is a webpage, not an audio stream Boot cleanup: - Removed boot-time auto FM/DAB tune, auto-beep, and the (now-concluded) Si4684 crystal IBIAS/CTUN empirical sweep from main.cpp — tuning/beep are on-demand via the existing REST API only Web UI: - Modernized styling (cards, gradients, toggle switches, light/dark theme) - New Stream tab wired to /api/streaming Fixes found via real idf.py build (not just clangd): - Restored wrongly-removed si4684/Si4684Tuner.hpp include in main.cpp - Fixed MP3Decode() argument types in web_radio_stream.cpp (unsigned char**/int*) Quality-gate fixes: - Host-test stub headers (esp_log.h, freertos/*) so TunerService.cpp's scanForStation logging/pacing compiles for station_service_test / integration_service_test instead of running stale binaries - Added WifiScanner and WebRadioService manual sections; filled in missing Doxygen docs on BluetoothService, i2s_sdata_probe, test_firmware, Bt1035At - Ignore clangd's .cache/ index directory Also includes prior uncommitted work carried in the tree: Wi-Fi/Bluetooth device scan REST API and UI (WifiScanner, BT scan), SigmaStudio TCP bridge, and the current ADAU1701 SigmaStudio DSP program export. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -27,6 +27,7 @@
|
||||
#include "secure_store/NvsPlatformInit.hpp"
|
||||
#include "station/StationService.hpp"
|
||||
#include "tuner/TunerService.hpp"
|
||||
#include "webradio/WebRadioService.hpp"
|
||||
|
||||
namespace net {
|
||||
|
||||
@@ -102,10 +103,12 @@ startSetupMode(core::ISecureStore& store, tuner::TunerService& tuner,
|
||||
station::StationService& stations,
|
||||
integration::IntegrationService& integration,
|
||||
ota::OtaService& ota,
|
||||
webradio::WebRadioService& webRadio,
|
||||
core::CompanionChipStatus companionChips,
|
||||
const core::DeviceIdentity& deviceIdentity)
|
||||
{
|
||||
esp_netif_create_default_wifi_ap();
|
||||
esp_netif_create_default_wifi_sta();
|
||||
|
||||
SoftApHost softAp(SoftApConfig::forSsid(deviceIdentity.softApSsid()));
|
||||
if (auto apResult = softAp.start(); !apResult) {
|
||||
@@ -115,17 +118,23 @@ startSetupMode(core::ISecureStore& store, tuner::TunerService& tuner,
|
||||
SetupWebServer webServer;
|
||||
if (auto webResult =
|
||||
webServer.start(store, NetState::SoftApSetup, tuner, audio,
|
||||
bluetooth, stations, integration, ota,
|
||||
bluetooth, stations, integration, ota, webRadio,
|
||||
companionChips, deviceIdentity);
|
||||
!webResult) {
|
||||
return std::unexpected(webResult.error());
|
||||
}
|
||||
|
||||
SigmaStudioTcpServer sigmaStudio;
|
||||
if (auto sigmaResult = sigmaStudio.start(); !sigmaResult) {
|
||||
ESP_LOGW(kTag, "SigmaStudio TCP bridge failed to start — continuing "
|
||||
"without it");
|
||||
}
|
||||
|
||||
ESP_LOGI(kTag, "setup mode ready — SSID %.*s",
|
||||
static_cast<int>(deviceIdentity.softApSsid().size()),
|
||||
deviceIdentity.softApSsid().data());
|
||||
return NetBootstrap(std::move(softAp), std::nullopt, std::move(webServer),
|
||||
NetState::SoftApSetup);
|
||||
std::move(sigmaStudio), NetState::SoftApSetup);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -146,6 +155,7 @@ startStaMode(core::ISecureStore& store, tuner::TunerService& tuner,
|
||||
station::StationService& stations,
|
||||
integration::IntegrationService& integration,
|
||||
ota::OtaService& ota,
|
||||
webradio::WebRadioService& webRadio,
|
||||
core::CompanionChipStatus companionChips,
|
||||
const core::DeviceIdentity& deviceIdentity)
|
||||
{
|
||||
@@ -175,17 +185,23 @@ startStaMode(core::ISecureStore& store, tuner::TunerService& tuner,
|
||||
SetupWebServer webServer;
|
||||
if (auto webResult =
|
||||
webServer.start(store, NetState::StaConnected, tuner, audio,
|
||||
bluetooth, stations, integration, ota,
|
||||
bluetooth, stations, integration, ota, webRadio,
|
||||
companionChips, deviceIdentity);
|
||||
!webResult) {
|
||||
return std::unexpected(webResult.error());
|
||||
}
|
||||
|
||||
SigmaStudioTcpServer sigmaStudio;
|
||||
if (auto sigmaResult = sigmaStudio.start(); !sigmaResult) {
|
||||
ESP_LOGW(kTag, "SigmaStudio TCP bridge failed to start — continuing "
|
||||
"without it");
|
||||
}
|
||||
|
||||
ESP_LOGI(kTag, "STA mode ready — hostname %.*s.local",
|
||||
static_cast<int>(deviceIdentity.hostname().size()),
|
||||
deviceIdentity.hostname().data());
|
||||
return NetBootstrap(std::nullopt, std::move(sta), std::move(webServer),
|
||||
NetState::StaConnected);
|
||||
std::move(sigmaStudio), NetState::StaConnected);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -197,6 +213,7 @@ NetBootstrap::start(core::ISecureStore& store, tuner::TunerService& tuner,
|
||||
station::StationService& stations,
|
||||
integration::IntegrationService& integration,
|
||||
ota::OtaService& ota,
|
||||
webradio::WebRadioService& webRadio,
|
||||
core::CompanionChipStatus companionChips,
|
||||
const core::DeviceIdentity& deviceIdentity)
|
||||
{
|
||||
@@ -210,8 +227,8 @@ NetBootstrap::start(core::ISecureStore& store, tuner::TunerService& tuner,
|
||||
|
||||
if (store.hasWifiCredentials()) {
|
||||
auto staResult = startStaMode(store, tuner, audio, bluetooth, stations,
|
||||
integration, ota, companionChips,
|
||||
deviceIdentity);
|
||||
integration, ota, webRadio,
|
||||
companionChips, deviceIdentity);
|
||||
if (staResult) {
|
||||
return staResult;
|
||||
}
|
||||
@@ -223,16 +240,18 @@ NetBootstrap::start(core::ISecureStore& store, tuner::TunerService& tuner,
|
||||
}
|
||||
|
||||
return startSetupMode(store, tuner, audio, bluetooth, stations, integration,
|
||||
ota, companionChips, deviceIdentity);
|
||||
ota, webRadio, companionChips, deviceIdentity);
|
||||
}
|
||||
|
||||
NetBootstrap::NetBootstrap(std::optional<SoftApHost> softAp,
|
||||
std::optional<StaClient> sta,
|
||||
SetupWebServer webServer,
|
||||
SigmaStudioTcpServer sigmaStudio,
|
||||
NetState state)
|
||||
: softAp_(std::move(softAp))
|
||||
, sta_(std::move(sta))
|
||||
, webServer_(std::move(webServer))
|
||||
, sigmaStudio_(std::move(sigmaStudio))
|
||||
, state_(state)
|
||||
{
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user