Nareshkumar Rao 7 months ago
parent
commit
8c3ed74faf
  1. 6
      .vscode/tasks.json
  2. 171
      Cargo.lock
  3. 3
      Cargo.toml
  4. 65
      src/control.rs
  5. 1
      src/io.rs
  6. 12
      src/main.rs
  7. 46
      src/server.rs

6
.vscode/tasks.json

@ -4,7 +4,11 @@
{ {
"type": "process", "type": "process",
"command": "cross", "command": "cross",
"args": ["build", "--target","arm-unknown-linux-gnueabihf"],
"args": [
"build",
"--target",
"arm-unknown-linux-gnueabihf"
],
"problemMatcher": [ "problemMatcher": [
"$rustc" "$rustc"
], ],

171
Cargo.lock

@ -27,6 +27,21 @@ dependencies = [
"nb 1.1.0", "nb 1.1.0",
] ]
[[package]]
name = "android-tzdata"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
[[package]]
name = "android_system_properties"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "async-trait" name = "async-trait"
version = "0.1.80" version = "0.1.80"
@ -38,6 +53,12 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "autocfg"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80"
[[package]] [[package]]
name = "axum" name = "axum"
version = "0.7.5" version = "0.7.5"
@ -46,6 +67,7 @@ checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf"
dependencies = [ dependencies = [
"async-trait", "async-trait",
"axum-core", "axum-core",
"axum-macros",
"bytes", "bytes",
"futures-util", "futures-util",
"http", "http",
@ -93,6 +115,18 @@ dependencies = [
"tracing", "tracing",
] ]
[[package]]
name = "axum-macros"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00c055ee2d014ae5981ce1016374e8213682aa14d9bf40e48ab48b5f3ef20eaa"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "backtrace" name = "backtrace"
version = "0.3.71" version = "0.3.71"
@ -114,6 +148,12 @@ version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
[[package]]
name = "bumpalo"
version = "3.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
[[package]] [[package]]
name = "bytes" name = "bytes"
version = "1.6.0" version = "1.6.0"
@ -138,6 +178,20 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
[[package]]
name = "chrono"
version = "0.4.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401"
dependencies = [
"android-tzdata",
"iana-time-zone",
"js-sys",
"num-traits",
"wasm-bindgen",
"windows-targets 0.52.5",
]
[[package]] [[package]]
name = "clipboard-win" name = "clipboard-win"
version = "5.3.1" version = "5.3.1"
@ -147,6 +201,12 @@ dependencies = [
"error-code", "error-code",
] ]
[[package]]
name = "core-foundation-sys"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
[[package]] [[package]]
name = "embedded-hal" name = "embedded-hal"
version = "0.2.7" version = "0.2.7"
@ -272,6 +332,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"ads1x1x", "ads1x1x",
"axum", "axum",
"chrono",
"libc", "libc",
"nb 1.1.0", "nb 1.1.0",
"rppal", "rppal",
@ -287,6 +348,12 @@ version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
[[package]]
name = "heck"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
[[package]] [[package]]
name = "home" name = "home"
version = "0.5.9" version = "0.5.9"
@ -377,6 +444,29 @@ dependencies = [
"tokio", "tokio",
] ]
[[package]]
name = "iana-time-zone"
version = "0.1.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141"
dependencies = [
"android_system_properties",
"core-foundation-sys",
"iana-time-zone-haiku",
"js-sys",
"wasm-bindgen",
"windows-core",
]
[[package]]
name = "iana-time-zone-haiku"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
dependencies = [
"cc",
]
[[package]] [[package]]
name = "indexmap" name = "indexmap"
version = "2.2.6" version = "2.2.6"
@ -393,6 +483,15 @@ version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
[[package]]
name = "js-sys"
version = "0.3.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d"
dependencies = [
"wasm-bindgen",
]
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.153" version = "0.2.153"
@ -485,6 +584,15 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "num-traits"
version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a"
dependencies = [
"autocfg",
]
[[package]] [[package]]
name = "object" name = "object"
version = "0.32.2" version = "0.32.2"
@ -888,6 +996,69 @@ version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
dependencies = [
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
[[package]]
name = "windows-core"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
dependencies = [
"windows-targets 0.52.5",
]
[[package]] [[package]]
name = "windows-sys" name = "windows-sys"
version = "0.48.0" version = "0.48.0"

3
Cargo.toml

@ -11,5 +11,6 @@ nb = "1.1"
rustyline = "14.0" rustyline = "14.0"
serde = { "version" = "1.0", features = ["derive"] } serde = { "version" = "1.0", features = ["derive"] }
toml = "0.8" toml = "0.8"
axum = "0.7"
axum = { "version" = "0.7", features = ["macros"] }
tokio = { "version" = "1.37" } tokio = { "version" = "1.37" }
chrono = "0.4.38"

65
src/control.rs

@ -1,3 +1,64 @@
use crate::state::ProgramStateShared;
use std::time::Duration;
pub fn control_thread(program_state: ProgramStateShared) {}
use chrono::{Local, Timelike};
use tokio::join;
use crate::{
actuators,
error::{lock_err, GenericResult},
sensors,
state::ProgramStateShared,
};
async fn temperature_control(program_state: ProgramStateShared) -> GenericResult<()> {
let mut program_state = program_state.lock().map_err(lock_err)?;
let current_temperature = sensors::get_temperature(&program_state.config)?;
if current_temperature > 28. {
actuators::switch_fan(crate::io::RelaySwitchState::On, &mut program_state)?;
} else {
actuators::switch_fan(crate::io::RelaySwitchState::Off, &mut program_state)?;
}
Ok(())
}
async fn temperature_control_loop(program_state: ProgramStateShared) {
loop {
let _ = temperature_control(program_state.clone()).await;
tokio::time::sleep(Duration::from_mins(1)).await;
}
}
async fn soil_moisture_control_loop(program_state: ProgramStateShared) {
loop {
tokio::time::sleep(Duration::from_days(1)).await;
}
}
async fn light_control(program_state: ProgramStateShared) -> GenericResult<()> {
let program_state = program_state.clone();
let mut program_state = program_state.lock().map_err(lock_err)?;
let local = Local::now();
let hour = local.time().hour();
const HOURS_ON: u32 = 24;
if hour <= HOURS_ON {
actuators::switch_lights(crate::io::RelaySwitchState::On, &mut program_state)?;
} else {
actuators::switch_lights(crate::io::RelaySwitchState::Off, &mut program_state)?;
}
Ok(())
}
async fn light_control_loop(program_state: ProgramStateShared) {
loop {
let _ = light_control(program_state.clone()).await;
tokio::time::sleep(Duration::from_hours(1)).await;
}
}
pub async fn control_thread(program_state: ProgramStateShared) {
join!(
light_control_loop(program_state.clone()),
temperature_control_loop(program_state.clone()),
soil_moisture_control_loop(program_state.clone())
);
}

1
src/io.rs

@ -27,6 +27,7 @@ pub fn get_input_voltage(pin: u8) -> GenericResult<f32> {
pub struct Relay { pub struct Relay {
relay_pins: Vec<Option<rppal::gpio::OutputPin>>, relay_pins: Vec<Option<rppal::gpio::OutputPin>>,
} }
#[derive(serde::Serialize, serde::Deserialize)]
pub enum RelaySwitchState { pub enum RelaySwitchState {
On, On,
Off, Off,

12
src/main.rs

@ -1,7 +1,6 @@
#![feature(duration_constructors)]
#![allow(dead_code)] #![allow(dead_code)]
use std::thread;
use cli_mode::run_cli; use cli_mode::run_cli;
use config::Configuration; use config::Configuration;
use server::run_server; use server::run_server;
@ -32,16 +31,17 @@ async fn main() {
let program_state = init_state(config).unwrap(); let program_state = init_state(config).unwrap();
let program_state_clone = program_state.clone(); let program_state_clone = program_state.clone();
let control_thread_handle = thread::spawn(move || control::control_thread(program_state_clone));
let control_thread_handle =
tokio::spawn(async move { control::control_thread(program_state_clone).await });
let args = std::env::args().collect::<Vec<_>>(); let args = std::env::args().collect::<Vec<_>>();
let mode = args.get(1).map(|x| x.as_str()); let mode = args.get(1).map(|x| x.as_str());
match mode { match mode {
Some("cli") => run_cli(program_state),
_ => run_server().await,
Some("cli") => run_cli(program_state.clone()),
_ => run_server(program_state.clone()).await,
} }
let _ = control_thread_handle.join();
let _ = control_thread_handle.await;
} }

46
src/server.rs

@ -1,13 +1,49 @@
use axum::{response::Html, routing::get, Router};
use axum::{
extract::{Path, State},
http::StatusCode,
response::{Html, IntoResponse},
routing::get,
Router,
};
pub async fn run_server() {
let app: Router = setup_router();
use crate::{
actuators,
error::{lock_err, GenericResult},
io::RelaySwitchState,
state::ProgramStateShared,
};
pub async fn run_server(program_state: ProgramStateShared) {
let app: Router = setup_router(program_state);
let listener = tokio::net::TcpListener::bind("0.0.0.0:2205").await.unwrap(); let listener = tokio::net::TcpListener::bind("0.0.0.0:2205").await.unwrap();
axum::serve(listener, app).await.unwrap(); axum::serve(listener, app).await.unwrap();
} }
fn setup_router() -> Router {
Router::new().route("/", get(handler))
fn setup_router(program_state: ProgramStateShared) -> Router {
Router::new()
.route("/", get(handler))
.route("/switch/:device/:state", get(switch_handler))
.with_state(program_state)
}
async fn switch_handler(
Path((device, state)): Path<(String, RelaySwitchState)>,
State(program_state): State<ProgramStateShared>,
) -> impl IntoResponse {
let exec = || -> GenericResult<()> {
let mut program_state = program_state.lock().map_err(lock_err)?;
match device.as_str() {
"lights" => actuators::switch_lights(state, &mut program_state)?,
"pump" => actuators::switch_water_pump(state, &mut program_state)?,
"fan" => actuators::switch_fan(state, &mut program_state)?,
_ => (),
}
Ok(())
};
match exec() {
Ok(_) => StatusCode::OK,
Err(_) => StatusCode::INTERNAL_SERVER_ERROR,
}
} }
async fn handler() -> Html<&'static str> { async fn handler() -> Html<&'static str> {

Loading…
Cancel
Save