Files
k-frame/crates/adapters/http-json/src/lib.rs
Gabriel Kaszewski a51d22649a 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.
2026-06-19 11:26:49 +02:00

76 lines
2.0 KiB
Rust

use domain::{DataSource, DataSourcePort, Value};
pub struct HttpJsonAdapter {
client: reqwest::Client,
}
#[derive(Debug, thiserror::Error)]
pub enum HttpJsonError {
#[error("request: {0}")]
Request(#[from] reqwest::Error),
#[error("no url configured")]
NoUrl,
#[error("parse: {0}")]
Parse(String),
}
impl Default for HttpJsonAdapter {
fn default() -> Self {
Self {
client: reqwest::Client::new(),
}
}
}
impl HttpJsonAdapter {
pub fn new() -> Self {
Self::default()
}
}
fn json_to_value(json: serde_json::Value) -> Value {
match json {
serde_json::Value::Null => Value::Null,
serde_json::Value::Bool(b) => Value::Bool(b),
serde_json::Value::Number(n) => Value::Number(n.as_f64().unwrap_or(0.0)),
serde_json::Value::String(s) => Value::String(s),
serde_json::Value::Array(arr) => Value::Array(arr.into_iter().map(json_to_value).collect()),
serde_json::Value::Object(map) => Value::Object(
map.into_iter()
.map(|(k, v)| (k, json_to_value(v)))
.collect(),
),
}
}
impl DataSourcePort for HttpJsonAdapter {
type Error = HttpJsonError;
async fn poll(&self, source: &DataSource) -> Result<Value, Self::Error> {
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 headers {
req = req.header(key, val);
}
if let Some(api_key) = api_key {
req = req.header("Authorization", format!("Bearer {api_key}"));
}
let resp = req.send().await.map_err(HttpJsonError::Request)?;
let json: serde_json::Value = resp.json().await.map_err(HttpJsonError::Request)?;
Ok(json_to_value(json))
}
}