aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMatthias P. Braendli <matthias.braendli@mpb.li>2024-01-02 14:30:44 +0100
committerMatthias P. Braendli <matthias.braendli@mpb.li>2024-01-02 14:30:44 +0100
commit8d79d7640cadab30ff1e7bfa8df41eb08ffbdf48 (patch)
tree90c5090e070aad6546e1cf198973a10ef25e00fa /src
parent317d81c65dafae1949588cb4a9412d9bdc483a7c (diff)
downloadcats-radio-node-8d79d7640cadab30ff1e7bfa8df41eb08ffbdf48.tar.gz
cats-radio-node-8d79d7640cadab30ff1e7bfa8df41eb08ffbdf48.tar.bz2
cats-radio-node-8d79d7640cadab30ff1e7bfa8df41eb08ffbdf48.zip
Add more pages, improve nav
Diffstat (limited to 'src')
-rw-r--r--src/config.rs57
-rw-r--r--src/main.rs61
2 files changed, 115 insertions, 3 deletions
diff --git a/src/config.rs b/src/config.rs
new file mode 100644
index 0000000..51bf507
--- /dev/null
+++ b/src/config.rs
@@ -0,0 +1,57 @@
+use std::fs;
+use anyhow::Context;
+use serde::{Deserialize, Serialize};
+
+#[derive(Serialize, Deserialize, Clone)]
+pub struct FelinetConfig {
+ pub enabled: bool,
+ pub address: String,
+}
+
+#[derive(Serialize, Deserialize, Clone)]
+pub struct TunnelConfig {
+ pub enabled: bool,
+ pub local_ip: String,
+ pub netmask: String,
+}
+
+type DurationSeconds = std::num::NonZeroU32;
+
+#[derive(Serialize, Deserialize, Clone)]
+pub struct BeaconConfig {
+ pub period_seconds: Option<DurationSeconds>,
+ #[serde(default)]
+ pub max_hops: u8,
+ pub latitude: Option<f64>,
+ pub longitude: Option<f64>,
+ pub altitude: Option<f64>,
+ pub comment: Option<String>,
+ pub antenna_height: Option<u8>,
+ pub antenna_gain: Option<f32>,
+ pub tx_power: Option<f32>,
+}
+
+#[derive(Serialize, Deserialize, Clone)]
+pub struct Config {
+ pub callsign: String,
+ pub ssid: u8,
+ #[serde(default)]
+ pub icon: u16,
+ pub felinet: FelinetConfig,
+ pub beacon: BeaconConfig,
+ pub tunnel: Option<TunnelConfig>,
+}
+
+const CONFIGFILE : &str = "node-config.toml";
+
+impl Config {
+ pub fn load() -> anyhow::Result<Self> {
+ let file_contents = fs::read_to_string(CONFIGFILE)?;
+ toml::from_str(&file_contents).context("parsing config file")
+ }
+
+ pub fn store(&self) -> anyhow::Result<()> {
+ fs::write(CONFIGFILE, toml::to_string_pretty(&self)?)
+ .context("writing config file")
+ }
+}
diff --git a/src/main.rs b/src/main.rs
index 1850e66..cab477c 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -11,6 +11,8 @@ use axum::{
use sqlx::{Connection, SqliteConnection};
use tower_http::services::ServeDir;
+mod config;
+
struct AppState {
callsign : String,
db : Mutex<SqliteConnection>
@@ -20,6 +22,9 @@ type SharedState = Arc<AppState>;
#[tokio::main]
async fn main() -> std::io::Result<()> {
+
+ // simple_logger::
+
let mut conn = SqliteConnection::connect("sqlite:cats-radio-node.db").await.unwrap();
sqlx::migrate!()
.run(&mut conn)
@@ -35,6 +40,9 @@ async fn main() -> std::io::Result<()> {
let app = Router::new()
.route("/", get(dashboard))
+ .route("/incoming", get(incoming))
+ .route("/send", get(send))
+ .route("/settings", get(settings))
.route("/form", get(show_form).post(accept_form))
.nest_service("/static", ServeDir::new("static"))
/* requires tracing and tower, e.g.
@@ -70,6 +78,7 @@ enum ActivePage {
Dashboard,
Incoming,
Send,
+ Settings,
}
#[derive(Template)]
@@ -80,9 +89,7 @@ struct DashboardTemplate<'a> {
callsign: String,
}
-async fn dashboard(
- State(state): State<SharedState>,
- ) -> DashboardTemplate<'static> {
+async fn dashboard(State(state): State<SharedState>) -> DashboardTemplate<'static> {
DashboardTemplate {
title: "Dashboard",
callsign: state.callsign.clone(),
@@ -90,6 +97,54 @@ async fn dashboard(
}
}
+#[derive(Template)]
+#[template(path = "incoming.html")]
+struct IncomingTemplate<'a> {
+ title: &'a str,
+ page: ActivePage,
+ callsign: String,
+}
+
+async fn incoming(State(state): State<SharedState>) -> IncomingTemplate<'static> {
+ IncomingTemplate {
+ title: "Incoming",
+ callsign: state.callsign.clone(),
+ page: ActivePage::Incoming,
+ }
+}
+
+#[derive(Template)]
+#[template(path = "send.html")]
+struct SendTemplate<'a> {
+ title: &'a str,
+ page: ActivePage,
+ callsign: String,
+}
+
+async fn send(State(state): State<SharedState>) -> SendTemplate<'static> {
+ SendTemplate {
+ title: "Send",
+ callsign: state.callsign.clone(),
+ page: ActivePage::Send,
+ }
+}
+
+#[derive(Template)]
+#[template(path = "settings.html")]
+struct SettingsTemplate<'a> {
+ title: &'a str,
+ page: ActivePage,
+ callsign: String,
+}
+
+async fn settings(State(state): State<SharedState>) -> SettingsTemplate<'static> {
+ SettingsTemplate {
+ title: "Settings",
+ callsign: state.callsign.clone(),
+ page: ActivePage::Settings,
+ }
+}
+
async fn show_form() -> Html<&'static str> {
Html(
r#"