Compare commits

...

3 Commits

Author SHA1 Message Date
Nareshkumar Rao 30bae4e57e wip 7 months ago
Nareshkumar Rao 8c3ed74faf wip 7 months ago
Nareshkumar Rao cc34b02d0f wip 7 months ago
  1. 6
      .vscode/tasks.json
  2. 780
      Cargo.lock
  3. 12
      Cargo.toml
  4. 59
      src/actuators.rs
  5. 83
      src/cli_mode.rs
  6. 64
      src/control.rs
  7. 4
      src/error.rs
  8. 31
      src/io.rs
  9. 39
      src/main.rs
  10. 94
      src/server.rs
  11. 14
      src/state.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"
], ],

780
Cargo.lock

@ -2,6 +2,21 @@
# It is not intended for manual editing. # It is not intended for manual editing.
version = 3 version = 3
[[package]]
name = "addr2line"
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"
dependencies = [
"gimli",
]
[[package]]
name = "adler"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]] [[package]]
name = "ads1x1x" name = "ads1x1x"
version = "0.2.2" version = "0.2.2"
@ -12,12 +27,145 @@ 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]]
name = "async-trait"
version = "0.1.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "autocfg"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80"
[[package]]
name = "axum"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf"
dependencies = [
"async-trait",
"axum-core",
"axum-macros",
"bytes",
"futures-util",
"http",
"http-body",
"http-body-util",
"hyper",
"hyper-util",
"itoa",
"matchit",
"memchr",
"mime",
"percent-encoding",
"pin-project-lite",
"rustversion",
"serde",
"serde_json",
"serde_path_to_error",
"serde_urlencoded",
"sync_wrapper 1.0.1",
"tokio",
"tower",
"tower-layer",
"tower-service",
"tracing",
]
[[package]]
name = "axum-core"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3"
dependencies = [
"async-trait",
"bytes",
"futures-util",
"http",
"http-body",
"http-body-util",
"mime",
"pin-project-lite",
"rustversion",
"sync_wrapper 0.1.2",
"tower-layer",
"tower-service",
"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]]
name = "backtrace"
version = "0.3.71"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d"
dependencies = [
"addr2line",
"cc",
"cfg-if",
"libc",
"miniz_oxide",
"object",
"rustc-demangle",
]
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "2.5.0" 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]]
name = "bytes"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9"
[[package]]
name = "cc"
version = "1.0.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d32a725bc159af97c3e629873bb9f88fb8cf8a4867175f76dc987815ea07c83b"
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
version = "1.0.0" version = "1.0.0"
@ -30,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"
@ -39,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"
@ -84,7 +252,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"
dependencies = [ dependencies = [
"libc", "libc",
"windows-sys",
"windows-sys 0.52.0",
] ]
[[package]] [[package]]
@ -101,7 +269,77 @@ checksum = "7e5768da2206272c81ef0b5e951a41862938a6070da63bcea197899942d3b947"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"rustix", "rustix",
"windows-sys",
"windows-sys 0.52.0",
]
[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "form_urlencoded"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
dependencies = [
"percent-encoding",
]
[[package]]
name = "futures-channel"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78"
dependencies = [
"futures-core",
]
[[package]]
name = "futures-core"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
[[package]]
name = "futures-task"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
[[package]]
name = "futures-util"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
dependencies = [
"futures-core",
"futures-task",
"pin-project-lite",
"pin-utils",
]
[[package]]
name = "gimli"
version = "0.28.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
[[package]]
name = "growpi"
version = "0.1.0"
dependencies = [
"ads1x1x",
"axum",
"chrono",
"libc",
"nb 1.1.0",
"rppal",
"rustyline",
"serde",
"tokio",
"toml",
] ]
[[package]] [[package]]
@ -110,13 +348,123 @@ 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"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5"
dependencies = [ dependencies = [
"windows-sys",
"windows-sys 0.52.0",
]
[[package]]
name = "http"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258"
dependencies = [
"bytes",
"fnv",
"itoa",
]
[[package]]
name = "http-body"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643"
dependencies = [
"bytes",
"http",
]
[[package]]
name = "http-body-util"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d"
dependencies = [
"bytes",
"futures-core",
"http",
"http-body",
"pin-project-lite",
]
[[package]]
name = "httparse"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
[[package]]
name = "httpdate"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
[[package]]
name = "hyper"
version = "1.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d"
dependencies = [
"bytes",
"futures-channel",
"futures-util",
"http",
"http-body",
"httparse",
"httpdate",
"itoa",
"pin-project-lite",
"smallvec",
"tokio",
]
[[package]]
name = "hyper-util"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa"
dependencies = [
"bytes",
"futures-util",
"http",
"http-body",
"hyper",
"pin-project-lite",
"socket2",
"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]]
@ -129,6 +477,21 @@ dependencies = [
"hashbrown", "hashbrown",
] ]
[[package]]
name = "itoa"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
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"
@ -147,12 +510,44 @@ version = "0.4.21"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
[[package]]
name = "matchit"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94"
[[package]] [[package]]
name = "memchr" name = "memchr"
version = "2.7.2" version = "2.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"
[[package]]
name = "mime"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
[[package]]
name = "miniz_oxide"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7"
dependencies = [
"adler",
]
[[package]]
name = "mio"
version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
dependencies = [
"libc",
"wasi",
"windows-sys 0.48.0",
]
[[package]] [[package]]
name = "nb" name = "nb"
version = "0.1.3" version = "0.1.3"
@ -189,6 +584,68 @@ 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]]
name = "object"
version = "0.32.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441"
dependencies = [
"memchr",
]
[[package]]
name = "once_cell"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "percent-encoding"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
[[package]]
name = "pin-project"
version = "1.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3"
dependencies = [
"pin-project-internal",
]
[[package]]
name = "pin-project-internal"
version = "1.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "pin-project-lite"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02"
[[package]]
name = "pin-utils"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.81" version = "1.0.81"
@ -217,19 +674,6 @@ dependencies = [
"nibble_vec", "nibble_vec",
] ]
[[package]]
name = "rpitest"
version = "0.1.0"
dependencies = [
"ads1x1x",
"libc",
"nb 1.1.0",
"rppal",
"rustyline",
"serde",
"toml",
]
[[package]] [[package]]
name = "rppal" name = "rppal"
version = "0.17.1" version = "0.17.1"
@ -245,6 +689,12 @@ dependencies = [
"void", "void",
] ]
[[package]]
name = "rustc-demangle"
version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
[[package]] [[package]]
name = "rustix" name = "rustix"
version = "0.38.34" version = "0.38.34"
@ -255,9 +705,15 @@ dependencies = [
"errno", "errno",
"libc", "libc",
"linux-raw-sys", "linux-raw-sys",
"windows-sys",
"windows-sys 0.52.0",
] ]
[[package]]
name = "rustversion"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80af6f9131f277a45a3fba6ce8e2258037bb0477a67e610d3c1fe046ab31de47"
[[package]] [[package]]
name = "rustyline" name = "rustyline"
version = "14.0.0" version = "14.0.0"
@ -277,9 +733,15 @@ dependencies = [
"unicode-segmentation", "unicode-segmentation",
"unicode-width", "unicode-width",
"utf8parse", "utf8parse",
"windows-sys",
"windows-sys 0.52.0",
] ]
[[package]]
name = "ryu"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.198" version = "1.0.198"
@ -300,6 +762,27 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "serde_json"
version = "1.0.116"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "serde_path_to_error"
version = "0.1.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6"
dependencies = [
"itoa",
"serde",
]
[[package]] [[package]]
name = "serde_spanned" name = "serde_spanned"
version = "0.6.5" version = "0.6.5"
@ -309,19 +792,41 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "serde_urlencoded"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
dependencies = [
"form_urlencoded",
"itoa",
"ryu",
"serde",
]
[[package]] [[package]]
name = "smallvec" name = "smallvec"
version = "1.13.2" version = "1.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
[[package]]
name = "socket2"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871"
dependencies = [
"libc",
"windows-sys 0.52.0",
]
[[package]] [[package]]
name = "spin_sleep" name = "spin_sleep"
version = "1.2.0" version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "368a978649eaf70006b082e79c832bd72556ac1393eaf564d686e919dca2347f" checksum = "368a978649eaf70006b082e79c832bd72556ac1393eaf564d686e919dca2347f"
dependencies = [ dependencies = [
"windows-sys",
"windows-sys 0.52.0",
] ]
[[package]] [[package]]
@ -335,6 +840,44 @@ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]]
name = "sync_wrapper"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
[[package]]
name = "sync_wrapper"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394"
[[package]]
name = "tokio"
version = "1.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787"
dependencies = [
"backtrace",
"libc",
"mio",
"pin-project-lite",
"socket2",
"tokio-macros",
"windows-sys 0.48.0",
]
[[package]]
name = "tokio-macros"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "toml" name = "toml"
version = "0.8.12" version = "0.8.12"
@ -369,6 +912,54 @@ dependencies = [
"winnow", "winnow",
] ]
[[package]]
name = "tower"
version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c"
dependencies = [
"futures-core",
"futures-util",
"pin-project",
"pin-project-lite",
"tokio",
"tower-layer",
"tower-service",
"tracing",
]
[[package]]
name = "tower-layer"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0"
[[package]]
name = "tower-service"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
[[package]]
name = "tracing"
version = "0.1.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
dependencies = [
"log",
"pin-project-lite",
"tracing-core",
]
[[package]]
name = "tracing-core"
version = "0.1.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
dependencies = [
"once_cell",
]
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.12" version = "1.0.12"
@ -399,13 +990,106 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
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]]
name = "windows-sys"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
"windows-targets 0.48.5",
]
[[package]] [[package]]
name = "windows-sys" name = "windows-sys"
version = "0.52.0" version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [ dependencies = [
"windows-targets",
"windows-targets 0.52.5",
]
[[package]]
name = "windows-targets"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
dependencies = [
"windows_aarch64_gnullvm 0.48.5",
"windows_aarch64_msvc 0.48.5",
"windows_i686_gnu 0.48.5",
"windows_i686_msvc 0.48.5",
"windows_x86_64_gnu 0.48.5",
"windows_x86_64_gnullvm 0.48.5",
"windows_x86_64_msvc 0.48.5",
] ]
[[package]] [[package]]
@ -414,28 +1098,46 @@ version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
dependencies = [ dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_aarch64_gnullvm 0.52.5",
"windows_aarch64_msvc 0.52.5",
"windows_i686_gnu 0.52.5",
"windows_i686_gnullvm", "windows_i686_gnullvm",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
"windows_i686_msvc 0.52.5",
"windows_x86_64_gnu 0.52.5",
"windows_x86_64_gnullvm 0.52.5",
"windows_x86_64_msvc 0.52.5",
] ]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]] [[package]]
name = "windows_aarch64_gnullvm" name = "windows_aarch64_gnullvm"
version = "0.52.5" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]] [[package]]
name = "windows_aarch64_msvc" name = "windows_aarch64_msvc"
version = "0.52.5" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
[[package]]
name = "windows_i686_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]] [[package]]
name = "windows_i686_gnu" name = "windows_i686_gnu"
version = "0.52.5" version = "0.52.5"
@ -448,24 +1150,48 @@ version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
[[package]]
name = "windows_i686_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]] [[package]]
name = "windows_i686_msvc" name = "windows_i686_msvc"
version = "0.52.5" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]] [[package]]
name = "windows_x86_64_gnu" name = "windows_x86_64_gnu"
version = "0.52.5" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]] [[package]]
name = "windows_x86_64_gnullvm" name = "windows_x86_64_gnullvm"
version = "0.52.5" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]] [[package]]
name = "windows_x86_64_msvc" name = "windows_x86_64_msvc"
version = "0.52.5" version = "0.52.5"

