diff --git a/Cargo.lock b/Cargo.lock index c77a4bb..eff3a2f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,21 @@ # It is not intended for manual editing. version = 3 +[[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]] name = "anstream" version = "0.6.15" @@ -51,6 +66,12 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + [[package]] name = "bincode" version = "1.3.3" @@ -60,6 +81,41 @@ dependencies = [ "serde", ] +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "cc" +version = "1.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f" +dependencies = [ + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[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", +] + [[package]] name = "clap" version = "4.5.16" @@ -106,24 +162,83 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + [[package]] name = "heck" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "iana-time-zone" +version = "0.1.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" +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]] name = "is_terminal_polyfill" version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +[[package]] +name = "js-sys" +version = "0.3.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" +dependencies = [ + "wasm-bindgen", +] + [[package]] name = "libc" version = "0.2.158" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + [[package]] name = "proc-macro2" version = "1.0.86" @@ -171,6 +286,12 @@ dependencies = [ "syn", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "strsim" version = "0.11.1" @@ -200,6 +321,70 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +[[package]] +name = "wasm-bindgen" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets", +] + [[package]] name = "windows-sys" version = "0.52.0" @@ -278,6 +463,7 @@ name = "zwote_sonne" version = "0.1.0" dependencies = [ "bincode", + "chrono", "clap", "clap_derive", "rppal", diff --git a/Cargo.toml b/Cargo.toml index 1a55416..0c90235 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,7 @@ path = "src/client.rs" [dependencies] bincode = "1.3.3" +chrono = "0.4.38" clap = { version = "4.5.16", features = ["derive"] } clap_derive = "4.5.13" rppal = "0.19.0" diff --git a/curve_description.adoc b/curve_description.adoc new file mode 100644 index 0000000..d610ecd --- /dev/null +++ b/curve_description.adoc @@ -0,0 +1,36 @@ += Description of curves for light purposes +Since the daily cycle is the main factor for plants whatever the periodicity of +the curve it will be restarted at midnight local time. + +== Curve definition +To keep it simple, we will only consider linear change. +Because of this the light value can be described in required brightness at +a given time. The value that the light had before that will then be adjusted +smoothly, until it reaches the value intended at the next time point. +The brightness at midnight must always be declared. + +For example: We want the light to be on off during the night, then turn on at +6:00 in the morning with 20% and gradually increase in brightness until it +reaches 100% at 8:00. Then, at 21:00 we want the light to start dimming until +it turns off at 23:00. The following graph shows this: + +.Graph not yet available +[%collapsible] +==== +==== + +The points should then be defined as follows: +[source] +---- +0000 0.0 +0600 0.0 +0600 0.2 +0800 1.0 +2100 1.0 +2300 0.0 +---- + +You will notice that two entries are at the same time here. This will make sure +that the light stays at the same level during the duration from 0000 to 0600. +When multiple entries are at the same time, the furthest down will be chosen. + diff --git a/src/client.rs b/src/client.rs index 0f987c9..603b63e 100644 --- a/src/client.rs +++ b/src/client.rs @@ -4,6 +4,7 @@ use clap::Parser; use clap_derive::Subcommand; use packet::Packet; +pub mod military_time; mod packet; #[derive(Parser, Debug)] @@ -17,47 +18,14 @@ struct Args } #[derive(Subcommand, Debug)] -enum Command -{ - /// Set a constant brightness in Range 0.0..=1.0 - Constant - { - brightness: f64 - }, - /// Sinusoidal curve with a period of 0.0.. seconds - Sine - { - period: f64 - }, - /// Triangle curve with a period of 0.0.. seconds - Triangle - { - period: f64 - }, - /// Sawtooth curve with a period of 0.0.. seconds - Sawtooth - { - period: f64 - }, - /// Square curve witha period of 0.0.. seconds and a duty cycle of 0.0..1.0 - Square - { - period: f64, duty: f64 - }, -} +enum Command {} fn main() { let args = Args::parse(); let mut stream = TcpStream::connect(args.connect).expect("Unable to connect to server"); - let packet = match args.command { - Command::Constant { brightness } => Packet::Constant(brightness), - Command::Sine { period } => Packet::Sine(period), - Command::Triangle { period } => Packet::Triangle(period), - Command::Sawtooth { period } => Packet::Sawtooth(period), - Command::Square { period, duty } => Packet::Square { period, duty }, - }; + let packet = match args.command {}; packet .write_to_stream(&mut stream) diff --git a/src/military_time.rs b/src/military_time.rs new file mode 100644 index 0000000..4b32e00 --- /dev/null +++ b/src/military_time.rs @@ -0,0 +1,76 @@ +use core::fmt; +use std::str::FromStr; + +const NUM_CHARS: usize = 4; + +/// Time of day representation in military time. +/// +/// Time does not know about anything fancy shmancy like timezones. Just useful +/// for simple time of day comparisons. +#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] +pub struct MilitaryTime(u16); + +#[derive(Debug)] +pub struct WrongFormat; +impl FromStr for MilitaryTime +{ + type Err = WrongFormat; + + fn from_str(s: &str) -> Result + { + if s.len() != NUM_CHARS { + return Err(WrongFormat); + } + + let time = u16::from_str(s).map_err(|_| Err(WrongFormat))?; + if time >= 2400 || (time % 100) >= 60 { + Err(WrongFormat) + } + else { + Ok(Self(time)) + } + } +} + +impl fmt::Display for MilitaryTime +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.0.fmt(f) } +} + +#[cfg(test)] +mod test +{ + use std::str::FromStr; + + use super::MilitaryTime; + + #[test] + fn parse_valid() + { + let valid_times = ["0000", "1234", "2359", "2000"]; + + for t in valid_times { + let _mt = MilitaryTime::from_str(&t).expect("Failed to parse valid time"); + } + } + + #[test] + fn parse_wrong_len() + { + let times = ["", "1", "12", "123", "12345"]; + + for t in times { + let _err = MilitaryTime::from_str(&t).expect_err("Invalid time parsed"); + } + } + + #[test] + fn parse_invalid_times() + { + let times = ["-123", "0061", "2360", "2400", "-000", "060a"]; + + for t in times { + let _err = MilitaryTime::from_str(&t).expect_err("Invalid time parsed"); + } + } +} diff --git a/src/packet.rs b/src/packet.rs index b30c819..67c40ad 100644 --- a/src/packet.rs +++ b/src/packet.rs @@ -8,19 +8,12 @@ const MAX_PACKET_SIZE_BYTES: u64 = 1024; #[derive(Serialize, Deserialize)] pub enum Packet { - /// Constant brightness in range 0.0..1.0 - Constant(f64), - /// Sinusoidal curve with a period of 0.0.. seconds - Sine(f64), - /// Triangle curve with a period of 0.0.. seconds - Triangle(f64), - /// Sawtooth curve with a period of 0.0.. seconds - Sawtooth(f64), - /// Square curve witha period of 0.0.. seconds and a duty cycle of 0.0..1.0 - Square - { - period: f64, duty: f64 - }, + SetDefaultCurveFile(String), + GetDefaultCurveFile(String), + SetCurve(String), + SaveCurve(String), + Ok(String), + Err(String), } #[inline] diff --git a/src/schedule.rs b/src/schedule.rs new file mode 100644 index 0000000..20eac61 --- /dev/null +++ b/src/schedule.rs @@ -0,0 +1 @@ +pub struct Schedule {} diff --git a/src/server.rs b/src/server.rs index ef8dc28..1fb5d5c 100644 --- a/src/server.rs +++ b/src/server.rs @@ -37,6 +37,7 @@ enum LightMode Triangle(f64), Sawtooth(f64), Square(f64, f64), + DaylightCycle(u32, u32), } impl LightMode { @@ -50,6 +51,9 @@ impl LightMode Self::Triangle(p) => triangle_wave(t / p), Self::Sawtooth(p) => sawtooth_wave(t / p), Self::Square(period, duty) => square_wave(t / period, *duty), + Self::DaylightCycle(day_start, night_start) => { + let night_after_day = night_start >= day_start; + }, } } } diff --git a/transfer.sh b/transfer.sh new file mode 100644 index 0000000..ff26338 --- /dev/null +++ b/transfer.sh @@ -0,0 +1 @@ +scp target/debug/zwote_sonne kuchen:~/