From a5cbb1e759818f5801f90817ada41da28e6c2bec Mon Sep 17 00:00:00 2001 From: Jakob Dalsgaard Date: Sun, 9 Feb 2025 14:02:42 +0100 Subject: [PATCH] Updates all crates.... Terrifying and time consuming - have not run on ESP32C3 yet... --- Cargo.lock | 305 +++++++++++++++++++++++++----------------- Cargo.toml | 27 ++-- set-env.sh | 7 +- src/database.rs | 8 +- src/httpd.rs | 87 ++++++++++-- src/main.rs | 19 ++- src/random.rs | 3 +- src/serial.rs | 26 ++-- src/static/app.js | 161 ++++++++++++++++++---- src/static/styles.css | 69 +++++++++- src/wifi.rs | 4 +- 11 files changed, 512 insertions(+), 204 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 86b5e34..351dfeb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -20,12 +20,6 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" -[[package]] -name = "bare-metal" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8fe8f5a8a398345e52358e18ff07cc17a568fbca5c6f73873d3a62056309603" - [[package]] name = "basic-toml" version = "0.1.9" @@ -49,9 +43,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.6.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" [[package]] name = "bytemuck" @@ -144,15 +138,15 @@ dependencies = [ [[package]] name = "data-encoding" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" +checksum = "0e60eed09d8c01d3cee5b7d30acb059b76614c918fa0f992e0dd6eeb10daad6f" [[package]] name = "delegate" -version = "0.13.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc2323e10c92e1cf4d86e11538512e6dc03ceb586842970b6332af3d4046a046" +checksum = "297806318ef30ad066b15792a8372858020ae3ca2e414ee6c2133b1eb9e9e945" dependencies = [ "proc-macro2", "quote", @@ -170,9 +164,9 @@ dependencies = [ [[package]] name = "embassy-embedded-hal" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5794414bc20e0d750f145bc0e82366b19dd078e9e075e8331fb8dd069a1cb6a2" +checksum = "41fea5ef5bed4d3468dfd44f5c9fa4cda8f54c86d4fb4ae683eacf9d39e2ea12" dependencies = [ "embassy-futures", "embassy-sync", @@ -187,9 +181,9 @@ dependencies = [ [[package]] name = "embassy-executor" -version = "0.6.3" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f64f84599b0f4296b92a4b6ac2109bc02340094bda47b9766c5f9ec6a318ebf8" +checksum = "90327bcc66333a507f89ecc4e2d911b265c45f5c9bc241f98eee076752d35ac6" dependencies = [ "critical-section", "document-features", @@ -216,9 +210,9 @@ checksum = "1f878075b9794c1e4ac788c95b728f26aa6366d32eeb10c7051389f898f7d067" [[package]] name = "embassy-net" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f9f2979069031c153e41075a43074c36a64492e598780b27944a605f829d23" +checksum = "ed041cc19a603d657124fddefdcbe5ef8bd60e77d972793ebb57de93394f5949" dependencies = [ "document-features", "embassy-net-driver", @@ -228,7 +222,7 @@ dependencies = [ "embedded-nal-async", "heapless", "managed", - "smoltcp 0.12.0", + "smoltcp", ] [[package]] @@ -239,9 +233,9 @@ checksum = "524eb3c489760508f71360112bca70f6e53173e6fe48fc5f0efd0f5ab217751d" [[package]] name = "embassy-sync" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3899a6e39fa3f54bf8aaf00979f9f9c0145a522f7244810533abbb748be6ce82" +checksum = "8d2c8cdff05a7a51ba0087489ea44b0b1d97a296ca6b1d6d1a33ea7423d34049" dependencies = [ "cfg-if", "critical-section", @@ -253,36 +247,39 @@ dependencies = [ [[package]] name = "embassy-time" -version = "0.3.2" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "158080d48f824fad101d7b2fae2d83ac39e3f7a6fa01811034f7ab8ffc6e7309" +checksum = "f820157f198ada183ad62e0a66f554c610cdcd1a9f27d4b316358103ced7a1f8" dependencies = [ "cfg-if", "critical-section", "document-features", "embassy-time-driver", - "embassy-time-queue-driver", + "embassy-time-queue-utils", "embedded-hal 0.2.7", "embedded-hal 1.0.0", "embedded-hal-async", "futures-util", - "heapless", ] [[package]] name = "embassy-time-driver" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e0c214077aaa9206958b16411c157961fb7990d4ea628120a78d1a5a28aed24" +checksum = "8d45f5d833b6d98bd2aab0c2de70b18bfaa10faf661a1578fd8e5dfb15eb7eba" dependencies = [ "document-features", ] [[package]] -name = "embassy-time-queue-driver" +name = "embassy-time-queue-utils" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1177859559ebf42cd24ae7ba8fe6ee707489b01d0bf471f8827b7b12dcb0bc0" +checksum = "dc55c748d16908a65b166d09ce976575fb8852cf60ccd06174092b41064d8f83" +dependencies = [ + "embassy-executor", + "heapless", +] [[package]] name = "embedded-can" @@ -418,20 +415,22 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "esp-alloc" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5162b6e9cd99cc974ec2742da3cf8433e7332853ae10fec922d174ff20fa4c5f" +checksum = "408c0d4c7f51efb256af18641047b0d83b58a485be9edf5a559da796abef0b63" dependencies = [ + "cfg-if", "critical-section", + "document-features", "enumset", "linked_list_allocator", ] [[package]] name = "esp-backtrace" -version = "0.14.2" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7660d85e3e7b0e113aaeeffb1a155e64a09a5035d4104031875acdba4cb68e" +checksum = "3c83ca63fd02ca40644ae91ae63362e3a6e7f53458f6c1356decf892343d2418" dependencies = [ "esp-build", "esp-println", @@ -439,9 +438,9 @@ dependencies = [ [[package]] name = "esp-build" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b94a4b8d74e7cc7baabcca5b2277b41877e039ad9cd49959d48ef94dac7eab4b" +checksum = "8aa1c8f9954c9506699cf1ca10a2adcc226ff10b6ae3cb9e875cf2c6a0b9a372" dependencies = [ "quote", "syn", @@ -450,22 +449,22 @@ dependencies = [ [[package]] name = "esp-config" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7584e4cd1dac06201fd92fff1c84b396be5458ac4d93e9457e7a89b1b42c60e" +checksum = "bd428a3b4b2975772f24eabea123d45cf6a5e28020396ed5dcb331ee3a904046" dependencies = [ "document-features", ] [[package]] name = "esp-hal" -version = "0.22.0" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a5605e1518d63f7bf9fbd9885e61d2896060d2e4f28954736bdd74da911b676" +checksum = "a573175c540fd1d21a9cf07b0dee286b5a8f4cfde4b35da0f4f4657de7942c45" dependencies = [ "basic-toml", "bitfield", - "bitflags 2.6.0", + "bitflags 2.8.0", "bytemuck", "cfg-if", "chrono", @@ -476,7 +475,6 @@ dependencies = [ "embassy-futures", "embassy-sync", "embedded-can", - "embedded-hal 0.2.7", "embedded-hal 1.0.0", "embedded-hal-async", "embedded-hal-nb", @@ -490,29 +488,34 @@ dependencies = [ "esp-riscv-rt", "esp32c3", "fugit", + "instability", "log", "nb 1.1.0", "paste", "portable-atomic", - "rand_core", + "rand_core 0.6.4", "riscv", "serde", "strum", "ufmt-write", "void", + "xtensa-lx", "xtensa-lx-rt", ] [[package]] name = "esp-hal-embassy" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7d0f2537ea2ff9bea26a1c8bfe43ad580d4c89febf27189653a9cf95f1f7961" +checksum = "4cea15ef146c7689fede0c3a7d765e07b1eb22ef462f1203a137dacc615b031a" dependencies = [ "critical-section", "document-features", "embassy-executor", + "embassy-sync", + "embassy-time", "embassy-time-driver", + "embassy-time-queue-utils", "esp-build", "esp-config", "esp-hal", @@ -524,9 +527,9 @@ dependencies = [ [[package]] name = "esp-hal-procmacros" -version = "0.15.0" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69a9a8706b7d1182b56335d196e70eeb04e2b70f4b8db96432898bd3c2bdb91e" +checksum = "e4a3297005c2b31cd00e2ba50037edc9bddf99da3afe1c97a2d1b0165a312eab" dependencies = [ "darling", "document-features", @@ -540,9 +543,9 @@ dependencies = [ [[package]] name = "esp-metadata" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9972bbb21dcafe430b87f92efc7a788978a2d17cf8f572d104beeb48602482a" +checksum = "fb15c17e50f4cccb0d88305c19eae2d5533d750f0a05b6a05f1c99864974758e" dependencies = [ "anyhow", "basic-toml", @@ -552,9 +555,9 @@ dependencies = [ [[package]] name = "esp-println" -version = "0.12.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee38e87bc7e303c299047c0e9bcd0f8ccca7c7e70d1fd78bbb565db14f33beb6" +checksum = "645e54eb592ca0a3d60213b1695e2a5fc0b51ca6d693c08d6983857224a629ed" dependencies = [ "critical-section", "esp-build", @@ -575,9 +578,9 @@ dependencies = [ [[package]] name = "esp-wifi" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00d36018303cd60a30184c6f605a921038c08ff34afc870e22070ea08a6280a2" +checksum = "321b112db6629693fae49644b1ba28e8b917b58829533e9cdd0400183af1877d" dependencies = [ "cfg-if", "critical-section", @@ -601,15 +604,15 @@ dependencies = [ "num-traits", "portable-atomic", "portable_atomic_enum", - "rand_core", - "smoltcp 0.11.0", + "rand_core 0.6.4", + "smoltcp", ] [[package]] name = "esp-wifi-sys" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7730d6093853119088bbb793e3383801965ebe8fcf91e0817781d94628aaf718" +checksum = "c6b5438361891c431970194a733415006fb3d00b6eb70b3dcb66fd58f04d9b39" dependencies = [ "anyhow", "log", @@ -617,9 +620,9 @@ dependencies = [ [[package]] name = "esp32c3" -version = "0.26.0" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d1750382dc49fa333ee6b1ba96f8c540038b9666f5a233dc1221c98e3236118" +checksum = "61655d48e45039dfac5ae769581fb50ea7f61dea3227b4b744a1a900d03fbbd4" dependencies = [ "critical-section", "vcell", @@ -735,19 +738,38 @@ dependencies = [ "flate2", "quote", "syn", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "indexmap" -version = "2.7.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" +checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" dependencies = [ "equivalent", "hashbrown", ] +[[package]] +name = "indoc" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5" + +[[package]] +name = "instability" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf9fed6d91cfb734e7476a06bde8300a1b94e217e1b523b6f0cd1a01998c71d" +dependencies = [ + "darling", + "indoc", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "itoa" version = "1.0.14" @@ -783,9 +805,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.22" +version = "0.4.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" [[package]] name = "managed" @@ -822,19 +844,13 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "minijinja" -version = "2.5.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c37e1b517d1dcd0e51dc36c4567b9d5a29262b3ec8da6cb5d35e27a8fb529b5" +checksum = "cff7b8df5e85e30b87c2b0b3f58ba3a87b68e133738bf512a7713769326dbca9" dependencies = [ "serde", ] -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - [[package]] name = "miniz_oxide" version = "0.8.3" @@ -844,12 +860,6 @@ dependencies = [ "adler2", ] -[[package]] -name = "mutex-trait" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4bb1638d419e12f8b1c43d9e639abd0d1424285bdea2f76aa231e233c63cd3a" - [[package]] name = "nb" version = "0.1.3" @@ -867,12 +877,11 @@ checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" [[package]] name = "nom" -version = "7.1.3" +version = "8.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" dependencies = [ "memchr", - "minimal-lexical", ] [[package]] @@ -903,9 +912,9 @@ checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "picoserve" -version = "0.13.3" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4086ade38e021293486610bdfd6a520d24e942264c535b297366e234f2feb9be" +checksum = "6d2c9a99cfe7a070728554f1d42f62067937ce30f9b057a6b507e0cc14fe96e9" dependencies = [ "const-sha1", "data-encoding", @@ -916,16 +925,29 @@ dependencies = [ "heapless", "lhash", "log", + "picoserve_derive", "ryu", "serde", "serde-json-core", + "thiserror 2.0.11", +] + +[[package]] +name = "picoserve_derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62ba0d83906d0357fedd23de7c5e3a5235342c248cc1d954d43d5e7b455c375c" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] [[package]] name = "pin-project-lite" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "pin-utils" @@ -1016,9 +1038,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.92" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" dependencies = [ "unicode-ident", ] @@ -1044,6 +1066,15 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +[[package]] +name = "rand_core" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b08f3c9802962f7e1b25113931d94f43ed9725bebc59db9d0c3e9a23b67e15ff" +dependencies = [ + "zerocopy", +] + [[package]] name = "riscv" version = "0.12.1" @@ -1093,9 +1124,9 @@ checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" [[package]] name = "ryu" -version = "1.0.18" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd" [[package]] name = "serde" @@ -1137,19 +1168,6 @@ dependencies = [ "serde", ] -[[package]] -name = "smoltcp" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a1a996951e50b5971a2c8c0fa05a381480d70a933064245c4a223ddc87ccc97" -dependencies = [ - "bitflags 1.3.2", - "byteorder", - "cfg-if", - "heapless", - "managed", -] - [[package]] name = "smoltcp" version = "0.12.0" @@ -1165,9 +1183,9 @@ dependencies = [ [[package]] name = "sntpc" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2927eedca9d3b301b1eb88b81a2e415666ec5a84eb24f1c2129c08fc98ff18be" +checksum = "78f778a0f82b3cf5d75f858eceee38e84d5292f1d03415e88cc4ec45ca6ba8a2" dependencies = [ "cfg-if", "embassy-net", @@ -1218,9 +1236,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.93" +version = "2.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c786062daee0d6db1132800e623df74274a0a87322d8e183338e01b3d98d058" +checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" dependencies = [ "proc-macro2", "quote", @@ -1242,7 +1260,16 @@ version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc" +dependencies = [ + "thiserror-impl 2.0.11", ] [[package]] @@ -1257,10 +1284,21 @@ dependencies = [ ] [[package]] -name = "toml" -version = "0.8.19" +name = "thiserror-impl" +version = "2.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" +checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "toml" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148" dependencies = [ "serde", "serde_spanned", @@ -1279,9 +1317,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.22" +version = "0.22.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" +checksum = "02a8b472d1a3d7c18e2d61a489aee3453fd9031c33e4f55bd533f4a7adca1bee" dependencies = [ "indexmap", "serde", @@ -1298,9 +1336,9 @@ checksum = "e87a2ed6b42ec5e28cc3b94c09982969e9227600b2e3dcbc1db927a84c06bd69" [[package]] name = "unicode-ident" -version = "1.0.14" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" +checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034" [[package]] name = "vcell" @@ -1344,9 +1382,9 @@ dependencies = [ "maud", "nom", "picoserve", - "rand_core", + "rand_core 0.9.0", "serde", - "smoltcp 0.11.0", + "smoltcp", "sntpc", "static_cell", ] @@ -1435,31 +1473,30 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.6.20" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" +checksum = "86e376c75f4f43f44db463cf729e0d3acbf954d13e22c51e26e4c264b4ab545f" dependencies = [ "memchr", ] [[package]] name = "xtensa-lx" -version = "0.9.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e758f94e1a1f71758f94052a2766dcb12604998eb372b8b2e30576e3ab1ba1e6" +checksum = "51cbb46c78cfd284c9378070ab90bae9d14d38b3766cb853a97c0a137f736d5b" dependencies = [ - "bare-metal", - "mutex-trait", + "critical-section", + "document-features", ] [[package]] name = "xtensa-lx-rt" -version = "0.17.2" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c0307d03dadbf95633942e13901984f2059df4c963367348168cbd21c962669" +checksum = "689c2ef159d9cd4fc9503603e9999968a84a30db9bde0f0f880d0cceea0190a9" dependencies = [ "anyhow", - "bare-metal", "document-features", "enum-as-inner", "minijinja", @@ -1482,3 +1519,23 @@ dependencies = [ "quote", "syn", ] + +[[package]] +name = "zerocopy" +version = "0.8.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa91407dacce3a68c56de03abe2760159582b846c6a4acd2f456618087f12713" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06718a168365cad3d5ff0bb133aad346959a2074bd4a85c121255a11304a8626" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/Cargo.toml b/Cargo.toml index 192debc..10e5f1a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,25 +4,25 @@ version = "0.1.0" edition = "2021" [dependencies] -esp-backtrace = { version = "0.14.2", features = [ +esp-backtrace = { version = "0.15.0", features = [ "esp32c3", "exception-handler", "panic-handler", "println", ]} -esp-hal = { version = "0.22.0", features = [ +esp-hal = { version = "0.23.1", features = [ "esp32c3", ] } -esp-println = { version = "0.12.0", features = ["esp32c3", "log"] } +esp-println = { version = "0.13.0", features = ["esp32c3", "log"] } log = { version = "0.4.21" } -esp-alloc = { version = "0.5.0" } +esp-alloc = { version = "0.6.0" } embedded-io = "0.6.1" embedded-io-async = "0.6.1" -embassy-net = { version = "0.5.0", features = [ "tcp", "udp", "dhcpv4", "dns", "medium-ethernet"] } +embassy-net = { version = "0.6.0", features = [ "tcp", "udp", "dhcpv4", "dns", "medium-ethernet"] } -esp-wifi = { version = "0.11.0", default-features=false, features = [ +esp-wifi = { version = "0.12.0", default-features=false, features = [ "esp32c3", "utils", "wifi", @@ -30,13 +30,12 @@ esp-wifi = { version = "0.11.0", default-features=false, features = [ "log", ] } embassy-sync = "0.6.1" -rand_core = "0.6.4" -nom = { version = "7.1.3", default-features = false, features = [ "alloc" ] } +rand_core = "0.9.0" +nom = { version = "8", default-features = false, features = [ "alloc" ] } heapless = { version = "0.8.0", default-features = false } -smoltcp = { version = "0.11.0", default-features = false, features = [ +smoltcp = { version = "0.12.0", default-features = false, features = [ "medium-ethernet", "proto-dhcpv4", - "proto-igmp", "proto-ipv4", "socket-dhcpv4", "socket-icmp", @@ -44,15 +43,15 @@ smoltcp = { version = "0.11.0", default-features = false, features = [ "socket-tcp", "socket-udp", ] } -embassy-executor = { version = "0.6.0", features = [ +embassy-executor = { version = "0.7.0", features = [ "task-arena-size-163840" ] } -embassy-time = { version = "0.3.1", features = ["generic-queue-8"] } -esp-hal-embassy = { version = "0.5.0", features = ["esp32c3"] } +embassy-time = { version = "0.4.0", features = ["generic-queue-8"] } +esp-hal-embassy = { version = "0.6.0", features = ["esp32c3"] } static_cell = { version = "2.1.0", features = ["nightly"] } critical-section = "1.2.0" maud = { path = "/home/jda/src/rust/maud/target/package/maud-0.26.0", features = ["alloc", "picoserve"] } -picoserve = { version = "0.13.3", default-features = false, features = [ +picoserve = { version = "0.14.1", default-features = false, features = [ "alloc", "embassy", "log", diff --git a/set-env.sh b/set-env.sh index de91c28..b56b379 100644 --- a/set-env.sh +++ b/set-env.sh @@ -1,5 +1,6 @@ echo "Execute as '. ./set-env.sh'" read -p "wifi ssid " WIFI_SSID -read -p "wifi password " WIFI_PASSWORD -read -p "esp loglevel (trace, debug, info, warn, error) " ESP_LOGLEVEL -export WIFI_SSID WIFI_PASSWORD ESP_LOGLEVEL +read -s -p "wifi password " WIFI_PASSWORD +echo +read -p "esp loglevel (trace, debug, info, warn, error) " ESP_LOG +export WIFI_SSID WIFI_PASSWORD ESP_LOG diff --git a/src/database.rs b/src/database.rs index f05297f..9a7e58e 100644 --- a/src/database.rs +++ b/src/database.rs @@ -1,6 +1,6 @@ -use embassy_sync::blocking_mutex::raw::{CriticalSectionRawMutex, NoopRawMutex, RawMutex}; +use embassy_sync::blocking_mutex::raw::{CriticalSectionRawMutex, RawMutex}; use embassy_sync::blocking_mutex::Mutex; use embassy_time::Instant; use alloc::vec::Vec; @@ -9,8 +9,8 @@ use crate::serial; pub struct DataPoint { pub instant: Instant, - t1: i8, - t2: i8, + pub t1: i8, + pub t2: i8, pub target: i8, pub current: i8, } @@ -63,7 +63,6 @@ impl RingBuffer { /** * Get oldest item in the ringbuffer - */ pub fn get_first(&self) -> Option { if self.has_wrapped { Some(self.buf[self.index]) @@ -73,6 +72,7 @@ impl RingBuffer { None } } + */ /** * Get all items in the buffer, oldest at index 0, diff --git a/src/httpd.rs b/src/httpd.rs index 0e685c5..cd4dc9f 100644 --- a/src/httpd.rs +++ b/src/httpd.rs @@ -1,19 +1,23 @@ -use picoserve::routing::{get, get_service}; +use picoserve::routing::{get, get_service, parse_path_segment}; use picoserve::response::{IntoResponse, File, Json}; -use embassy_time::{Duration, Instant}; +use picoserve::response::status::StatusCode; +use embassy_time::{Duration, Instant, with_timeout}; use embassy_net::Stack; use maud::{DOCTYPE, html, Markup}; use alloc::vec::Vec; -use crate::sntp_client::get_now; use crate::sntp_client::get_instant; use serde::{Serialize, Serializer}; use serde::ser::SerializeSeq; use include_file_compress::include_file_compress_deflate; - +use crate::serial; use crate::database::DATAPOINT_BUFFER; +use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; +use embassy_sync::mutex::Mutex; + + const STYLES_CSS_FILENAME: &str = concat!("/styles-", env!("CARGO_PKG_VERSION_SAFE"), ".css"); -const APP_JS_FILENAME: &str = concat!("/app-", env!("CARGO_PKG_VERSION_SAFE"), ".css"); +const APP_JS_FILENAME: &str = concat!("/app-", env!("CARGO_PKG_VERSION_SAFE"), ".js"); static PICO_CONFIG : picoserve::Config = picoserve::Config::new( picoserve::Timeouts { @@ -43,8 +47,16 @@ async fn web_task( ) -> ! { let api_router = picoserve::Router::new() .route("/latest", get(|| async { latest() })) - .route("/allreadings", get(|| async { allreadings() })); + .route("/allreadings", get(|| async { allreadings() })) + .route("/metrics", get(|| async { metrics () })) + .route("/cmd/start", get(|| { cmd_start() })) + .route("/cmd/stop", get(|| { cmd_stop() })) + .route("/cmd/ventilate", get(|| { cmd_ventilate() })) + .route(("/cmd/temperature", parse_path_segment::()), get(|t| { cmd_temperature(t) })); + let image_router = picoserve::Router::new() + .route("/favicon.png", get_service(File::with_content_type_and_headers(&PNG_CONTENT_TYPE, + include_bytes!("static/favicon.png"), CACHEABLE_IMAGE_HEADERS))) .route("/risc-v-logo.png", get_service(File::with_content_type_and_headers(&PNG_CONTENT_TYPE, include_bytes!("static/risc-v-logo.png"), CACHEABLE_IMAGE_HEADERS))) .route("/espressif-logo.png", get_service(File::with_content_type_and_headers(&PNG_CONTENT_TYPE, @@ -85,6 +97,7 @@ fn page(heading: &str, content: Markup) -> Markup { html { head { link rel="stylesheet" type="text/css" href=(STYLES_CSS_FILENAME); + link rel="icon" type="image/png" href="/images/facicon.png" script src=(APP_JS_FILENAME) {}; title { (heading) } } @@ -184,6 +197,15 @@ impl LatestResponse { } } +fn metrics() -> impl IntoResponse { + match DATAPOINT_BUFFER.get_latest() { + None => "".into(), + Some(datapoint) => { + alloc::format!(include_str!("static/prometheus-template.txt"), target = datapoint.target, temperature = datapoint.current, command = datapoint.t1, state = datapoint.t2) + } + } +} + fn latest() -> impl IntoResponse { match DATAPOINT_BUFFER.get_latest() { None => Json(LatestResponse::none()), @@ -192,9 +214,54 @@ fn latest() -> impl IntoResponse { } fn index() -> impl IntoResponse { - page("Wallas 22GB Wifi Extension", html! { - p .intro { "Beta version of ESP32C3 based Wifi extension to the Wallas 361062 Control Panel for the DT/GB Heaters" } - p #graph { "Waiting for data ..." } - p #latest { "Waiting for latest reading ..." } + page("Wallas 22GB Wifi Extension", html! { + div .opaque { p .intro { "Beta version of ESP32C3 based Wifi extension to the Wallas 361062 Control Panel for the DT/GB Heaters" } } + div .opaque { p #graph { "Waiting for data ..." } } + div .opaque { p #latest { "Waiting for latest reading ..." } } + button #"button-start" .button { "Start heater" } + button #"button-stop" .button { "Stop heater" } + button #"button-ventilate" .button { "Start ventilator" } + button #"button-target" .button { "Set target temperature" } }) } + +async fn wait_for_ok () -> () { + let mut subscriber = serial::DOMAIN_MESSAGE_CHANNEL.subscriber().unwrap(); + loop { + let data = subscriber.next_message_pure().await; + if let serial::DomainMessage::AtOk = data { + return (); + } + } +} + +static CMDLOCK: Mutex = Mutex::new(()); + +async fn cmd(c: serial::DomainCommand) -> impl IntoResponse { + match CMDLOCK.try_lock() { + Err(_) => (StatusCode::LOCKED, ""), + _ => { + serial::DOMAIN_COMMAND_CHANNEL.publisher().unwrap().publish_immediate(c); + match with_timeout(Duration::from_secs(5), wait_for_ok()).await { + Ok(()) => (StatusCode::NO_CONTENT, ""), + Err(_) => (StatusCode::GATEWAY_TIMEOUT, "") + } + } + } +} + +async fn cmd_start() -> impl IntoResponse { + cmd(serial::DomainCommand::Start).await +} + +async fn cmd_stop() -> impl IntoResponse { + cmd(serial::DomainCommand::Stop).await +} + +async fn cmd_ventilate() -> impl IntoResponse { + cmd(serial::DomainCommand::Ventilate).await +} + +async fn cmd_temperature(t: i8) -> impl IntoResponse { + cmd(serial::DomainCommand::Temperature(t)).await +} diff --git a/src/main.rs b/src/main.rs index 30d877c..90119b8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,23 +2,21 @@ #![no_main] use esp_backtrace as _; -use esp_hal::prelude::*; use log::{info, error}; extern crate alloc; use heapless::String; use esp_hal::rng::Rng; -use esp_hal::timer::systimer::SystemTimer; +use esp_hal::timer::timg::TimerGroup; +use esp_hal::clock::CpuClock; /** * Embassy includes */ -use esp_hal_embassy::init as initialize_embassy; -use esp_hal::timer::systimer::Target; +//use esp_hal_embassy::init as initialize_embassy; +use esp_hal_embassy::main; use embassy_executor::Spawner; -// use embassy_time::{Duration, Timer}; -use esp_hal::timer::timg::TimerGroup; /** * Rng functionality @@ -104,8 +102,9 @@ async fn main_fallible( esp_println::logger::init_logger_from_env(); - let systimer = SystemTimer::new(peripherals.SYSTIMER).split::(); - initialize_embassy(systimer.alarm0); + // let systimer = SystemTimer::new(peripherals.SYSTIMER).split::(); + let tmg0 = TimerGroup::new(peripherals.TIMG0); +// initialize_embassy(tmg0.timer0); let rng = Rng::new(peripherals.RNG); @@ -113,13 +112,13 @@ async fn main_fallible( let password = String::<64>::try_from(WIFI_PASSWORD).map_err(|()| Error::ParseCredentials)?; - let stack = connect_to_wifi(spawner, TimerGroup::new(peripherals.TIMG0), rng, peripherals.WIFI, peripherals.RADIO_CLK, (ssid, password)).await.unwrap(); + let stack = connect_to_wifi(spawner, tmg0, rng, peripherals.WIFI, peripherals.RADIO_CLK, (ssid, password)).await.unwrap(); let _ = httpd_spawn(spawner, HTTPD_SOCKETS, stack); let _ = sntp_client_spawn(spawner, stack); - serial_spawn(spawner, peripherals.UART0.into(), peripherals.GPIO20.into(), peripherals.GPIO21.into()); + serial_spawn(spawner, peripherals.UART0.into()); let _ = database_spawn(spawner); diff --git a/src/random.rs b/src/random.rs index 53946f5..7accb61 100644 --- a/src/random.rs +++ b/src/random.rs @@ -7,7 +7,6 @@ //! Random numbers generator use rand_core::CryptoRng; -use rand_core::Error; use rand_core::RngCore; use esp_hal::rng::Rng; @@ -39,10 +38,12 @@ impl RngCore for RngWrapper { } } + /* fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { self.fill_bytes(dest); Ok(()) } + */ } impl CryptoRng for RngWrapper {} diff --git a/src/serial.rs b/src/serial.rs index 343da49..37022c5 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -2,7 +2,6 @@ use esp_hal::{ // clock::ClockControl, // peripherals::{Peripherals}, uart::{AnyUart, Uart, UartRx, UartTx, Config}, - gpio::AnyPin, Async, }; use log::{info, error, debug}; @@ -13,6 +12,7 @@ use embassy_sync::pubsub::{PubSubChannel, Subscriber}; use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_time::{Instant, Timer}; use heapless::Vec; +use nom::Parser; const BUFFER_SIZE: usize = 256; type BaseMessage = heapless::String; @@ -31,19 +31,20 @@ pub enum DomainCommand { Temperature(i8), } -type DomainMessageChannel = PubSubChannel; -pub type DomainMessageSubscriber<'a> = Subscriber<'a, CriticalSectionRawMutex, DomainMessage, 3, 1, 1>; +type DomainMessageChannel = PubSubChannel; +pub type DomainMessageSubscriber<'a> = Subscriber<'a, CriticalSectionRawMutex, DomainMessage, 3, 2, 1>; pub static DOMAIN_MESSAGE_CHANNEL: DomainMessageChannel = DomainMessageChannel::new(); type DomainCommandChannel = PubSubChannel; -static DOMAIN_COMMAND_CHANNEL: DomainCommandChannel = DomainCommandChannel::new(); +pub static DOMAIN_COMMAND_CHANNEL: DomainCommandChannel = DomainCommandChannel::new(); -pub fn serial_spawn(spawner: embassy_executor::Spawner, peri_uart: AnyUart, rx_pin: AnyPin, tx_pin: AnyPin) { +pub fn serial_spawn(spawner: embassy_executor::Spawner, peri_uart: AnyUart) { // Initialize and configure UART0 - let config = Config::default().rx_fifo_full_threshold(BUFFER_SIZE as u16); - let my_uart = Uart::new_with_config(peri_uart, config, rx_pin, tx_pin).unwrap().into_async(); + let config = Config::default().with_rx_fifo_full_threshold(BUFFER_SIZE as u16); + // removed rx_pin, tx_pin + let my_uart = Uart::new(peri_uart, config).unwrap().into_async(); // Split UART0 to create seperate Tx and Rx handles let (rx, tx) = my_uart.split(); @@ -75,10 +76,10 @@ async fn fakedata() { fn at_ok_parser (i: &str) -> Option<()> { - match nom::sequence::tuple(( + match ( nom::bytes::complete::tag("AT+OK"), nom::character::complete::crlf::<&str, nom::error::Error<&str>> - ))(i) { + ).parse(i) { Ok((_residual, (_, _))) => { Some(()) } @@ -89,7 +90,7 @@ fn at_ok_parser (i: &str) -> Option<()> { } fn at_wallas_parser (i: &str) -> Option<(i8, i8, i8, i8)> { - match nom::sequence::tuple(( + match ( nom::bytes::complete::tag("AT+WALLAS="), nom::character::complete::i8, nom::character::complete::char(','), @@ -99,7 +100,7 @@ fn at_wallas_parser (i: &str) -> Option<(i8, i8, i8, i8)> { nom::character::complete::char(','), nom::character::complete::i8, nom::character::complete::crlf::<&str, nom::error::Error<&str>> - ))(i) { + ).parse(i) { Ok((_residual, (_, t1, _, t2, _, t3, _, t4, _))) => { Some((t1, t2, t3, t4)) } @@ -128,6 +129,7 @@ async fn writer(mut tx: UartTx<'static, Async>) { let mut domain_subscriber = DOMAIN_COMMAND_CHANNEL.subscriber().unwrap(); loop { let cmd = domain_subscriber.next_message_pure().await; + info!("Writing message {:?} to serial port", &cmd); let _ = embedded_io_async::Write::write(&mut tx, match &cmd { DomainCommand::Start => b"START\r\n", @@ -135,7 +137,7 @@ async fn writer(mut tx: UartTx<'static, Async>) { DomainCommand::Ventilate => b"VENT\r\n", DomainCommand::Temperature(temp) => { let msg = alloc::format!("TEMP={}\r\n", temp); - wbuf.copy_from_slice(msg.as_bytes()); + wbuf[0..msg.len()].copy_from_slice(msg.as_bytes()); &wbuf[0..msg.len()] } } diff --git a/src/static/app.js b/src/static/app.js index 5b29082..d1f32e7 100644 --- a/src/static/app.js +++ b/src/static/app.js @@ -4,10 +4,39 @@ function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } -document.addEventListener("DOMContentLoaded", () => LoadCurrent(), false); -document.addEventListener("DOMContentLoaded", () => LoadGraph(), false); +document.addEventListener("DOMContentLoaded", () => main(), false); -async function LoadCurrent() { +async function main () { + + var pgraph = document.querySelector("#graph"); + if (pgraph) LoadGraph(pgraph); + + var platest = document.querySelector("#latest"); + if (platest) LoadLatest(platest); + + var bstart = document.querySelector("#button-start"); + if (bstart) bstart.addEventListener("click", + () => wallas_command("start", "Wallas Heater did not acknowledge the start command", "Wallas heater started")); + + var bstop = document.querySelector("#button-stop"); + if (bstop) bstop.addEventListener("click", + () => wallas_command("stop", "Wallas Heater did not acknowledge the stop command", "Wallas heater stopped")); + + var bventilate = document.querySelector("#button-ventilate"); + if (bventilate) bventilate.addEventListener("click", + () => wallas_command("ventilate", "Wallas Heater did not acknowledge the ventilate command", "Wallas heater is ventilating")); + + var btarget = document.querySelector("#button-target"); + if (btarget) { + btarget.addEventListener("click", set_temperature_dialog); + var target_label = document.querySelector("label#target-label"); + document.querySelector("input#target").addEventListener("input", (i) => { target_label.innerHTML = `Target temperature is ${i.target.value}°C`; }); + } + +} + + +async function LoadLatest(platest) { await sleep(500); while (true) { fetch("/api/v1/latest").then((response) => response.json()).then((json) => { @@ -15,7 +44,7 @@ async function LoadCurrent() { time = json.time; temperature = json.temperature; target = json.target; - document.getElementById("latest").innerHTML = `Temperature was ${temperature}°C at ${time} UTC, target temperature was ${target}°C`; + platest.innerHTML = `Temperature was ${temperature}°C at ${time} UTC, target temperature was ${target}°C`; } }) await sleep(10000); @@ -23,50 +52,136 @@ async function LoadCurrent() { }; const svg_xmlns = "http://www.w3.org/2000/svg"; -function appendSVGElement(parent, name, attributes) { +function appendSVGElement(parent, name, attributes, text = null) { var elem = document.createElementNS(svg_xmlns, name); for (var aname in attributes) { elem.setAttributeNS(null, aname, attributes[aname]); } - parent.appendChild(elem); - return elem; + if (text != null) { + textnode = document.createTextNode(text); + elem.appendChild(textnode); + } + return parent.appendChild(elem); } -async function LoadGraph() { +function appendElement(parent, name, attributes, text = null) { + var elem = document.createElement(name); + for (var aname in attributes) { + elem.setAttribute(aname, attributes[aname]); + } + if (text != null) { + textnode = document.createTextNode(text); + elem.appendChild(textnode); + } + return parent.appendChild(elem); +} + + + + +async function LoadGraph(pgraph) { await sleep(1000); while (true) { fetch("/api/v1/allreadings").then((response) => response.json()).then((json) => { if (json instanceof Array && json.length > 0) { + var width = pgraph.offsetWidth; + var height = pgraph.offsetHeight; + var temp_y = y => (25 - y) * height/35; + var temp_i = i => (99 - i) * (width - 48)/100; var graph = document.createDocumentFragment(); - var svg = appendSVGElement(graph, "svg", {"width": "100%", "height": "100%", "viewBox": "0 0 100 35"}); - var x = 99; + var svg = appendSVGElement(graph, "svg", {"width": "100%", "height": "100%", "viewBox": `0 0 ${width} ${height}`}); var target_points = []; var temperature_points = []; - for (var i = json.length - 1; i > 0; i--) { - var r = json[i]; - var temperature_y = 25 - r.temperature; - temperature_points.push(`${x},${temperature_y}`); - var target_y = 25 - r.target; - target_points.push(`${x},${target_y}`); - x = x - 1; + for (var i = 0; i < json.length && i < 99; i++) { + var r = json[json.length - i - 1]; + var x_coord = temp_i(i); + var temperature_y = temp_y(r.temperature); + temperature_points.push(`${x_coord},${temperature_y}`); + var target_y = temp_y(r.target); + target_points.push(`${x_coord},${target_y}`); } temperature_points_str = temperature_points.join(" "); target_points_str = target_points.join(" "); + // Horizontal lines // zero line - appendSVGElement(svg, "polyline", {"stroke-width": "0.1", "fill": "none", "stroke":"#000080", "stroke-linecap": "round", "stroke-dasharray": "5,2", "points": "1,25 99,25"}); + appendSVGElement(svg, "polyline", {"class": "grid grid-zero", "points": ""+temp_i(100)+","+temp_y(0)+" "+temp_i(0)+","+temp_y(0)}); // ten line - appendSVGElement(svg, "polyline", {"stroke-width": "0.05", "fill": "none", "stroke":"#000070", "stroke-linecap": "round", "stroke-dasharray": "5,2", "points": "1,15 99,15"}); + appendSVGElement(svg, "polyline", {"class": "grid", "points": ""+temp_i(100)+","+temp_y(10)+" "+temp_i(0)+","+temp_y(10)}); // twenty line - appendSVGElement(svg, "polyline", {"stroke-width": "0.05", "fill": "none", "stroke":"#000080", "stroke-linecap": "round", "stroke-dasharray": "5,2", "points": "1,5 99,5"}); + appendSVGElement(svg, "polyline", {"class": "grid", "points": ""+temp_i(100)+","+temp_y(20)+" "+temp_i(0)+","+temp_y(20)}); - target_polyline = appendSVGElement(svg, "polyline", {"stroke-width": "1", "fill": "none", "stroke": "#007900", "points": target_points_str}); - temperature_polyline = appendSVGElement(svg, "polyline", {"stroke-width": "1", "fill": "none", "stroke": "#0079d9", "points": temperature_points_str}); + // Vertical lines + appendSVGElement(svg, "polyline", {"class": "grid", "points": ""+temp_i(10)+","+temp_y(24)+" "+temp_i(10)+","+temp_y(-9)}); + appendSVGElement(svg, "polyline", {"class": "grid", "points": ""+temp_i(30)+","+temp_y(24)+" "+temp_i(30)+","+temp_y(-9)}); + appendSVGElement(svg, "polyline", {"class": "grid", "points": ""+temp_i(50)+","+temp_y(24)+" "+temp_i(50)+","+temp_y(-9)}); + appendSVGElement(svg, "polyline", {"class": "grid", "points": ""+temp_i(70)+","+temp_y(24)+" "+temp_i(70)+","+temp_y(-9)}); + appendSVGElement(svg, "polyline", {"class": "grid", "points": ""+temp_i(90)+","+temp_y(24)+" "+temp_i(90)+","+temp_y(-9)}); + // text + appendSVGElement(svg, "text", {"x": temp_i(0), "y": temp_y(0), "dx": 6, "dy": 5, "fill": "#000000"}, "0°C"); + appendSVGElement(svg, "text", {"x": temp_i(0), "y": temp_y(10), "dx": 6, "dy": 5, "fill": "#000000"}, "10°C"); + appendSVGElement(svg, "text", {"x": temp_i(0), "y": temp_y(20), "dx": 6, "dy": 5, "fill": "#000000"}, "20°C"); - document.getElementById("graph").replaceChildren(graph); + + target_polyline = appendSVGElement(svg, "polyline", {"class": "data target", "points": target_points_str}); + temperature_polyline = appendSVGElement(svg, "polyline", {"class": "data temperature", "points": temperature_points_str}); + //temperature_polyline.onmouseover = () => { console.log("yup"); }; + pgraph.replaceChildren(graph); } }) await sleep(10000); } } +async function set_temperature_dialog() { + var target = null; + await fetch("/api/v1/latest").then((response) => response.json()).then((json) => { + console.log(json); + if (json.target) { + if (json.target < 5) { + target = 5; + } else if (json.target > 25) { + target = 25; + } else { + target = json.target; + } + } + }); + var dialog = document.querySelector("dialog#set-target"); + dialog.showModal(); + var target_label = document.querySelector("label#target-label"); + var target_input = document.querySelector("input#target"); + console.log(target); + target_input.value = target; + target_label.innerHTML = `Target temperature is ${target}°C`; + target_input.addEventListener("input", (i) => { target_label.innerHTML = `Target temperature is ${i.target.value}°C`; }); + document.querySelector("span.cancel-x").addEventListener("click", () => { dialog.close(); }); + document.querySelector("button#set-target").addEventListener("click", (e) => { + e.preventDefault(); + dialog.close(); + var temperature = target_input.value; + wallas_command(`temperature/${temperature}`, "Wallas Heater did not accept the command", "Temperature target set to ${temperature}°C"); + }); +} + +async function wallas_command(cmd, no_atok, success) { + var dialog = document.querySelector("dialog#message"); + dialog.addEventListener('cancel', (event) => { event.preventDefault(); }); + dialog.innerHTML = "Sending command...."; + dialog.showModal(); + fetch(`/api/v1/cmd/${cmd}`).then((response) => { + if (response.status == 423) { + dialog.innerHTML = "Busy executing other command, try again later"; + } else if (response.status == 504) { + dialog.innerHTML = no_atok; + } else if (response.status == 204) { + dialog.innerHTML = success; + } else { + dialog.innerHTML = "Trouble communicating with Wallas Heater, try again later"; + } + setTimeout(() => { + dialog.close(); + }, 5000); + }); +} + diff --git a/src/static/styles.css b/src/static/styles.css index f9da5c7..56342d0 100644 --- a/src/static/styles.css +++ b/src/static/styles.css @@ -20,11 +20,14 @@ p.intro { padding: 0.2em; margin: 0.3em 10vw 0.3em 10vw; } +div.opaque { + background: rgba(213, 228, 246, 0.8); +} p#graph { border: 1px solid #B15C1B; padding: 0.2em; margin: 0.3em 15vw 0.3em 15vw; - height: 40vw; + height: 30vw; line-height: 100%; text-align: center; } @@ -32,6 +35,18 @@ p#latest { border: 1px solid #B15C1B; padding: 0.2em; margin: 0.3em 10vw 0.3em 10vw; + opacity: 1; +} +span.cancel-x { + font-weight: bold; + position: absolute; + top: 0.5em; + right: 0.5em; + cursor: default; + color: #9f0000; +} +span.cancel-x:hover { + color: #ff0000; } div#footer { position: absolute; @@ -41,8 +56,60 @@ div#footer { font-size: 70%; width: 100%; padding-bottom: 0.3em; + z-index: -1; +} +dialog#set-target { + padding: 1em; + width: 25em; +} +dialog#set-target form { + margin-top: 2em; +} +dialog#set-target button { + margin-top: 2em; +} +dialog.dialog-center { + position: fixed; + background: rgb(213, 228, 246); + z-index: 3; + width: 25em; + border: 2px solid #ef7606; } div#footer > a > img { padding-left: 3vw; padding-right: 3vw; } +button { + background-color: rgb(160, 171, 185); + border: 2px solid rgb(160, 171, 185); + padding: 15px; + border-radius: 5px; +} +button:hover { + border: 2px solid black; + background-color: #ef7606; +} +polyline.data { + stroke-width: 2px; + stroke-linecap: round; + stroke-linejoin: round; + fill: none; +} +polyline.temperature { + stroke: #0079d9; +} +polyline.target { + stroke: #B15C1B; + stroke-dasharray: 0.5,1; +} +polyline.grid { + stroke-width: 1; + fill: none; + stroke: rgb(160, 171, 185); + stroke-linecap: round; + stroke-dasharray: 5,7; +} +polyline.grid-zero { + stroke: rgb(107, 114, 123); + stroke-dasharray: 5,3; +} diff --git a/src/wifi.rs b/src/wifi.rs index b0daea7..77f2edc 100644 --- a/src/wifi.rs +++ b/src/wifi.rs @@ -45,7 +45,7 @@ use esp_hal::peripherals::TIMG0; use esp_hal::peripherals::WIFI; use esp_hal::rng::Rng; use esp_hal::timer::timg::TimerGroup; -use esp_hal::Blocking; +// use esp_hal::Blocking; use heapless::String; @@ -70,7 +70,7 @@ pub static STOP_WIFI_SIGNAL: Signal = Signal::new() /// Connect to WiFi pub async fn connect( spawner: Spawner, - timg0: TimerGroup<'static, TIMG0, Blocking>, + timg0: TimerGroup, rng: Rng, wifi: WIFI, radio_clock_control: RADIO_CLK,