internal data sources (clock, static text), connection indicator, rendering fixes

DataSourceConfig refactored to enum: External/Clock/StaticText. Clock
generates formatted time via chrono, static text emits configured string.

ESP32: connection status indicator (green/red dot bottom-right), per-widget
clear before redraw, RenderEvent enum for local + server messages.

Polling uses DataUpdate instead of ScreenUpdate to avoid wiping widget state.
Empty mappings passthrough raw source data for internal sources.
This commit is contained in:
2026-06-19 11:26:49 +02:00
parent b448fa15fe
commit a51d22649a
25 changed files with 630 additions and 214 deletions

View File

@@ -47,15 +47,23 @@ impl DataSourcePort for HttpJsonAdapter {
type Error = HttpJsonError;
async fn poll(&self, source: &DataSource) -> Result<Value, Self::Error> {
let url = source.config.url.as_ref().ok_or(HttpJsonError::NoUrl)?;
let domain::DataSourceConfig::External {
ref url,
ref headers,
ref api_key,
} = source.config
else {
return Err(HttpJsonError::NoUrl);
};
let url = url.as_ref().ok_or(HttpJsonError::NoUrl)?;
let mut req = self.client.get(url);
for (key, val) in &source.config.headers {
for (key, val) in headers {
req = req.header(key, val);
}
if let Some(api_key) = &source.config.api_key {
if let Some(api_key) = api_key {
req = req.header("Authorization", format!("Bearer {api_key}"));
}

View File

@@ -34,7 +34,7 @@ fn make_source(url: String) -> DataSource {
name: "test".into(),
source_type: DataSourceType::HttpJson,
poll_interval: Duration::from_secs(60),
config: DataSourceConfig {
config: DataSourceConfig::External {
url: Some(url),
headers: vec![],
api_key: None,
@@ -82,7 +82,7 @@ async fn returns_error_when_no_url() {
name: "bad".into(),
source_type: DataSourceType::HttpJson,
poll_interval: Duration::from_secs(60),
config: DataSourceConfig {
config: DataSourceConfig::External {
url: None,
headers: vec![],
api_key: None,