12
Cargo.toml

@ -1,16 +1,16 @@
[package] [package]
name = "rpitest"
name = "growpi"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
rppal = { version = "0.17", features = ["hal"] } rppal = { version = "0.17", features = ["hal"] }
#rumqttc = "0.24.0"
libc = "0.2" libc = "0.2"
ads1x1x = "0.2" ads1x1x = "0.2"
nb = "1.1.0"
rustyline = "14.0.0"
nb = "1.1"
rustyline = "14.0"
serde = { "version" = "1.0", features = ["derive"] } serde = { "version" = "1.0", features = ["derive"] }
toml = "0.8" toml = "0.8"
axum = { "version" = "0.7", features = ["macros"] }
tokio = { "version" = "1.37" }
chrono = "0.4.38"

59
src/actuators.rs

@ -1,45 +1,54 @@
use std::{thread, time::Duration}; use std::{thread, time::Duration};
use crate::{
config::*,
error::GenericResult,
io::{Relay, RelaySwitchState},
};
use crate::{error::GenericResult, io::RelaySwitchState, state::ProgramState};
pub fn switch_lights( pub fn switch_lights(
relay: &mut Relay,
state: RelaySwitchState, state: RelaySwitchState,
config: &Configuration,
program_state: &mut ProgramState,
) -> GenericResult<()> { ) -> GenericResult<()> {
relay.switch(config.relay_settings.light_pin, state, config)
program_state
.relay
.switch(program_state.config.relay_settings.light_pin, state)
} }
pub fn switch_fan(
relay: &mut Relay,
state: RelaySwitchState,
config: &Configuration,
) -> GenericResult<()> {
relay.switch(config.relay_settings.fan_pin, state, config)
pub fn switch_fan(state: RelaySwitchState, program_state: &mut ProgramState) -> GenericResult<()> {
program_state
.relay
.switch(program_state.config.relay_settings.fan_pin, state)
} }
pub fn switch_water_pump( pub fn switch_water_pump(
relay: &mut Relay,
state: RelaySwitchState, state: RelaySwitchState,
config: &Configuration,
program_state: &mut ProgramState,
) -> GenericResult<()> { ) -> GenericResult<()> {
relay.switch(config.relay_settings.water_pump_pin, state, config)
program_state
.relay
.switch(program_state.config.relay_settings.water_pump_pin, state)
} }
pub fn pump_water(
water_mass_g: u16,
relay: &mut Relay,
config: &Configuration,
) -> GenericResult<()> {
let duration_ms = water_mass_g as f32 / config.water_pump_settings.grams_per_millisecond;
pub fn get_light_state(program_state: &mut ProgramState) -> GenericResult<RelaySwitchState> {
let pin = program_state.config.relay_settings.light_pin;
program_state.relay.get_state(pin)
}
pub fn get_water_pump_state(program_state: &mut ProgramState) -> GenericResult<RelaySwitchState> {
let pin = program_state.config.relay_settings.water_pump_pin;
program_state.relay.get_state(pin)
}
pub fn get_fan_state(program_state: &mut ProgramState) -> GenericResult<RelaySwitchState> {
let pin = program_state.config.relay_settings.fan_pin;
program_state.relay.get_state(pin)
}
pub fn pump_water(water_mass_g: u16, program_state: &mut ProgramState) -> GenericResult<()> {
let duration_ms = water_mass_g as f32
/ program_state
.config
.water_pump_settings
.grams_per_millisecond;
let duration_ms = duration_ms.round() as u64; let duration_ms = duration_ms.round() as u64;
let duration = Duration::from_millis(duration_ms); let duration = Duration::from_millis(duration_ms);
switch_water_pump(relay, RelaySwitchState::On, config)?;
switch_water_pump(RelaySwitchState::On, program_state)?;
thread::sleep(duration); thread::sleep(duration);
switch_water_pump(relay, RelaySwitchState::Off, config)?;
switch_water_pump(RelaySwitchState::Off, program_state)?;
Ok(()) Ok(())
} }

