diff --git a/src/main.rs b/src/main.rs index 0d3e113..0486f1c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -36,6 +36,8 @@ struct Args { enum Command { /// Run as a background daemon providing a web UI. Daemon, + /// Stop the running daemon process. + Kill, } /// Default config content, embedded in the binary. @@ -91,24 +93,65 @@ async fn main() { let log_buffer = logger::setup_logger(); let args = Args::parse(); - if let Some(Command::Daemon) = &args.command { - log::info!("🚀 Starting daemon..."); + if let Some(command) = &args.command { + match command { + Command::Daemon => { + log::info!("🚀 Starting daemon..."); - // Create files for stdout and stderr in the current directory - let stdout = fs::File::create("daemon.out").expect("Could not create daemon.out"); - let stderr = fs::File::create("daemon.err").expect("Could not create daemon.err"); + // Create files for stdout and stderr in the current directory + let stdout = + fs::File::create("daemon.out").expect("Could not create daemon.out"); + let stderr = + fs::File::create("daemon.err").expect("Could not create daemon.err"); - let daemonize = Daemonize::new() - .pid_file("ntp_timeturner.pid") // Create a PID file - .working_directory(".") // Keep the same working directory - .stdout(stdout) - .stderr(stderr); + let daemonize = Daemonize::new() + .pid_file("ntp_timeturner.pid") // Create a PID file + .working_directory(".") // Keep the same working directory + .stdout(stdout) + .stderr(stderr); - match daemonize.start() { - Ok(_) => { /* Process is now daemonized */ } - Err(e) => { - log::error!("Error daemonizing: {}", e); - return; // Exit if daemonization fails + match daemonize.start() { + Ok(_) => { /* Process is now daemonized */ } + Err(e) => { + log::error!("Error daemonizing: {}", e); + return; // Exit if daemonization fails + } + } + } + Command::Kill => { + log::info!("🛑 Stopping daemon..."); + let pid_file = "ntp_timeturner.pid"; + match fs::read_to_string(pid_file) { + Ok(pid_str) => { + let pid_str = pid_str.trim(); + log::info!("Found daemon with PID: {}", pid_str); + match std::process::Command::new("kill").arg("-9").arg(format!("-{}", pid_str)).status() { + Ok(status) => { + if status.success() { + log::info!("✅ Daemon stopped successfully."); + if fs::remove_file(pid_file).is_err() { + log::warn!("Could not remove PID file '{}'. It may need to be removed manually.", pid_file); + } + } else { + log::error!("'kill' command failed with status: {}. The daemon may not be running, or you may not have permission to stop it.", status); + log::warn!("Attempting to remove stale PID file '{}'...", pid_file); + if fs::remove_file(pid_file).is_ok() { + log::info!("Removed stale PID file."); + } else { + log::warn!("Could not remove PID file."); + } + } + } + Err(e) => { + log::error!("Failed to execute 'kill' command. Is 'kill' in your PATH? Error: {}", e); + } + } + } + Err(_) => { + log::error!("Could not read PID file '{}'. Is the daemon running in this directory?", pid_file); + } + } + return; } } } @@ -205,7 +248,9 @@ async fn main() { let state = sync_state.lock().unwrap(); let config = sync_config.lock().unwrap(); - if config.auto_sync_enabled && state.latest.is_some() { + if config.is_auto_sync_paused() { + log::info!("Auto-sync is temporarily paused."); + } else if config.auto_sync_enabled && state.latest.is_some() { let delta = state.get_ewma_clock_delta(); let frame = state.latest.as_ref().unwrap(); diff --git a/src/system.rs b/src/system.rs index 64205b4..77a1aa0 100644 --- a/src/system.rs +++ b/src/system.rs @@ -45,21 +45,13 @@ pub fn calculate_target_time(frame: &LtcFrame, config: &Config) -> DateTime Result<(), ()> { pub fn set_date(date: &str) -> Result<(), ()> { #[cfg(target_os = "linux")] { + let datetime_str = format!("{} 10:00:00", date); let success = Command::new("sudo") .arg("date") .arg("--set") - .arg(date) + .arg(&datetime_str) .status() .map(|s| s.success()) .unwrap_or(false); if success { - log::info!("Set system date to {}", date); + log::info!("Set system date and time to {}", datetime_str); Ok(()) } else { - log::error!("Failed to set system date"); + log::error!("Failed to set system date and time"); Err(()) } } diff --git a/static/assets/FuturaStdHeavy.otf b/static/assets/FuturaStdHeavy.otf new file mode 100644 index 0000000..7b8c22d Binary files /dev/null and b/static/assets/FuturaStdHeavy.otf differ diff --git a/static/assets/quartz-ms-regular.ttf b/static/assets/quartz-ms-regular.ttf new file mode 100644 index 0000000..15c7ce4 Binary files /dev/null and b/static/assets/quartz-ms-regular.ttf differ diff --git a/static/assets/timeturner_controls.png b/static/assets/timeturner_controls.png new file mode 100644 index 0000000..a91f39b Binary files /dev/null and b/static/assets/timeturner_controls.png differ diff --git a/static/assets/timeturner_delta_green.png b/static/assets/timeturner_delta_green.png new file mode 100644 index 0000000..ddc84b9 Binary files /dev/null and b/static/assets/timeturner_delta_green.png differ diff --git a/static/assets/timeturner_delta_orange.png b/static/assets/timeturner_delta_orange.png new file mode 100644 index 0000000..64e9776 Binary files /dev/null and b/static/assets/timeturner_delta_orange.png differ diff --git a/static/assets/timeturner_delta_red.png b/static/assets/timeturner_delta_red.png new file mode 100644 index 0000000..c7272ac Binary files /dev/null and b/static/assets/timeturner_delta_red.png differ diff --git a/static/assets/timeturner_jitter_green.png b/static/assets/timeturner_jitter_green.png new file mode 100644 index 0000000..8cc64e3 Binary files /dev/null and b/static/assets/timeturner_jitter_green.png differ diff --git a/static/assets/timeturner_jitter_orange.png b/static/assets/timeturner_jitter_orange.png new file mode 100644 index 0000000..96c5f84 Binary files /dev/null and b/static/assets/timeturner_jitter_orange.png differ diff --git a/static/assets/timeturner_jitter_red.png b/static/assets/timeturner_jitter_red.png new file mode 100644 index 0000000..8813159 Binary files /dev/null and b/static/assets/timeturner_jitter_red.png differ diff --git a/static/assets/timeturner_logs.png b/static/assets/timeturner_logs.png new file mode 100644 index 0000000..6bdd935 Binary files /dev/null and b/static/assets/timeturner_logs.png differ diff --git a/static/assets/timeturner_ltc_green.png b/static/assets/timeturner_ltc_green.png new file mode 100644 index 0000000..4329913 Binary files /dev/null and b/static/assets/timeturner_ltc_green.png differ diff --git a/static/assets/timeturner_ltc_orange.png b/static/assets/timeturner_ltc_orange.png new file mode 100644 index 0000000..b060ac2 Binary files /dev/null and b/static/assets/timeturner_ltc_orange.png differ diff --git a/static/assets/timeturner_ltc_red.png b/static/assets/timeturner_ltc_red.png new file mode 100644 index 0000000..a8e7f96 Binary files /dev/null and b/static/assets/timeturner_ltc_red.png differ diff --git a/static/assets/timeturner_network.png b/static/assets/timeturner_network.png new file mode 100644 index 0000000..06ec4b9 Binary files /dev/null and b/static/assets/timeturner_network.png differ diff --git a/static/assets/timeturner_ntp_green.png b/static/assets/timeturner_ntp_green.png new file mode 100644 index 0000000..caf824d Binary files /dev/null and b/static/assets/timeturner_ntp_green.png differ diff --git a/static/assets/timeturner_ntp_orange.png b/static/assets/timeturner_ntp_orange.png new file mode 100644 index 0000000..88319b5 Binary files /dev/null and b/static/assets/timeturner_ntp_orange.png differ diff --git a/static/assets/timeturner_ntp_red.png b/static/assets/timeturner_ntp_red.png new file mode 100644 index 0000000..16e66ee Binary files /dev/null and b/static/assets/timeturner_ntp_red.png differ diff --git a/static/assets/timeturner_sync_green.png b/static/assets/timeturner_sync_green.png new file mode 100644 index 0000000..9b4988e Binary files /dev/null and b/static/assets/timeturner_sync_green.png differ diff --git a/static/assets/timeturner_sync_orange.png b/static/assets/timeturner_sync_orange.png new file mode 100644 index 0000000..0b41130 Binary files /dev/null and b/static/assets/timeturner_sync_orange.png differ diff --git a/static/assets/timeturner_sync_red.png b/static/assets/timeturner_sync_red.png new file mode 100644 index 0000000..1c4c4c9 Binary files /dev/null and b/static/assets/timeturner_sync_red.png differ