Initial commit master
authorGreg Burri <greg.burri@gmail.com>
Sun, 3 Nov 2024 00:30:01 +0000 (01:30 +0100)
committerGreg Burri <greg.burri@gmail.com>
Sun, 3 Nov 2024 00:30:01 +0000 (01:30 +0100)
.gitignore [new file with mode: 0644]
Cargo.toml [new file with mode: 0644]
deploy.nu [new file with mode: 0644]
src/config.rs [new file with mode: 0644]
src/main.rs [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..9a5d03d
--- /dev/null
@@ -0,0 +1,4 @@
+/target
+config.ron
+Cargo.lock
+deploy-to-ek.nu
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644 (file)
index 0000000..2a692d9
--- /dev/null
@@ -0,0 +1,21 @@
+[package]
+name = "rpi_keep_alive"
+version = "0.1.0"
+authors = ["Greg Burri <greg.burri@gmail.com>"]
+edition = "2021"
+
+[dependencies]
+rand = "0.8"
+
+serde = { version = "1.0", features = ["derive"] }
+serde_json = "1.0"
+ron = "0.8"
+
+ping = "0.5"
+
+anyhow = "1"
+
+[profile.release]
+codegen-units = 1
+lto = true
+panic = 'abort'
diff --git a/deploy.nu b/deploy.nu
new file mode 100644 (file)
index 0000000..a30499b
--- /dev/null
+++ b/deploy.nu
@@ -0,0 +1,35 @@
+# 'zigbuild' is needed to build for target 'x86_64-unknown-linux-gnu' on linux:
+# https://github.com/rust-cross/cargo-zigbuild
+
+def main [host: string, destination: string, ssh_key: path] {
+    let ssh_args = [-i $ssh_key $host]
+    let scp_args = [-r -i $ssh_key]
+    let target = "x86_64-unknown-linux-gnu"
+    let app_name = "rpi_keep_alive"
+    let build = "release" # "debug" or "release".
+
+    def invoke_ssh [command: string] {
+        let args = $ssh_args ++ $command
+        print $"Executing: ssh ($args)"
+        ssh ...$args
+    }
+
+    def copy_ssh [source: string, destination: string] {
+        let args = $scp_args ++ [$source $"($host):($destination)"]
+        print $"Executing: scp ($args)"
+        scp ...$args
+    }
+
+    # Don't know how to dynamically pass variable arguments.
+    if $build == "release" {
+        cargo zigbuild --target $target --release
+    } else {
+        cargo zigbuild --target $target
+    }
+
+    # invoke_ssh $"systemctl stop ($app_name)"
+    copy_ssh ./target/($target)/($build)/($app_name) $destination
+    invoke_ssh $"chmod u+x ($destination)/($app_name)"
+    # invoke_ssh $"systemctl start ($app_name)"
+    print "Deployment finished"
+}
\ No newline at end of file
diff --git a/src/config.rs b/src/config.rs
new file mode 100644 (file)
index 0000000..09d81dd
--- /dev/null
@@ -0,0 +1,36 @@
+use std::{fs::File, time::Duration};
+
+use anyhow::Result;
+use ron::{
+    de::from_reader,
+    ser::{to_writer_pretty, PrettyConfig},
+};
+use serde::{Deserialize, Serialize};
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct Config {
+    pub address: String,
+    pub duration: Duration,
+}
+
+impl Config {
+    pub fn default() -> Self {
+        Config {
+            address: "192.168.2.1".to_string(),
+            duration: Duration::from_secs(60),
+        }
+    }
+
+    pub fn read(file_path: &str) -> Result<Config> {
+        match File::open(file_path) {
+            Ok(file) => from_reader(file).map_err(|e| e.into()),
+            // The file doesn't exit -> create it with default values.
+            Err(_) => {
+                let file = File::create(file_path)?;
+                let default_config = Config::default();
+                to_writer_pretty(file, &default_config, PrettyConfig::new())?;
+                Ok(default_config)
+            }
+        }
+    }
+}
diff --git a/src/main.rs b/src/main.rs
new file mode 100644 (file)
index 0000000..6d877bb
--- /dev/null
@@ -0,0 +1,45 @@
+use std::{
+    fmt,
+    net::{IpAddr, Ipv4Addr, UdpSocket},
+    str::FromStr,
+    thread,
+    time::{self, Duration},
+};
+
+use anyhow::Result;
+use ping::rawsock::ping;
+
+use crate::config::Config;
+
+mod config;
+
+const FILE_CONF: &str = "config.ron";
+const PING_TIMEOUT: Duration = Duration::from_secs(5);
+
+fn main() -> Result<()> {
+    println!("Raspberry Keep Alive");
+
+    let config = Config::read(FILE_CONF)?;
+    let ip_addr = IpAddr::V4(Ipv4Addr::from_str(&config.address)?);
+
+    println!("Configuration: {:?}", config);
+
+    loop {
+        let time_beginning_loop = time::Instant::now();
+
+        println!("Sending a ping to {}", config.address);
+
+        if let Err(error) = ping(ip_addr, Some(PING_TIMEOUT), None, None, None, None) {
+            println!("Error during ping: {:?}", error);
+        }
+
+        // println!("Time: {:?}", time::Instant::now() - time_beginning_loop);
+
+        let elapsed = time::Instant::now() - time_beginning_loop;
+
+        if elapsed < config.duration {
+            let to_wait = config.duration - elapsed;
+            thread::sleep(to_wait);
+        }
+    }
+}