83
src/cli_mode.rs

@ -4,29 +4,25 @@ use rustyline::{config::Configurer, error::ReadlineError, history::FileHistory};
use crate::{ use crate::{
actuators, actuators,
config::Configuration,
error::GenericResult,
error::{lock_err, GenericResult},
io::{self, get_input_voltage}, io::{self, get_input_voltage},
sensors, sensors,
state::ProgramStateShared,
}; };
struct LoopFlags { struct LoopFlags {
exit: bool, exit: bool,
} }
fn process_input(
input: String,
program_state: &mut ProgramState,
config: &Configuration,
) -> GenericResult<LoopFlags> {
fn process_input(input: String, program_state: ProgramStateShared) -> GenericResult<LoopFlags> {
let args = input.split(' ').collect::<Vec<_>>(); let args = input.split(' ').collect::<Vec<_>>();
let main_command = *args.first().ok_or("No main command found.")?; let main_command = *args.first().ok_or("No main command found.")?;
match main_command { match main_command {
"ana" => command_ana(&args)?, "ana" => command_ana(&args)?,
"rel" => command_rel(&args, program_state, config)?,
"soil" => command_soil(&args, config)?,
"temp" => command_temp(&args, config)?,
"pump" => command_pump(&args, program_state, config)?,
"rel" => command_rel(&args, program_state)?,
"soil" => command_soil(&args, program_state)?,
"temp" => command_temp(&args, program_state)?,
"pump" => command_pump(&args, program_state)?,
"exit" => return Ok(LoopFlags { exit: true }), "exit" => return Ok(LoopFlags { exit: true }),
_ => return Err("Unknown main command".into()), _ => return Err("Unknown main command".into()),
}; };
@ -34,11 +30,9 @@ fn process_input(
Ok(LoopFlags { exit: false }) Ok(LoopFlags { exit: false })
} }
fn command_pump(
args: &[&str],
program_state: &mut ProgramState,
config: &Configuration,
) -> GenericResult<()> {
fn command_pump(args: &[&str], program_state: ProgramStateShared) -> GenericResult<()> {
let mut program_state = program_state.lock().map_err(lock_err)?;
let use_grams = args let use_grams = args
.get(2) .get(2)
.map(|arg| matches!(*arg, "grams")) .map(|arg| matches!(*arg, "grams"))
@ -46,26 +40,27 @@ fn command_pump(
if use_grams { if use_grams {
let grams: u16 = args.get(1).ok_or("No mass specified.")?.parse()?; let grams: u16 = args.get(1).ok_or("No mass specified.")?.parse()?;
actuators::pump_water(grams, &mut program_state.relay, config)?;
actuators::pump_water(grams, &mut program_state)?;
return Ok(()); return Ok(());
} }
let duration_ms: u64 = args.get(1).ok_or("No duration specified.")?.parse()?; let duration_ms: u64 = args.get(1).ok_or("No duration specified.")?.parse()?;
let duration = Duration::from_millis(duration_ms); let duration = Duration::from_millis(duration_ms);
actuators::switch_water_pump(&mut program_state.relay, io::RelaySwitchState::On, config)?;
actuators::switch_water_pump(io::RelaySwitchState::On, &mut program_state)?;
thread::sleep(duration); thread::sleep(duration);
actuators::switch_water_pump(&mut program_state.relay, io::RelaySwitchState::Off, config)?;
actuators::switch_water_pump(io::RelaySwitchState::Off, &mut program_state)?;
Ok(()) Ok(())
} }
fn command_temp(args: &[&str], config: &Configuration) -> GenericResult<()> {
fn command_temp(args: &[&str], program_state: ProgramStateShared) -> GenericResult<()> {
let show_loop = args let show_loop = args
.get(1) .get(1)
.map(|arg| matches!(*arg, "loop")) .map(|arg| matches!(*arg, "loop"))
.unwrap_or(false); .unwrap_or(false);
loop { loop {
let temperature = sensors::get_temperature(config)?;
let program_state = program_state.lock().map_err(lock_err)?;
let temperature = sensors::get_temperature(&program_state.config)?;
println!("Temperature: {}C", temperature); println!("Temperature: {}C", temperature);
if !show_loop { if !show_loop {
break; break;
@ -75,14 +70,15 @@ fn command_temp(args: &[&str], config: &Configuration) -> GenericResult<()> {
Ok(()) Ok(())
} }
fn command_soil(args: &[&str], config: &Configuration) -> GenericResult<()> {
fn command_soil(args: &[&str], program_state: ProgramStateShared) -> GenericResult<()> {
let show_loop = args let show_loop = args
.get(1) .get(1)
.map(|arg| matches!(*arg, "loop")) .map(|arg| matches!(*arg, "loop"))
.unwrap_or(false); .unwrap_or(false);
loop { loop {
let humidity = sensors::get_soil_moisture(config)?;
let program_state = program_state.lock().map_err(lock_err)?;
let humidity = sensors::get_soil_moisture(&program_state.config)?;
println!("Soil humidity: {}", humidity); println!("Soil humidity: {}", humidity);
if !show_loop { if !show_loop {
break; break;
@ -93,11 +89,9 @@ fn command_soil(args: &[&str], config: &Configuration) -> GenericResult<()> {
Ok(()) Ok(())
} }
fn command_rel(
args: &[&str],
program_state: &mut ProgramState,
config: &Configuration,
) -> GenericResult<()> {
fn command_rel(args: &[&str], program_state: ProgramStateShared) -> GenericResult<()> {
let mut program_state = program_state.lock().map_err(lock_err)?;
let pin = args let pin = args
.get(1) .get(1)
.ok_or("Must specify pin number.")? .ok_or("Must specify pin number.")?
@ -117,11 +111,11 @@ fn command_rel(
match switch_state { match switch_state {
Some(state) => { Some(state) => {
println!("Switching relay"); println!("Switching relay");
program_state.relay.switch(pin, state?, config)?
program_state.relay.switch(pin, state?)?
} }
None => { None => {
println!("Toggling relay"); println!("Toggling relay");
program_state.relay.toggle(pin, config)?
program_state.relay.toggle(pin)?
} }
}; };
@ -152,17 +146,13 @@ fn command_ana(args: &[&str]) -> GenericResult<()> {
Ok(()) Ok(())
} }
fn cli_loop(
rl: &mut CLIEditor,
program_state: &mut ProgramState,
config: &Configuration,
) -> GenericResult<LoopFlags> {
fn cli_loop(rl: &mut CLIEditor, program_state: ProgramStateShared) -> GenericResult<LoopFlags> {
let readline = rl.readline("growpi>> "); let readline = rl.readline("growpi>> ");
match readline { match readline {
Ok(line) => { Ok(line) => {
rl.add_history_entry(line.as_str())?; rl.add_history_entry(line.as_str())?;
process_input(line, program_state, config)
process_input(line, program_state)
} }
Err(ReadlineError::Eof) => Ok(LoopFlags { exit: true }), Err(ReadlineError::Eof) => Ok(LoopFlags { exit: true }),
Err(_) => Err("No input".into()), Err(_) => Err("No input".into()),
@ -175,29 +165,12 @@ fn init_readline() -> GenericResult<CLIEditor> {
rl.set_max_history_size(10)?; rl.set_max_history_size(10)?;
Ok(rl) Ok(rl)
} }
struct ProgramState {
relay: io::Relay,
}
fn init_state(config: &Configuration) -> GenericResult<ProgramState> {
Ok(ProgramState {
relay: io::Relay::new(config)?,
})
}
pub fn run_cli() {
pub fn run_cli(program_state: ProgramStateShared) {
let mut rl = init_readline().unwrap(); let mut rl = init_readline().unwrap();
let config = Configuration::from_file(std::path::Path::new("./growpi.toml"));
if let Err(config) = &config {
println!("Could not load config: {}", config);
}
let config = config.unwrap_or_default();
let mut program_state = init_state(&config).unwrap();
'cli_loop: loop { 'cli_loop: loop {
match cli_loop(&mut rl, &mut program_state, &config) {
match cli_loop(&mut rl, program_state.clone()) {
Ok(loop_flags) => { Ok(loop_flags) => {
if loop_flags.exit { if loop_flags.exit {
println!("Leaving CLI"); println!("Leaving CLI");

64
src/control.rs

@ -0,0 +1,64 @@
use std::time::Duration;
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())
);
}

4
src/error.rs

@ -1,3 +1,7 @@
use std::error::Error; use std::error::Error;
pub type GenericResult<T> = Result<T, Box<dyn Error>>; pub type GenericResult<T> = Result<T, Box<dyn Error>>;
pub fn lock_err<T: std::fmt::Display>(e: T) -> String {
format!("{}", e)
}

31
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,
@ -59,19 +60,14 @@ impl Relay {
relay_pins: output_pins, relay_pins: output_pins,
}) })
} }
pub fn toggle(&mut self, pin: u8, config: &Configuration) -> GenericResult<()> {
let pin = self.get_output_pin(pin, config)?;
pub fn toggle(&mut self, pin: u8) -> GenericResult<()> {
let pin = self.get_output_pin(pin)?;
pin.toggle(); pin.toggle();
Ok(()) Ok(())
} }
pub fn switch(
&mut self,
pin: u8,
state: RelaySwitchState,
config: &Configuration,
) -> GenericResult<()> {
let pin = self.get_output_pin(pin, config)?;
pub fn switch(&mut self, pin: u8, state: RelaySwitchState) -> GenericResult<()> {
let pin = self.get_output_pin(pin)?;
match state { match state {
RelaySwitchState::On => pin.set_low(), RelaySwitchState::On => pin.set_low(),
RelaySwitchState::Off => pin.set_high(), RelaySwitchState::Off => pin.set_high(),
@ -79,15 +75,20 @@ impl Relay {
Ok(()) Ok(())
} }
fn get_output_pin(&mut self, pin: u8, config: &Configuration) -> GenericResult<&mut OutputPin> {
pub fn get_state(&mut self, pin: u8) -> GenericResult<RelaySwitchState> {
let pin = self.get_output_pin(pin)?;
if pin.is_set_high() {
Ok(RelaySwitchState::Off)
} else {
Ok(RelaySwitchState::On)
}
}
fn get_output_pin(&mut self, pin: u8) -> GenericResult<&mut OutputPin> {
Ok(self Ok(self
.relay_pins .relay_pins
.get_mut(pin as usize) .get_mut(pin as usize)
.ok_or(format!(
"Pin {} not within pin array with length {}",
pin,
config.relay_settings.relay_gpio_pins.len()
))?
.ok_or(format!("Pin {} not within pin array", pin,))?
.as_mut() .as_mut()
.ok_or("Pin not configured.")?) .ok_or("Pin not configured.")?)
} }

39
src/main.rs

@ -1,20 +1,47 @@
#![feature(duration_constructors)]
#![allow(dead_code)] #![allow(dead_code)]
use cli_mode::run_cli; use cli_mode::run_cli;
use config::Configuration;
use server::run_server;
use state::init_state;
mod actuators; mod actuators;
mod cli_mode; mod cli_mode;
mod config; mod config;
mod control;
mod error; mod error;
mod io; mod io;
mod sensors; mod sensors;
mod server;
mod state;
fn load_config() -> config::Configuration {
let config = Configuration::from_file(std::path::Path::new("./growpi.toml"));
if let Err(config) = &config {
println!("Could not load config: {}", config);
}
config.unwrap_or_default()
}
#[tokio::main(flavor = "current_thread")]
async fn main() {
let config = load_config();
let program_state = init_state(config).unwrap();
let program_state_clone = program_state.clone();
let control_thread_handle =
tokio::spawn(async move { control::control_thread(program_state_clone).await });
fn main() {
let args = std::env::args().collect::<Vec<_>>(); let args = std::env::args().collect::<Vec<_>>();
if let Some(mode) = args.first().map(|x| x.as_str()) {
match mode {
"cli" => run_cli(),
_ => run_cli(),
}
let mode = args.get(1).map(|x| x.as_str());
match mode {
Some("cli") => run_cli(program_state.clone()),
_ => run_server(program_state.clone()).await,
} }
let _ = control_thread_handle.await;
} }

94
src/server.rs

@ -0,0 +1,94 @@
use axum::{
extract::{Path, State},
http::StatusCode,
response::IntoResponse,
routing::get,
Json, Router,
};
use serde::{Deserialize, Serialize};
use crate::{
actuators,
error::{lock_err, GenericResult},
io::RelaySwitchState,
sensors,
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();
axum::serve(listener, app).await.unwrap();
}
fn setup_router(program_state: ProgramStateShared) -> Router {
Router::new()
.route("/info", get(info_handler))
.route("/switch/:device/:state", get(switch_handler))
.route("/pump/:quantity", get(pump_handler))
.with_state(program_state)
}
async fn pump_handler(
Path(quantity): Path<u16>,
State(program_state): State<ProgramStateShared>,
) -> impl IntoResponse {
let exec = || -> GenericResult<()> {
let mut program_state = program_state.lock().map_err(lock_err)?;
actuators::pump_water(quantity, &mut program_state)?;
Ok(())
};
match exec() {
Ok(_) => StatusCode::OK,
Err(_) => StatusCode::INTERNAL_SERVER_ERROR,
}
}
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,
}
}
#[derive(Serialize, Deserialize)]
struct Info {
temperature: f32,
soil_moisture: f32,
fan_state: RelaySwitchState,
light_state: RelaySwitchState,
pump_state: RelaySwitchState,
}
async fn info_handler(
State(program_state): State<ProgramStateShared>,
) -> Result<Json<Info>, String> {
let mut program_state = program_state.lock().map_err(lock_err)?;
let temperature = sensors::get_temperature(&program_state.config).map_err(|e| e.to_string())?;
let soil_moisture =
sensors::get_soil_moisture(&program_state.config).map_err(|e| e.to_string())?;
let fan_state = actuators::get_fan_state(&mut program_state).map_err(|e| e.to_string())?;
let light_state = actuators::get_light_state(&mut program_state).map_err(|e| e.to_string())?;
let pump_state =
actuators::get_water_pump_state(&mut program_state).map_err(|e| e.to_string())?;
Ok(Json(Info {
temperature,
soil_moisture,
fan_state,
light_state,
pump_state,
}))
}

14
src/state.rs

@ -0,0 +1,14 @@
use std::sync::{Arc, Mutex};
use crate::{config::Configuration, error::GenericResult, io};
pub type ProgramStateShared = Arc<Mutex<ProgramState>>;
pub struct ProgramState {
pub config: Configuration,
pub relay: io::Relay,
}
pub fn init_state(config: Configuration) -> GenericResult<ProgramStateShared> {
let relay = io::Relay::new(&config)?;
Ok(Arc::new(Mutex::new(ProgramState { config, relay })))
}
Loading…
Cancel
Save