commit 40a109637f9ab23a33377e37b8d19ab0b98831f5 Author: Andre Henriques Date: Mon Mar 13 20:59:50 2023 +0000 Initial Commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a5ff07f --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +/target + + +# Added by cargo +# +# already existing elements were commented out + +#/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..de313e0 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,1724 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aead" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877" +dependencies = [ + "generic-array", +] + +[[package]] +name = "aes" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", + "opaque-debug", +] + +[[package]] +name = "aes-gcm" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df5f85a83a7d8b0442b6aa7b504b8212c1733da07b98aae43d4bc21b2cb3cdf6" +dependencies = [ + "aead", + "aes", + "cipher", + "ctr", + "ghash", + "subtle", +] + +[[package]] +name = "ahash" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +dependencies = [ + "getrandom", + "once_cell", + "version_check", +] + +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + +[[package]] +name = "async-stream" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dad5c83079eae9969be7fadefe640a1c566901f05ff91ab221de4b6f68d9507e" +dependencies = [ + "async-stream-impl", + "futures-core", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "async-trait" +version = "0.1.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76464446b8bc32758d7e88ee1a804d9914cd9b1cb264c029899680b0be29826f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "atomic" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b88d82667eca772c4aa12f0f1348b3ae643424c8876448f3f7bd5787032e234c" +dependencies = [ + "autocfg", +] + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "base64" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" + +[[package]] +name = "binascii" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "383d29d513d8764dcdc42ea295d979eb99c3c9f00607b3692cf68a431f7dca72" + +[[package]] +name = "bindgen" +version = "0.59.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bd2a9a458e8f4304c52c43ebb0cfbd520289f8379a52e329a38afda99bf8eb8" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "lazy_static", + "lazycell", + "peeking_take_while", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "block-buffer" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bytemuck" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44f8cb64b4147a528e1e9e77583739e683541973295b35f3bd7e78d42c5971fd" + +[[package]] +name = "bytes" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db" + +[[package]] +name = "cc" +version = "1.0.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cipher" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" +dependencies = [ + "generic-array", +] + +[[package]] +name = "clang-sys" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a050e2153c5be08febd6734e29298e844fdb0fa21aeddd63b4eb7baa106c69b" +dependencies = [ + "glob", + "libc", +] + +[[package]] +name = "cookie" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94d4706de1b0fa5b132270cddffa8585166037822e260a944fe161acd137ca05" +dependencies = [ + "aes-gcm", + "base64", + "hkdf", + "hmac", + "percent-encoding", + "rand", + "sha2", + "subtle", + "time", + "version_check", +] + +[[package]] +name = "cpufeatures" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "ctr" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "049bb91fb4aaf0e3c7efa6cd5ef877dbbbd15b39dad06d9948de4ec8a75761ea" +dependencies = [ + "cipher", +] + +[[package]] +name = "devise" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50c7580b072f1c8476148f16e0a0d5dedddab787da98d86c5082c5e9ed8ab595" +dependencies = [ + "devise_codegen", + "devise_core", +] + +[[package]] +name = "devise_codegen" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "123c73e7a6e51b05c75fe1a1b2f4e241399ea5740ed810b0e3e6cacd9db5e7b2" +dependencies = [ + "devise_core", + "quote", +] + +[[package]] +name = "devise_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841ef46f4787d9097405cac4e70fb8644fc037b526e8c14054247c0263c400d0" +dependencies = [ + "bitflags", + "proc-macro2", + "proc-macro2-diagnostics", + "quote", + "syn", +] + +[[package]] +name = "digest" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adfbc57365a37acbd2ebf2b64d7e69bb766e2fea813521ed536f5d0520dcf86c" +dependencies = [ + "block-buffer", + "crypto-common", + "subtle", +] + +[[package]] +name = "either" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" + +[[package]] +name = "encoding_rs" +version = "0.8.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "fallible-iterator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" + +[[package]] +name = "fallible-streaming-iterator" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" + +[[package]] +name = "fastrand" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" +dependencies = [ + "instant", +] + +[[package]] +name = "figment" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e3bd154d9ae2f1bb0ada5b7eebd56529513efa5de7d2fc8c6adf33bc43260cf" +dependencies = [ + "atomic", + "pear", + "serde", + "toml", + "uncased", + "version_check", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "futures" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f21eda599937fba36daeb58a22e8f5cee2d14c4a17b5b7739c7c8e5e3b8230c" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30bdd20c28fadd505d0fd6712cdfcb0d4b5648baf45faef7f852afb2399bb050" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e5aa3de05362c3fb88de6531e6296e85cde7739cccad4b9dfeeb7f6ebce56bf" + +[[package]] +name = "futures-io" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbf4d2a7a308fd4578637c0b17c7e1c7ba127b8f6ba00b29f717e9655d85eb68" + +[[package]] +name = "futures-sink" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b20ba5a92e727ba30e72834706623d94ac93a725410b6a6b6fbc1b07f7ba56" + +[[package]] +name = "futures-task" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6508c467c73851293f390476d4491cf4d227dbabcd4170f3bb6044959b294f1" + +[[package]] +name = "futures-util" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44fb6cb1be61cc1d2e43b262516aafcf63b241cffdb1d3fa115f91d9c7b09c90" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generator" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc184cace1cea8335047a471cc1da80f18acf8a76f3bab2028d499e328948ec7" +dependencies = [ + "cc", + "libc", + "log", + "rustversion", + "windows", +] + +[[package]] +name = "generic-array" +version = "0.14.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "ghash" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1583cc1656d7839fd3732b80cf4f38850336cdb9b8ded1cd399ca62958de3c99" +dependencies = [ + "opaque-debug", + "polyval", +] + +[[package]] +name = "glob" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" + +[[package]] +name = "h2" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca32592cf21ac7ccab1825cd87f6c9b3d9022c44d086172ed0966bec8af30be" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash", +] + +[[package]] +name = "hashlink" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69fe1fcf8b4278d860ad0548329f892a3631fb63f82574df68275f34cdbe0ffa" +dependencies = [ + "hashbrown", +] + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "hkdf" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437" +dependencies = [ + "hmac", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "http" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +dependencies = [ + "bytes", + "http", + "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.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" + +[[package]] +name = "hyper" +version = "0.14.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02c929dc5c39e335a03c405292728118860721b10190d98c2a0f0efd5baafbac" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "indexmap" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" +dependencies = [ + "autocfg", + "hashbrown", + "serde", +] + +[[package]] +name = "inlinable_string" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8fae54786f62fb2918dcfae3d568594e50eb9b5c25bf04371af6fe7516452fb" + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "itoa" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + +[[package]] +name = "libc" +version = "0.2.131" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04c3b4822ccebfa39c02fc03d1534441b22ead323fa0f48bb7ddd8e6ba076a40" + +[[package]] +name = "libsqlite3-sys" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f0455f2c1bc9a7caa792907026e469c1d91761fb0ea37cbb16427c77280cf35" +dependencies = [ + "cc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "lock_api" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f80bf5aacaf25cbfc8210d1cfb718f2bf3b11c4c54e5afe36c236853a8ec390" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "loom" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff50ecb28bb86013e935fb6683ab1f6d3a20016f123c76fd4c27470076ac30f5" +dependencies = [ + "cfg-if", + "generator", + "scoped-tls", + "serde", + "serde_json", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata", +] + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "mime" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "mio" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" +dependencies = [ + "libc", + "log", + "wasi", + "windows-sys", +] + +[[package]] +name = "multer" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a30ba6d97eb198c5e8a35d67d5779d6680cca35652a60ee90fc23dc431d4fde8" +dependencies = [ + "bytes", + "encoding_rs", + "futures-util", + "http", + "httparse", + "log", + "memchr", + "mime", + "spin", + "tokio", + "tokio-util", + "version_check", +] + +[[package]] +name = "neolights" +version = "0.1.0" +dependencies = [ + "r2d2", + "r2d2_sqlite", + "rocket", + "serde", + "smart-leds", + "tokio", + "ws281x-rpi", +] + +[[package]] +name = "nom" +version = "7.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "num_cpus" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "num_threads" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" +dependencies = [ + "libc", +] + +[[package]] +name = "once_cell" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f7254b99e31cad77da24b08ebf628882739a608578bb1bcdfc1f9c21260d7c0" + +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-sys", +] + +[[package]] +name = "pear" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15e44241c5e4c868e3eaa78b7c1848cadd6344ed4f54d029832d32b415a58702" +dependencies = [ + "inlinable_string", + "pear_codegen", + "yansi", +] + +[[package]] +name = "pear_codegen" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82a5ca643c2303ecb740d506539deba189e16f2754040a42901cd8105d0282d0" +dependencies = [ + "proc-macro2", + "proc-macro2-diagnostics", + "quote", + "syn", +] + +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" + +[[package]] +name = "percent-encoding" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" + +[[package]] +name = "pin-project-lite" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" + +[[package]] +name = "polyval" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8419d2b623c7c0896ff2d5d96e2cb4ede590fed28fcc34934f4c33c036e620a1" +dependencies = [ + "cfg-if", + "cpufeatures", + "opaque-debug", + "universal-hash", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" + +[[package]] +name = "proc-macro2" +version = "1.0.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "proc-macro2-diagnostics" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bf29726d67464d49fa6224a1d07936a8c08bb3fba727c7493f6cf1616fdaada" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "version_check", + "yansi", +] + +[[package]] +name = "quote" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r2d2" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51de85fb3fb6524929c8a2eb85e6b6d363de4e8c48f9e2c2eac4944abc181c93" +dependencies = [ + "log", + "parking_lot", + "scheduled-thread-pool", +] + +[[package]] +name = "r2d2_sqlite" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4f5d0337e99cd5cacd91ffc326c6cc9d8078def459df560c4f9bf9ba4a51034" +dependencies = [ + "r2d2", + "rusqlite", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags", +] + +[[package]] +name = "ref-cast" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed13bcd201494ab44900a96490291651d200730904221832b9547d24a87d332b" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5234cd6063258a5e32903b53b1b6ac043a0541c8adc1f610f67b0326c7a578fa" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "regex" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" +dependencies = [ + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" + +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi", +] + +[[package]] +name = "rgb" +version = "0.8.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3b221de559e4a29df3b957eec92bc0de6bc8eaf6ca9cfed43e5e1d67ff65a34" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "rocket" +version = "0.5.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98ead083fce4a405feb349cf09abdf64471c6077f14e0ce59364aa90d4b99317" +dependencies = [ + "async-stream", + "async-trait", + "atomic", + "atty", + "binascii", + "bytes", + "either", + "figment", + "futures", + "indexmap", + "log", + "memchr", + "multer", + "num_cpus", + "parking_lot", + "pin-project-lite", + "rand", + "ref-cast", + "rocket_codegen", + "rocket_http", + "serde", + "serde_json", + "state", + "tempfile", + "time", + "tokio", + "tokio-stream", + "tokio-util", + "ubyte", + "version_check", + "yansi", +] + +[[package]] +name = "rocket_codegen" +version = "0.5.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6aeb6bb9c61e9cd2c00d70ea267bf36f76a4cc615e5908b349c2f9d93999b47" +dependencies = [ + "devise", + "glob", + "indexmap", + "proc-macro2", + "quote", + "rocket_http", + "syn", + "unicode-xid", +] + +[[package]] +name = "rocket_http" +version = "0.5.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ded65d127954de3c12471630bf4b81a2792f065984461e65b91d0fdaafc17a2" +dependencies = [ + "cookie", + "either", + "futures", + "http", + "hyper", + "indexmap", + "log", + "memchr", + "pear", + "percent-encoding", + "pin-project-lite", + "ref-cast", + "serde", + "smallvec", + "stable-pattern", + "state", + "time", + "tokio", + "uncased", +] + +[[package]] +name = "rusqlite" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01e213bc3ecb39ac32e81e51ebe31fd888a940515173e3a18a35f8c6e896422a" +dependencies = [ + "bitflags", + "fallible-iterator", + "fallible-streaming-iterator", + "hashlink", + "libsqlite3-sys", + "smallvec", +] + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustversion" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8" + +[[package]] +name = "ryu" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" + +[[package]] +name = "scheduled-thread-pool" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "977a7519bff143a44f842fd07e80ad1329295bd71686457f18e496736f4bf9bf" +dependencies = [ + "parking_lot", +] + +[[package]] +name = "scoped-tls" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "serde" +version = "1.0.145" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.145" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81fa1584d3d1bcacd84c277a0dfe21f5b0f6accf4a23d04d4c6d61f1af522b4c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.85" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sharded-slab" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" + +[[package]] +name = "signal-hook-registry" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" +dependencies = [ + "libc", +] + +[[package]] +name = "slab" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" + +[[package]] +name = "smart-leds" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38dd45fa275f70b4110eac5f5182611ad384f88bb22b68b9a9c3cafd7015290b" +dependencies = [ + "smart-leds-trait", +] + +[[package]] +name = "smart-leds-trait" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebf6d833fa93f16a1c1874e62c2aebe8567e5bdd436d59bf543ed258b6f7a8e3" +dependencies = [ + "rgb", +] + +[[package]] +name = "socket2" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "spin" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6002a767bff9e83f8eeecf883ecb8011875a21ae8da43bffb817a57e78cc09" + +[[package]] +name = "stable-pattern" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4564168c00635f88eaed410d5efa8131afa8d8699a612c80c455a0ba05c21045" +dependencies = [ + "memchr", +] + +[[package]] +name = "state" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbe866e1e51e8260c9eed836a042a5e7f6726bb2b411dffeaa712e19c388f23b" +dependencies = [ + "loom", +] + +[[package]] +name = "subtle" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" + +[[package]] +name = "syn" +version = "1.0.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tempfile" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" +dependencies = [ + "cfg-if", + "fastrand", + "libc", + "redox_syscall", + "remove_dir_all", + "winapi", +] + +[[package]] +name = "thread_local" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" +dependencies = [ + "once_cell", +] + +[[package]] +name = "time" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c3f9a28b618c3a6b9251b6908e9c99e04b9e5c02e6581ccbb67d59c34ef7f9b" +dependencies = [ + "itoa", + "libc", + "num_threads", + "time-macros", +] + +[[package]] +name = "time-macros" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42657b1a6f4d817cda8e7a0ace261fe0cc946cf3a80314390b22cc61ae080792" + +[[package]] +name = "tokio" +version = "1.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0020c875007ad96677dcc890298f4b942882c5d4eb7cc8f439fc3bf813dc9c95" +dependencies = [ + "autocfg", + "bytes", + "libc", + "memchr", + "mio", + "num_cpus", + "once_cell", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "winapi", +] + +[[package]] +name = "tokio-macros" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-stream" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df54d54117d6fdc4e4fea40fe1e4e566b3505700e148a6827e59b34b0d2600d9" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", +] + +[[package]] +name = "toml" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" +dependencies = [ + "serde", +] + +[[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.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fce9567bd60a67d08a16488756721ba392f24f29006402881e43b19aac64307" +dependencies = [ + "cfg-if", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11c75893af559bc8e10716548bdef5cb2b983f8e637db9d0e15126b61b484ee2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aeea4303076558a00714b823f9ad67d58a3bbda1df83d8827d21193156e22f7" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +dependencies = [ + "lazy_static", + "log", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60db860322da191b40952ad9affe65ea23e7dd6a5c442c2c42865810c6ab8e6b" +dependencies = [ + "ansi_term", + "matchers", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "try-lock" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" + +[[package]] +name = "typenum" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" + +[[package]] +name = "ubyte" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c81f0dae7d286ad0d9366d7679a77934cfc3cf3a8d67e82669794412b2368fe6" +dependencies = [ + "serde", +] + +[[package]] +name = "uncased" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09b01702b0fd0b3fadcf98e098780badda8742d4f4a7676615cad90e8ac73622" +dependencies = [ + "serde", + "version_check", +] + +[[package]] +name = "unicode-ident" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf" + +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + +[[package]] +name = "universal-hash" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05" +dependencies = [ + "generic-array", + "subtle", +] + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "want" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +dependencies = [ + "log", + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbedf6db9096bc2364adce0ae0aa636dcd89f3c3f2cd67947062aaf0ca2a10ec" +dependencies = [ + "windows_aarch64_msvc 0.32.0", + "windows_i686_gnu 0.32.0", + "windows_i686_msvc 0.32.0", + "windows_x86_64_gnu 0.32.0", + "windows_x86_64_msvc 0.32.0", +] + +[[package]] +name = "windows-sys" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +dependencies = [ + "windows_aarch64_msvc 0.36.1", + "windows_i686_gnu 0.36.1", + "windows_i686_msvc 0.36.1", + "windows_x86_64_gnu 0.36.1", + "windows_x86_64_msvc 0.36.1", +] + +[[package]] +name = "windows_aarch64_msvc" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8e92753b1c443191654ec532f14c199742964a061be25d77d7a96f09db20bf5" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" + +[[package]] +name = "windows_i686_gnu" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a711c68811799e017b6038e0922cb27a5e2f43a2ddb609fe0b6f3eeda9de615" + +[[package]] +name = "windows_i686_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" + +[[package]] +name = "windows_i686_msvc" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "146c11bb1a02615db74680b32a68e2d61f553cc24c4eb5b4ca10311740e44172" + +[[package]] +name = "windows_i686_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c912b12f7454c6620635bbff3450962753834be2a594819bd5e945af18ec64bc" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "504a2476202769977a040c6364301a3f65d0cc9e3fb08600b2bda150a0488316" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" + +[[package]] +name = "ws281x-rpi" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d768fe61b40787b95662aece079d7477f5d9c3787a717aade53ca89f4c4ada3a" +dependencies = [ + "bindgen", + "cc", + "smart-leds-trait", +] + +[[package]] +name = "yansi" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..c027c71 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "neolights" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +smart-leds = "0.3.0" +ws281x-rpi = "0.0.1" +rocket = { version="0.5.0-rc.2", features = ["json"] } +# rusqlite = { version = "0.28.0", features = ["bundled"] } +r2d2 = "0.8.10" +r2d2_sqlite = { version = "0.21.0", features = ["bundled"] } +tokio = { version = "1.21.1", features = ["full"] } +serde = "1.0.145" + diff --git a/src/animations.rs b/src/animations.rs new file mode 100644 index 0000000..2c454e7 --- /dev/null +++ b/src/animations.rs @@ -0,0 +1,393 @@ +use std::{u8, error::Error}; + +use rocket::{serde::{json::{Json, serde_json::json}, Deserialize, Serialize}, State}; + +use crate::{utils::ApiResponse, DBConn, ASender, Action}; +use crate::DBPool; + +#[derive(Debug, Deserialize, Serialize, Clone)] +#[serde(crate = "rocket::serde")] +#[serde(rename_all = "camelCase")] +pub struct LigthSetting { + start: Option, + end: Option, + tags: Option, + r: u8, + b: u8, + g: u8, +} + +impl LigthSetting { + pub fn get_start(&self) -> Option{ + self.start + } + pub fn get_end(&self) -> Option{ + self.end + } + pub fn get_tags(&self) -> Option{ + if self.tags.as_ref().is_some() { + return Some(self.tags.as_ref().unwrap().to_string()); + } + None + } + pub fn get_r(&self) -> u8 { + self.r + } + pub fn get_b(&self) -> u8 { + self.b + } + pub fn get_g(&self) -> u8 { + self.g + } +} + + +#[derive(Debug, Deserialize, Serialize, Clone)] +#[serde(crate = "rocket::serde")] +#[serde(rename_all = "camelCase")] +pub struct KeyFrame { + duration: u32, + settings: Vec +} + +impl KeyFrame { + pub fn get_settings(&self) -> Vec { + self.settings.clone() + } + + pub fn get_duration(&self) -> u32 { + self.duration + } +} + +#[derive(Debug, Deserialize, Serialize, Clone)] +#[serde(crate = "rocket::serde")] +#[serde(rename_all = "camelCase")] +pub struct Animation { + key_frames: Vec, + priority: Option, + name: String, + repeat: bool, +} + +impl Animation { + + pub fn get_frames(&self) -> Vec { + self.key_frames.clone() + } + + pub fn get_name(&self) -> String { + self.name.to_string() + } + + pub fn get_priority(&self) -> u32 { + if self.priority.is_none() { 0 } else {self.priority.unwrap()} + } + + pub fn get_repeat(&self) -> bool { + self.repeat + } +} + +#[post("/animation", data= "")] +pub async fn animation(data: Json, db: &State) -> String { + + if data.key_frames.is_empty() { + return json!(ApiResponse {code: 400, message: "KeyFrame are nessesary".to_string()}).to_string(); + } + if data.name.is_empty() { + return json!(ApiResponse {code: 400, message: "Name must not be empty".to_string()}).to_string(); + } + + for key_frame in data.key_frames.iter() { + if key_frame.settings.is_empty() { + return json!(ApiResponse {code: 400, message: "keyFrames.settings can not be empty".to_string()}).to_string(); + } + + if key_frame.duration == 0 { + return json!(ApiResponse {code: 400, message: "keyFrames.duration can not be 0".to_string()}).to_string(); + } + + for setting in key_frame.settings.iter() { + + if setting.tags.is_none() && (setting.start.is_none() || setting.end.is_none()) { + return json!(ApiResponse {code: 400, message: "Either tags or start end pair is needed".to_string()}).to_string(); + } + + if !(setting.start.is_none() && setting.end.is_none()) && (setting.start.is_none() || setting.end.is_none()) { + return json!(ApiResponse {code: 400, message: "Both start and end need to be filled".to_string()}).to_string(); + } + + } + } + + let db_status = add_animation_to_db(data, db); + + if db_status.is_err() || db_status.as_ref().ok().is_none() { + return json!(ApiResponse {code: 500, message: format!("Error setting the animation. Err: {:?}", db_status.err()).to_string()}).to_string(); + } + + let db_status = db_status.ok().unwrap(); + + if !db_status.is_empty() { + return db_status; + } + + json!(ApiResponse {code: 200, message: "Configuration was successful".to_string()}).to_string() +} + +fn get_animation_from_name(conn: &DBConn, name: String) -> Result, Box> { + let mut stmt = conn.prepare("SELECT id FROM animation WHERE name=?1")?; + + let next = stmt.query_map([name], |row| { + row.get(0) + })?.next(); + + if next.is_none() { + return Ok(None); + } + + Ok(next.unwrap()?) +} + +fn get_keyframe_from_index(conn: &DBConn, animation: u32, index: u32) -> Result, Box> { + let mut stmt = conn.prepare("SELECT id FROM keyframe WHERE animation=?1 AND i=?2")?; + + let next = stmt.query_map([animation, index], |row| { + row.get(0) + })?.next(); + + if next.is_none() { + return Ok(None); + } + + Ok(next.unwrap()?) +} + +fn add_animation_to_db(data: Json, pool: &State) -> Result>{ + let priority = if data.priority.is_some() { data.priority.unwrap() } else { 0 }; + + let conn = pool.get()?; + + println!("g: {}", data.name); + + let name = get_animation_from_name(&conn, data.name.to_string())?; + + println!("t: {:?}", name); + + if name.is_some() { + return Ok(json!(ApiResponse {code: 500, message: "Animation with that name is already exists.".to_string()}).to_string()); + } + + conn.execute("INSERT INTO animation (priority, name, repeat) VALUES (?1, ?2, ?3);", (priority, data.name.to_string(), data.repeat ))?; + + let name = get_animation_from_name(&conn, data.name.to_string())?; + if name.is_none() { + return Ok(json!(ApiResponse {code: 500, message: "Failed to create animation.".to_string()}).to_string()); + } + let animation_id = name.unwrap(); + + let mut i = 0; + + for key_frame in data.key_frames.clone() { + conn.execute("INSERT INTO keyframe (duration, animation, i) VALUES (?1, ?2, ?3);", (key_frame.duration, animation_id, i))?; + + let keyframe = get_keyframe_from_index(&conn, animation_id, i)?; + if keyframe.is_none() { + return Ok(json!(ApiResponse {code: 500, message: "Failed to create animation.".to_string()}).to_string()); + } + let keyframe = keyframe.unwrap(); + + for setting in key_frame.settings { + conn.execute("INSERT INTO lightsetting (start, end, tags, r, b, g, keyframe) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7);", (setting.start, setting.end, setting.tags, setting.r, setting.b, setting.g, keyframe))?; + } + + i += 1; + } + + Ok("".to_string()) +} + +/** + * + * Stop animations + * + */ +#[get("/stop/")] +pub async fn stop_animation(name: &str, stop_sender: &State>) -> String { + + let r = stop_sender.lock().unwrap().send(name.to_string()); + + if r.is_err() || r.ok().is_none() { + return json!(ApiResponse {code: 500, message: "Something went wrong".to_string()}).to_string() + } + + json!(ApiResponse {code: 200, message: "Configuration was successful".to_string()}).to_string() +} + + +/** + * + * Start animations + * + */ +#[get("/start/")] +pub async fn start_animation(name: &str, start_sender: &State>, db: &State) -> String { + + let animation = get_animation(name, db); + + if animation.is_err() || animation.as_ref().ok().is_none() { + return json!(ApiResponse {code: 500, message: format!("Probelms with the db: {:?}", animation.err()).to_string()}).to_string() + } + + let animation = animation.ok().unwrap(); + + if animation.is_none() { + return json!(ApiResponse {code: 404, message: "Animation not found".to_string()}).to_string() + } + + let animation = animation.unwrap(); + + let r = start_sender.lock().unwrap().send(animation); + if r.is_err() || r.as_ref().ok().is_none() { + return json!(ApiResponse {code: 500, message: "Probelms with the db".to_string()}).to_string() + } + + json!(ApiResponse {code: 200, message: "Started animation".to_string()}).to_string() +} + +/** + * + * Clear animations + * + */ +#[get("/clear/")] +pub async fn clear(name: &str, start_sender: &State>, db: &State, action: &State>) -> String { + + let r = action.lock().unwrap().send(Action::Clear); + + if r.is_err() || r.ok().is_none() { + return json!(ApiResponse {code: 500, message: "Something went wrong".to_string()}).to_string() + } + + let animation = get_animation(name, db); + + if animation.is_err() || animation.as_ref().ok().is_none() { + return json!(ApiResponse {code: 500, message: format!("Probelms with the db: {:?}", animation.err()).to_string()}).to_string() + } + + let animation = animation.ok().unwrap(); + + if animation.is_none() { + return json!(ApiResponse {code: 404, message: "Animation not found".to_string()}).to_string() + } + + let animation = animation.unwrap(); + + let r = start_sender.lock().unwrap().send(animation); + if r.is_err() || r.as_ref().ok().is_none() { + return json!(ApiResponse {code: 500, message: "Probelms with the db".to_string()}).to_string() + } + + json!(ApiResponse {code: 200, message: "Started animation".to_string()}).to_string() +} + +pub fn get_animation(name: &str, db: &State) -> Result, Box> { + + let conn = db.get()?; + + let mut stmt = conn.prepare("SELECT id, priority, name, repeat FROM animation WHERE name=?1;")?; + + struct AnimationId { + animation: Animation, + id: u8 + }; + + let next = stmt.query_map([name], |row| { + Ok(AnimationId { + animation: Animation { + key_frames: Vec::new(), + priority: Some(row.get(1)?), + name: row.get(2)?, + repeat: row.get(3)? + }, + id: row.get(0)? + }) + })?.next(); + + if next.is_none() { + return Ok(None); + } + + let mut animation = next.unwrap()?; + + struct KeyFrameId { + keyframe: KeyFrame, + id: u8, + } + + let mut stmt = conn.prepare("SELECT id, duration from keyframe where animation=?1 order by i asc")?; + + let mut map = stmt.query_map([animation.id], |row| { + Ok(KeyFrameId { + id: row.get(0)?, + keyframe: KeyFrame { + duration: row.get(1)?, + settings: Vec::new() + } + }) + })?; + + while let Some(key_frame_id) = map.next() { + let mut key_frame_id = key_frame_id?; + + let mut stmt = conn.prepare("SELECT start, end, tags, r, b, g from lightsetting where keyframe=?1")?; + + let mut light_setting_map = stmt.query_map([key_frame_id.id], |row| { + Ok(LigthSetting { + start: row.get(0)?, + end: row.get(1)?, + tags: row.get(2)?, + r: row.get(3)?, + b: row.get(4)?, + g: row.get(5)? + }) + })?; + + while let Some(light_setting) = light_setting_map.next() { + key_frame_id.keyframe.settings.push(light_setting?); + } + + animation.animation.key_frames.push(key_frame_id.keyframe); + } + + Ok(Some(animation.animation)) +} + +/** + * + * Delete animations + * + */ +#[get("/delete/")] +pub async fn delete(name: &str, start_sender: &State>, db: &State) -> String { + + let animation = remove_animation(name, db); + + if animation.is_err() || animation.as_ref().ok().is_none() { + return json!(ApiResponse {code: 500, message: format!("Probelms with the db: {:?}", animation.err()).to_string()}).to_string() + } + + json!(ApiResponse {code: 200, message: "Deleted animation".to_string()}).to_string() +} + +pub fn remove_animation(name: &str, db: &State) -> Result<(), Box> { + + let conn = db.get()?; + + conn.execute("delete from lightsetting where id in (select l.id from lightsetting as l left join keyframe as k on l.keyframe = k.id left join animation as a on k.animation = a.id where a.name=?1);", [name])?; + conn.execute("delete from keyframe where id in (select k.id from keyframe as k left join animation as a on k.animation = a.id where a.name=?1);", [name])?; + conn.execute("delete from animation where name=?1;", [name])?; + + Ok(()) +} diff --git a/src/configure.rs b/src/configure.rs new file mode 100644 index 0000000..8c60150 --- /dev/null +++ b/src/configure.rs @@ -0,0 +1,102 @@ +use rocket::{serde::{json::{Json, serde_json::json}, Deserialize, Serialize}, State}; + +use crate::{utils::ApiResponse, Action, ASender}; +use crate::DBPool; + +#[derive(Debug, Deserialize, Serialize, Clone)] +#[serde(crate = "rocket::serde")] +#[serde(rename_all = "camelCase")] +pub struct LightConfiguration { + number: u32, + direction_x: u32, + direction_y: u32, + direction_z: u32, + tags: Option +} + +#[derive(Debug, Deserialize, Serialize, Clone)] +#[serde(crate = "rocket::serde")] +#[serde(rename_all = "camelCase")] +pub struct LightConfigurationRequest { + lights: Vec +} + +#[post("/configure", data= "")] +pub async fn configure(data: Json, db: &State, action: &State>) -> String { + + let conn = db.get(); + + if conn.is_err() || conn.as_ref().ok().is_none() { + return json!(ApiResponse {code: 500, message: "Clould not configure. Err: 1".to_string()}).to_string(); + } + + let conn = conn.ok().unwrap(); + + let stmt = conn.prepare("SELECT configured from meta"); + + if stmt.is_err() || stmt.as_ref().ok().is_none() { + return json!(ApiResponse {code: 500, message: format!("Clould not configure. Err: 2, {:?}", stmt)}).to_string(); + } + + let mut stmt = stmt.ok().unwrap(); + + struct Data { + configured: bool, + } + + let version_iter = stmt.query_map([], |row| { + Ok(Data { + configured: row.get(0)? + }) + }); + + if version_iter.is_err() || version_iter.as_ref().ok().is_none() { + return json!(ApiResponse {code: 500, message: "Clould not configure. Err: 3".to_string()}).to_string(); + } + + let version_iter = version_iter.ok().unwrap(); + + let mut recreate = false; + + for data in version_iter { + if data.unwrap().configured { + println!("Already configured deleting current"); + recreate = true; + break; + } + } + + drop(stmt); + + if recreate { + let stmt = conn.execute("DELETE FROM configuration;", ()); + if stmt.is_err() || stmt.as_ref().ok().is_none() { + return json!(ApiResponse {code: 500, message: format!("Clould not configure. Err: 4, {:?}", stmt)}).to_string(); + } + } + + for light in data.lights.iter() { + + let mut tags: String = "".to_string(); + + if light.tags.is_some() { + tags = light.tags.as_ref().unwrap().to_string() + } + + let stmt = conn.execute( + "INSERT INTO configuration (ledcount, directionX, directionY, directionZ, tags) VALUES (?1, ?2, ?3, ?4, ?5);", + (light.number, light.direction_x, light.direction_y, light.direction_z, tags)); + + if stmt.is_err() || stmt.as_ref().ok().is_none() { + return json!(ApiResponse {code: 500, message: format!("Clould not configure. Err: 5, {:?}", stmt)}).to_string(); + } + } + + let send = action.lock().unwrap().send(Action::Reload); + + if send.is_err() || send.ok().is_none() { + return json!(ApiResponse {code: 500, message: "Failed to reload".to_string()}).to_string() + } + + json!(ApiResponse {code: 200, message: "Configuration was successful".to_string()}).to_string() +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..904c5d0 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,354 @@ +#[macro_use] +extern crate rocket; +//use std::{thread, time::Duration, sync::Arc, io}; +use ::std::sync::Arc; + +mod animations; +mod configure; +mod render; +mod utils; + +use animations::Animation; +use r2d2::PooledConnection; +use utils::ApiResponse; + +use rocket::{State, serde::json::serde_json::json}; + +use r2d2_sqlite::SqliteConnectionManager; + +//use std::sync::atomic::AtomicBool; + +use std::{ + error::Error, + sync::{ + mpsc::{self, Receiver, Sender}, + Mutex, + } +}; + +pub type DBPool = Arc>; +pub type DBConn = PooledConnection; +pub type GResult = Result<(), Box>; +pub type ASender = Arc>>; + +#[get("/")] +fn index() -> &'static str { + "Hello World" +} + +pub enum Action { + Reload, + Stop, + Clear +} + +#[get("/quit")] +async fn quit(shutdown: rocket::Shutdown, action: &State>) -> String { + println!("Got Shutdown"); + + let send = action.lock().unwrap().send(Action::Stop); + + if send.is_err() || send.ok().is_none() { + return json!(ApiResponse {code: 500, message: "Failed to stop".to_string()}).to_string() + } + + shutdown.notify(); + + json!(ApiResponse {code: 200, message: "Stoped".to_string()}).to_string() +} + +#[get("/reload")] +async fn reload(action: &State>) -> String { + println!("Got Shutdown"); + + let send = action.lock().unwrap().send(Action::Reload); + + if send.is_err() || send.ok().is_none() { + return json!(ApiResponse {code: 500, message: "Failed to reload".to_string()}).to_string() + } + + json!(ApiResponse {code: 200, message: "Reloaded".to_string()}).to_string() +} + +fn ligth_controll( + pool: DBPool, + action: Receiver, + start_ani: Receiver, + stop_ani: Receiver, +) { + println!("Data loop started"); + + let render = render::Render::new(pool.clone()); + + if render.is_err() || render.as_ref().ok().is_none() { + println!("something every wrong {:?}", render.err()); + return; + } + + let mut render = render.ok().unwrap(); + + 'mainloop: loop { + let action = action.try_recv(); + + if action.is_ok() { + match action.ok().unwrap() { + Action::Reload => { + let result = render.load_config(); + if result.is_err() || result.as_ref().ok().is_none() { + println!("Ehh failed to load config i guess: {:?}", result.err()); + } + }, + Action::Clear => { + render.blank(); + }, + Action::Stop => { + render.blank(); + render.render(); + break 'mainloop; + }, + } + } + + let ani = start_ani.try_recv(); + + if ani.is_ok() { + println!("Added animation"); + //TODO + render.add_animation(ani.ok().unwrap()); + //ani.ok().unwrap(). + } + + let ani = stop_ani.try_recv(); + + if ani.is_ok() { + render.remove_animation(ani.ok().unwrap()); + } + + render.render(); + + } + + println!("stoped main loop"); +} + +const DATAVERSION: &str = "0.0.10"; + +fn setup_database(pool: DBPool) -> GResult { + let conn = pool.get()?; + + println!("Trying to get meta data"); + + let stmt = conn.prepare("SELECT version from meta"); + + if stmt.is_err() || stmt.as_ref().ok().is_none() { + return create_database(pool); + } + + let mut stmt = stmt?; + + struct Data { + version: String, + } + + let version_iter = stmt.query_map([], |row| { + Ok(Data { + version: row.get(0)?, + }) + }); + + println!("Process meta"); + + if version_iter.is_err() || version_iter.as_ref().ok().is_none() { + create_database(pool)?; + } else { + let version_iter = version_iter.ok().unwrap(); + + let mut recreate = true; + + for data in version_iter { + let version = data.unwrap().version; + println!("Found version {}", version); + + if !DATAVERSION.to_string().eq(&version) { + println!("Mismatched versions recreating database"); + recreate = true; + break; + } + + recreate = false; + } + + if recreate { + create_database(pool)?; + } + } + Ok(()) +} + +fn create_database(pool: DBPool) -> GResult { + let conn = pool.get()?; + + println!("Createing the database"); + + println!("Createing new meta table. With version {}", DATAVERSION); + println!("Drop old meta table"); + conn.execute("DROP TABLE IF EXISTS meta;", ())?; + // Create the database + println!("create new meta table"); + conn.execute( + "CREATE TABLE meta ( + id INTEGER PRIMARY KEY, + version TEXT, + configured Boolean + );", + (), + )?; + println!("insert data"); + conn.execute( + "INSERT INTO meta (version, configured) VALUES (?1, ?2);", + (&DATAVERSION, false), + )?; + + println!( + "Createing new configuration table. With version {}", + DATAVERSION + ); + println!("Drop configuration table"); + conn.execute("DROP TABLE IF EXISTS configuration", ())?; + println!("Create new configuration table"); + conn.execute( + "CREATE TABLE configuration ( + id INTEGER PRIMARY KEY, + ledcount INTEGER, + directionX INTEGER, + directionY INTEGER, + directionZ INTEGER, + tags VARCHAR(255) + );", + (), + )?; + + println!( + "Createing new Animation table. With version {}", + DATAVERSION + ); + println!("Drop Animation table and references"); + conn.execute("DROP TABLE IF EXISTS lightsetting", ())?; + conn.execute("DROP TABLE IF EXISTS keyframe", ())?; + conn.execute("DROP TABLE IF EXISTS animation", ())?; + println!("Create new animation table"); + conn.execute( + "CREATE TABLE animation ( + id INTEGER PRIMARY KEY, + priority INTEGER, + name VARCHAR(255), + repeat BOOLEAN + );", + (), + )?; + + println!( + "Createing new key_frame table. With version {}", + DATAVERSION + ); + println!("Drop key_frame table"); + println!("Create new key_frame table"); + conn.execute( + "CREATE TABLE keyframe ( + id INTEGER PRIMARY KEY, + i INTEGER, + duration INTEGER, + animation INTEGER, + FOREIGN KEY(animation) REFERENCES animation(id) ON DELETE CASCADE + );", + (), + )?; + + println!( + "Createing new LigthSetting table. With version {}", + DATAVERSION + ); + println!("Drop LigthSetting table"); + println!("Create new light_setting table"); + conn.execute( + "CREATE TABLE lightsetting ( + id INTEGER PRIMARY KEY, + start INTEGER, + end INTEGER, + tags VARCHAR(255), + r INTEGER, + b INTEGER, + g INTEGER, + keyframe INTEGER, + FOREIGN KEY(keyframe) REFERENCES keyframe(id) ON DELETE CASCADE + );", + (), + )?; + + Ok(()) +} + +#[rocket::main] +async fn main() -> GResult { + println!("Program start"); + + println!("Try to connect db"); + let sqlite_conn_manager = SqliteConnectionManager::file("ligths.db"); + let conn_pool = r2d2::Pool::new(sqlite_conn_manager).expect("Failed to create pool"); + let conn_pool_arc = Arc::new(conn_pool); + + { + let pool = conn_pool_arc.clone(); + let dd = setup_database(pool); + println!("{:?}", dd); + dd.ok().unwrap(); + } + + let (action_sender, action_receiver): (Sender, Receiver) = mpsc::channel(); + let (start_animation_sender, start_animation_receiver): ( + Sender, + Receiver, + ) = mpsc::channel(); + let (stop_animation_sender, stop_animation_receiver): (Sender, Receiver) = + mpsc::channel(); + + let pool_clone = conn_pool_arc.clone(); + + let ligths_controll = std::thread::spawn(move || { + ligth_controll( + pool_clone, + action_receiver, + start_animation_receiver, + stop_animation_receiver, + ); + }); + + let cfg = rocket::Config::figment() + .merge(("port", 3000)) + .merge(("address", "0.0.0.0")); + + let _rocket = rocket::custom(cfg) + .mount( + "/", + routes![ + index, + quit, + reload, + configure::configure, + animations::animation, + animations::start_animation, + animations::stop_animation, + animations::clear, + animations::delete + ], + ) + .manage(conn_pool_arc.clone()) + .manage(Arc::new(Mutex::new(action_sender))) + .manage(Arc::new(Mutex::new(start_animation_sender))) + .manage(Arc::new(Mutex::new(stop_animation_sender))) + .launch() + .await?; + ligths_controll.join().unwrap(); + + Ok(()) +} diff --git a/src/render.rs b/src/render.rs new file mode 100644 index 0000000..4aacf86 --- /dev/null +++ b/src/render.rs @@ -0,0 +1,290 @@ +use ws281x_rpi::Ws2812Rpi; + +use crate::{DBPool, animations::Animation}; + +use std::error::Error; +use smart_leds::{RGB8, SmartLedsWrite}; +use std::time::{SystemTime, UNIX_EPOCH}; + +#[derive(Clone, Debug)] +struct LocalLedConfiguration { + tag: Option, + start: usize, + end: usize +} + +#[derive(Clone)] +pub struct LigthSetting { + start: Option, + end: Option, + tags: Option, + color: RGB8, +} + +#[derive(Clone)] +pub struct KeyFrame { + duration: u64, + settings: Vec +} + +#[derive(Clone)] +pub struct RenderAnimation { + key_frames: Vec, + priority: u32, + name: String, + + current_frame: usize, + start_time: u64, + reset: bool, +} + +pub struct Render { + conn: DBPool, + num_leds: u32, + + ws: Option, + last: Vec, + + animations: Vec, + + local_led_config: Vec, +} + +fn try_into_usize (input: Option) -> Option { + if input.is_none() {return None;} + + let t: Result = input.unwrap().try_into(); + + if t.is_err() {return None;} + + return t.ok(); +} + +impl Render { + pub fn new(conn: DBPool) -> Result> { + let mut render = Render { + conn, + num_leds: 0, + ws: None, + animations: vec![], + local_led_config: vec![], + last: vec![], + }; + + render.load_config()?; + + return Ok(render); + } + + pub fn load_config(&mut self) -> Result<(), Box> { + println!("Load config"); + // GPIO Pin 10 is SPI + // Other modes and PINs are available depending on the Raspberry Pi revision + // Additional OS configuration might be needed for any mode. + // Check https://github.com/jgarff/rpi_ws281x for more information. + const PIN: i32 = 18; + + let conn = self.conn.get()?; + + let stmt = conn.prepare("SELECT ledcount, tags from configuration;"); + + if stmt.is_err() || stmt.as_ref().ok().is_none() { + Err(format!("Something went wrong while reading the database {:?}", stmt.as_ref().err()))?; + } + + let mut stmt = stmt?; + + struct Data { + ledcount: u32, + tag: String + } + + let version_iter = stmt.query_map([], |row| { + Ok(Data { + ledcount: row.get(0)?, + tag: row.get(1)? + }) + }); + + if version_iter.is_err() || version_iter.as_ref().ok().is_none() { + Err(format!("Something went wrong while reading the database {:?}", version_iter.as_ref().err()))?; + } + + let version_iter = version_iter.ok().unwrap(); + + let mut current_pos = 0; + + let mut local_led_config = Vec::new(); + + for data in version_iter { + + let data = data?; + + let tag = if data.tag.is_empty() { None } else { Some(data.tag) }; + + let start = current_pos; + let end = current_pos + data.ledcount; + current_pos = end; + + let start: Result = start.try_into(); + let end: Result = end.try_into(); + + if start.is_err() || start.ok().is_none() || end.is_err() || end.ok().is_none() { + println!("Skiping loading configuration"); + continue; + } + + let start = start.ok().unwrap(); + let end = end.ok().unwrap(); + + local_led_config.push(LocalLedConfiguration { + tag, + start, + end + }); + } + + self.num_leds = current_pos; + println!("Loaded: {} leds, with config: {:?}", self.num_leds, local_led_config); + self.local_led_config = local_led_config; + + self.ws = Some(Ws2812Rpi::new(current_pos as i32, PIN).unwrap()); + + println!("Here"); + + Ok(()) + } + + pub fn add_animation(&mut self, animation: Animation) { + + println!("Added animation"); + + let mut key_frames = Vec::new(); + + for frame in animation.get_frames().iter() { + let mut light_settings = Vec::new(); + + for setting in frame.get_settings() { + light_settings.push(LigthSetting { + tags: setting.get_tags(), + start: try_into_usize(setting.get_start()), + end: try_into_usize(setting.get_end()), + color: RGB8::new(setting.get_r(), setting.get_g(), setting.get_b()), + }); + } + + key_frames.push(KeyFrame { duration: frame.get_duration().into(), settings: light_settings }) + } + + let new_animation = RenderAnimation { + key_frames, + priority: animation.get_priority(), + name: animation.get_name(), + current_frame: 0, + start_time: 0, + reset: animation.get_repeat(), + }; + + self.animations.push(new_animation); + + self.animations.sort_by(|a,b| a.priority.partial_cmp(&b.priority).unwrap()) + } + + pub fn blank(&mut self) { + self.animations = Vec::new(); + } + + pub fn remove_animation(&mut self, animation_name: String) { + self.animations = self.animations.clone().into_iter().filter(|ani| !ani.name.eq(&animation_name)).collect::>(); + } + + pub fn proccess_settings (&mut self, data: &mut Vec, settings: &Vec) { + fn load_led_into_light (data: &mut Vec, color: RGB8, start: usize, end: usize) { + for i in start..=end { + data[i] = color; + } + } + + for setting in settings { + if setting.tags.is_some() { + let tags = setting.tags.as_ref().unwrap().to_string(); + let tags = tags.split(","); + let tags_fn = |t: String| tags.clone().into_iter().any(|tag| tag.eq(&t)); + for config in self.local_led_config.clone() { + if config.tag.is_some() && tags_fn(config.tag.unwrap()) { + load_led_into_light(data, setting.color, config.start, config.end); + } + } + } + + if setting.start.is_some() && setting.end.is_some() { + load_led_into_light(data, setting.color, setting.start.unwrap(), setting.end.unwrap()); + } + } + } + + pub fn render(&mut self) { + + if self.ws.is_none() { return; } + + let mut data = vec![RGB8::default(); self.num_leds.try_into().unwrap()]; + + let time = SystemTime::now().duration_since(UNIX_EPOCH).expect("Time went backwards").as_secs(); + + let mut to_clean: Vec = Vec::new(); + + let animations = self.animations.clone().iter_mut().map(|animation| { + let mut animation = animation.to_owned(); + + let mut start_time = animation.start_time; + + if start_time == 0 { + animation.start_time = time; + animation.current_frame = 0; + + self.proccess_settings(&mut data, &animation.key_frames[0].settings); + return animation; + } + + while start_time + animation.key_frames[animation.current_frame].duration < time { + start_time += animation.key_frames[animation.current_frame].duration; + animation.start_time = start_time; + + if animation.current_frame + 1 >= animation.key_frames.len() { + if animation.reset { + animation.start_time = time; + animation.current_frame = 0; + self.proccess_settings(&mut data, &animation.key_frames[0].settings); + } else { + to_clean.push(animation.name.to_string()); + } + return animation; + } + + animation.current_frame += 1; + } + + let cf = animation.current_frame; + + self.proccess_settings(&mut data, &animation.key_frames[cf].settings); + + return animation; + }).collect(); + + self.animations = animations; + + to_clean.iter().for_each(|i| self.remove_animation(i.to_string())); + + if self.last.is_empty() || !self.last.clone().iter().eq(data.clone().iter()) { + let err = self.ws.as_mut().unwrap().write(data.clone().into_iter()); + + if err.is_err() || err.ok().is_none() { + println!("Failed to write data"); + } + + self.last = data; + } + + } +} + diff --git a/src/utils.rs b/src/utils.rs new file mode 100644 index 0000000..1901568 --- /dev/null +++ b/src/utils.rs @@ -0,0 +1,11 @@ +use rocket::{serde::{Deserialize, Serialize}, Responder, http::{ContentType, Header}}; + +#[derive(Deserialize, Serialize)] +#[serde(crate="rocket::serde")] +pub struct ApiResponse { + pub code: u32, + pub message: String +} + +#[derive(Responder)] +pub struct ApiResponder(String);