feat: Add hyperdeck command
This commit is contained in:
parent
ee375e34a8
commit
f9cac35a29
|
@ -23,10 +23,6 @@ name = "accesskit"
|
|||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "74a4b14f3d99c1255dcba8f45621ab1a2e7540a0009652d33989005a4d0bfc6b"
|
||||
dependencies = [
|
||||
"enumn",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "accesskit_consumer"
|
||||
|
@ -117,7 +113,6 @@ dependencies = [
|
|||
"cfg-if",
|
||||
"getrandom",
|
||||
"once_cell",
|
||||
"serde",
|
||||
"version_check",
|
||||
"zerocopy",
|
||||
]
|
||||
|
@ -131,6 +126,27 @@ dependencies = [
|
|||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "alloc-no-stdlib"
|
||||
version = "2.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3"
|
||||
|
||||
[[package]]
|
||||
name = "alloc-stdlib"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece"
|
||||
dependencies = [
|
||||
"alloc-no-stdlib",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "allocator-api2"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5"
|
||||
|
||||
[[package]]
|
||||
name = "android-activity"
|
||||
version = "0.5.2"
|
||||
|
@ -202,6 +218,22 @@ dependencies = [
|
|||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-compression"
|
||||
version = "0.4.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c90a406b4495d129f00461241616194cb8a032c8d1c53c657f0961d5f8e0498"
|
||||
dependencies = [
|
||||
"brotli",
|
||||
"flate2",
|
||||
"futures-core",
|
||||
"memchr",
|
||||
"pin-project-lite",
|
||||
"tokio",
|
||||
"zstd",
|
||||
"zstd-safe",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-executor"
|
||||
version = "1.11.0"
|
||||
|
@ -415,6 +447,71 @@ version = "1.2.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80"
|
||||
|
||||
[[package]]
|
||||
name = "axum"
|
||||
version = "0.6.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"axum-core",
|
||||
"axum-macros",
|
||||
"base64",
|
||||
"bitflags 1.3.2",
|
||||
"bytes",
|
||||
"futures-util",
|
||||
"http 0.2.12",
|
||||
"http-body",
|
||||
"hyper",
|
||||
"itoa",
|
||||
"matchit",
|
||||
"memchr",
|
||||
"mime",
|
||||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
"rustversion",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_path_to_error",
|
||||
"serde_urlencoded",
|
||||
"sha1",
|
||||
"sync_wrapper",
|
||||
"tokio",
|
||||
"tokio-tungstenite 0.20.1",
|
||||
"tower",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "axum-core"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"bytes",
|
||||
"futures-util",
|
||||
"http 0.2.12",
|
||||
"http-body",
|
||||
"mime",
|
||||
"rustversion",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "axum-macros"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdca6a10ecad987bda04e95606ef85a5417dcaac1a78455242d72e031e2b6b62"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.60",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.71"
|
||||
|
@ -447,9 +544,6 @@ name = "bitflags"
|
|||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block"
|
||||
|
@ -527,6 +621,27 @@ dependencies = [
|
|||
"piper",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "brotli"
|
||||
version = "6.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "74f7971dbd9326d58187408ab83117d8ac1bb9c17b085fdacd1cf2f598719b6b"
|
||||
dependencies = [
|
||||
"alloc-no-stdlib",
|
||||
"alloc-stdlib",
|
||||
"brotli-decompressor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "brotli-decompressor"
|
||||
version = "4.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6221fe77a248b9117d431ad93761222e1cf8ff282d9d1d5d9f53d6299a1cf76"
|
||||
dependencies = [
|
||||
"alloc-no-stdlib",
|
||||
"alloc-stdlib",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.16.0"
|
||||
|
@ -827,27 +942,6 @@ dependencies = [
|
|||
"crypto-common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "directories-next"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "339ee130d97a610ea5a5872d2bbb130fdf68884ff09d3028b81bec8a1ac23bbc"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"dirs-sys-next",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs-sys-next"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"redox_users",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dispatch"
|
||||
version = "0.2.0"
|
||||
|
@ -885,7 +979,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "20930a432bbd57a6d55e07976089708d4893f3d556cf42a0d79e9e321fa73b10"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -896,7 +989,6 @@ checksum = "020e2ccef6bbcec71dbc542f7eed64a5846fc3076727f5746da8fd307c91bab2"
|
|||
dependencies = [
|
||||
"bytemuck",
|
||||
"cocoa",
|
||||
"directories-next",
|
||||
"document-features",
|
||||
"egui",
|
||||
"egui-winit",
|
||||
|
@ -912,8 +1004,6 @@ dependencies = [
|
|||
"percent-encoding",
|
||||
"raw-window-handle 0.5.2",
|
||||
"raw-window-handle 0.6.1",
|
||||
"ron",
|
||||
"serde",
|
||||
"static_assertions",
|
||||
"thiserror",
|
||||
"wasm-bindgen",
|
||||
|
@ -935,8 +1025,6 @@ dependencies = [
|
|||
"epaint",
|
||||
"log",
|
||||
"nohash-hasher",
|
||||
"ron",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -950,7 +1038,6 @@ dependencies = [
|
|||
"egui",
|
||||
"log",
|
||||
"raw-window-handle 0.6.1",
|
||||
"serde",
|
||||
"smithay-clipboard",
|
||||
"web-time",
|
||||
"webbrowser",
|
||||
|
@ -979,7 +1066,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "e4c3a552cfca14630702449d35f41c84a0d15963273771c6059175a803620f3f"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1003,17 +1089,6 @@ dependencies = [
|
|||
"syn 2.0.60",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "enumn"
|
||||
version = "0.1.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6fd000fd6988e73bbe993ea3db9b1aa64906ab88766d654973924340c8cddb42"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.60",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "env_logger"
|
||||
version = "0.10.2"
|
||||
|
@ -1041,7 +1116,6 @@ dependencies = [
|
|||
"log",
|
||||
"nohash-hasher",
|
||||
"parking_lot 0.12.2",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1125,6 +1199,21 @@ dependencies = [
|
|||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ewebsock"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6177769715c6ec5a324acee995183b22721ea23c58e49af14a828eadec85d120"
|
||||
dependencies = [
|
||||
"document-features",
|
||||
"js-sys",
|
||||
"log",
|
||||
"tungstenite 0.21.0",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "eyre"
|
||||
version = "0.6.12"
|
||||
|
@ -1453,11 +1542,37 @@ dependencies = [
|
|||
"gl_generator",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"allocator-api2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hdrhistogram"
|
||||
version = "7.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "765c9198f173dd59ce26ff9f95ef0aafd0a0fe01fb9d72841bc5066a4c06511d"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
|
@ -1486,6 +1601,17 @@ version = "0.2.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a80870ee775a6b862265eb04a8d61d1b1ef8e4c423154a52ba6a1e3ff24836c"
|
||||
|
||||
[[package]]
|
||||
name = "http"
|
||||
version = "0.2.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"fnv",
|
||||
"itoa",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "http"
|
||||
version = "1.1.0"
|
||||
|
@ -1497,32 +1623,84 @@ dependencies = [
|
|||
"itoa",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "http-body"
|
||||
version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"http 0.2.12",
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "http-range-header"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "add0ab9360ddbd88cfeb3bd9574a1d85cfdfa14db10b3e21d3700dbc4328758f"
|
||||
|
||||
[[package]]
|
||||
name = "httparse"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
|
||||
|
||||
[[package]]
|
||||
name = "httpdate"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
|
||||
|
||||
[[package]]
|
||||
name = "humantime"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
|
||||
|
||||
[[package]]
|
||||
name = "hyper"
|
||||
version = "0.14.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"http 0.2.12",
|
||||
"http-body",
|
||||
"httparse",
|
||||
"httpdate",
|
||||
"itoa",
|
||||
"pin-project-lite",
|
||||
"socket2 0.5.7",
|
||||
"tokio",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
"want",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hyperdeck-monitor"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"axum",
|
||||
"color-eyre",
|
||||
"futures",
|
||||
"futures-util",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tokio",
|
||||
"tokio-tungstenite",
|
||||
"tokio-stream",
|
||||
"tokio-tungstenite 0.21.0",
|
||||
"tokio-util",
|
||||
"tower",
|
||||
"tower-http",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
"url",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1532,9 +1710,11 @@ dependencies = [
|
|||
"eframe",
|
||||
"egui",
|
||||
"env_logger",
|
||||
"ewebsock",
|
||||
"hrtime",
|
||||
"log",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"wasm-bindgen-futures",
|
||||
"wasm-timer",
|
||||
]
|
||||
|
@ -1579,6 +1759,16 @@ version = "0.3.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683"
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"hashbrown 0.12.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.2.6"
|
||||
|
@ -1586,7 +1776,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown",
|
||||
"hashbrown 0.14.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1609,6 +1799,16 @@ dependencies = [
|
|||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iri-string"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f5f6c2df22c009ac44f6f1499308e7a3ac7ba42cd2378475cc691510e1eef1b"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "is-terminal"
|
||||
version = "0.4.12"
|
||||
|
@ -1705,16 +1905,6 @@ dependencies = [
|
|||
"redox_syscall 0.4.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libredox"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.3.8"
|
||||
|
@ -1767,6 +1957,12 @@ dependencies = [
|
|||
"regex-automata 0.1.10",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "matchit"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.2"
|
||||
|
@ -1800,6 +1996,22 @@ dependencies = [
|
|||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mime"
|
||||
version = "0.3.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
|
||||
|
||||
[[package]]
|
||||
name = "mime_guess"
|
||||
version = "2.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef"
|
||||
dependencies = [
|
||||
"mime",
|
||||
"unicase",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.7.2"
|
||||
|
@ -2047,7 +2259,7 @@ version = "0.3.47"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "52f0d54bde9774d3a51dcf281a5def240c71996bc6ca05d2c847ec8b2b216166"
|
||||
dependencies = [
|
||||
"libredox 0.0.2",
|
||||
"libredox",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2147,6 +2359,26 @@ version = "2.3.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
|
||||
|
||||
[[package]]
|
||||
name = "pin-project"
|
||||
version = "1.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3"
|
||||
dependencies = [
|
||||
"pin-project-internal",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-internal"
|
||||
version = "1.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.60",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.14"
|
||||
|
@ -2350,17 +2582,6 @@ dependencies = [
|
|||
"bitflags 2.5.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_users"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"libredox 0.1.3",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.10.4"
|
||||
|
@ -2405,18 +2626,6 @@ version = "0.8.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56"
|
||||
|
||||
[[package]]
|
||||
name = "ron"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"bitflags 2.5.0",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.23"
|
||||
|
@ -2450,6 +2659,12 @@ dependencies = [
|
|||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.17"
|
||||
|
@ -2499,15 +2714,25 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.116"
|
||||
version = "1.0.117"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813"
|
||||
checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_path_to_error"
|
||||
version = "0.1.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_repr"
|
||||
version = "0.1.19"
|
||||
|
@ -2519,6 +2744,18 @@ dependencies = [
|
|||
"syn 2.0.60",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_urlencoded"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
|
||||
dependencies = [
|
||||
"form_urlencoded",
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha1"
|
||||
version = "0.10.6"
|
||||
|
@ -2671,6 +2908,12 @@ dependencies = [
|
|||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sync_wrapper"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.10.1"
|
||||
|
@ -2767,6 +3010,30 @@ dependencies = [
|
|||
"syn 2.0.60",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-stream"
|
||||
version = "0.1.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"pin-project-lite",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-tungstenite"
|
||||
version = "0.20.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c"
|
||||
dependencies = [
|
||||
"futures-util",
|
||||
"log",
|
||||
"tokio",
|
||||
"tungstenite 0.20.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-tungstenite"
|
||||
version = "0.21.0"
|
||||
|
@ -2776,19 +3043,23 @@ dependencies = [
|
|||
"futures-util",
|
||||
"log",
|
||||
"tokio",
|
||||
"tungstenite",
|
||||
"tungstenite 0.21.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-util"
|
||||
version = "0.7.10"
|
||||
version = "0.7.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15"
|
||||
checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-core",
|
||||
"futures-io",
|
||||
"futures-sink",
|
||||
"futures-util",
|
||||
"hashbrown 0.14.5",
|
||||
"pin-project-lite",
|
||||
"slab",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
|
@ -2804,7 +3075,7 @@ version = "0.19.15"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"indexmap 2.2.6",
|
||||
"toml_datetime",
|
||||
"winnow",
|
||||
]
|
||||
|
@ -2815,17 +3086,81 @@ version = "0.21.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"indexmap 2.2.6",
|
||||
"toml_datetime",
|
||||
"winnow",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tower"
|
||||
version = "0.4.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"hdrhistogram",
|
||||
"indexmap 1.9.3",
|
||||
"pin-project",
|
||||
"pin-project-lite",
|
||||
"rand",
|
||||
"slab",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tower-http"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "61c5bb1d698276a2443e5ecfabc1008bf15a36c12e6a7176e7bf089ea9131140"
|
||||
dependencies = [
|
||||
"async-compression",
|
||||
"base64",
|
||||
"bitflags 2.5.0",
|
||||
"bytes",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"http 0.2.12",
|
||||
"http-body",
|
||||
"http-range-header",
|
||||
"httpdate",
|
||||
"iri-string",
|
||||
"mime",
|
||||
"mime_guess",
|
||||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
"tower",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tower-layer"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0"
|
||||
|
||||
[[package]]
|
||||
name = "tower-service"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
|
||||
|
||||
[[package]]
|
||||
name = "tracing"
|
||||
version = "0.1.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
|
||||
dependencies = [
|
||||
"log",
|
||||
"pin-project-lite",
|
||||
"tracing-attributes",
|
||||
"tracing-core",
|
||||
|
@ -2891,12 +3226,37 @@ dependencies = [
|
|||
"tracing-log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "try-lock"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
|
||||
|
||||
[[package]]
|
||||
name = "ttf-parser"
|
||||
version = "0.20.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "17f77d76d837a7830fe1d4f12b7b4ba4192c1888001c7164257e4bc6d21d96b4"
|
||||
|
||||
[[package]]
|
||||
name = "tungstenite"
|
||||
version = "0.20.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e3dac10fd62eaf6617d3a904ae222845979aec67c615d1c842b4002c7666fb9"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"bytes",
|
||||
"data-encoding",
|
||||
"http 0.2.12",
|
||||
"httparse",
|
||||
"log",
|
||||
"rand",
|
||||
"sha1",
|
||||
"thiserror",
|
||||
"url",
|
||||
"utf-8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tungstenite"
|
||||
version = "0.21.0"
|
||||
|
@ -2906,7 +3266,7 @@ dependencies = [
|
|||
"byteorder",
|
||||
"bytes",
|
||||
"data-encoding",
|
||||
"http",
|
||||
"http 1.1.0",
|
||||
"httparse",
|
||||
"log",
|
||||
"rand",
|
||||
|
@ -2933,6 +3293,15 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicase"
|
||||
version = "2.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89"
|
||||
dependencies = [
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-bidi"
|
||||
version = "0.3.15"
|
||||
|
@ -2977,6 +3346,16 @@ version = "0.7.6"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
|
||||
|
||||
[[package]]
|
||||
name = "uuid"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "valuable"
|
||||
version = "0.1.0"
|
||||
|
@ -3005,6 +3384,15 @@ dependencies = [
|
|||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "want"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e"
|
||||
dependencies = [
|
||||
"try-lock",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
|
@ -3723,6 +4111,34 @@ dependencies = [
|
|||
"syn 2.0.60",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zstd"
|
||||
version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2d789b1514203a1120ad2429eae43a7bd32b90976a7bb8a05f7ec02fa88cc23a"
|
||||
dependencies = [
|
||||
"zstd-safe",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zstd-safe"
|
||||
version = "7.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1cd99b45c6bc03a018c8b8a86025678c87e55526064e38f9df301989dce7ec0a"
|
||||
dependencies = [
|
||||
"zstd-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zstd-sys"
|
||||
version = "2.0.10+zstd.1.5.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c253a4914af5bafc8fa8c86ee400827e83cf6ec01195ec1f1ed8441bf00d65aa"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zvariant"
|
||||
version = "3.15.2"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
[workspace]
|
||||
members = [
|
||||
"monitor",
|
||||
"frontend"
|
||||
"frontend",
|
||||
]
|
||||
resolver = "2"
|
||||
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
# Copied during build (🤮)
|
||||
src/websocket.rs
|
||||
|
||||
# trunk output folder
|
||||
dist
|
||||
|
||||
|
|
|
@ -9,12 +9,13 @@ eframe = { version = "0.27.0", default-features = false, features = [
|
|||
"accesskit", # Make egui comptaible with screen readers.
|
||||
"default_fonts", # Embed the default egui fonts.
|
||||
"glow", # Use the glow rendering backend. Alternative: "wgpu".
|
||||
"persistence", # Enable restoring app state when restarting the app.
|
||||
] }
|
||||
log = "0.4"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
hrtime = "0.2.0"
|
||||
wasm-timer = "0.2.5"
|
||||
ewebsock = "0.5.0"
|
||||
serde_json = "1.0.117"
|
||||
|
||||
|
||||
# native:
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
fn main() {
|
||||
// Sorry, I know it's horrible but I don't have the spoons to make it right.
|
||||
const API_DEFINITION_FILE: &str = "../monitor/src/api/message.rs";
|
||||
println!("cargo:rerun-if-changed={API_DEFINITION_FILE}");
|
||||
std::fs::copy(API_DEFINITION_FILE, "./src/websocket.rs")
|
||||
.expect("Failed to copy API definition");
|
||||
}
|
|
@ -1,35 +1,38 @@
|
|||
use std::{
|
||||
collections::VecDeque,
|
||||
fmt::Display,
|
||||
mem,
|
||||
net::{IpAddr, Ipv4Addr},
|
||||
};
|
||||
|
||||
use egui::{Color32, RichText, Sense, Stroke, Vec2};
|
||||
use egui::{Button, Color32, RichText, Sense, Stroke, Vec2};
|
||||
use ewebsock::{Options, WsReceiver, WsSender};
|
||||
use wasm_timer::Instant;
|
||||
|
||||
#[derive(serde::Deserialize, serde::Serialize)]
|
||||
#[serde(default)]
|
||||
use crate::websocket::{AddHyperdeckRequest, ClientRequest};
|
||||
|
||||
pub struct HyperdeckMonitorApp {
|
||||
#[serde(skip)]
|
||||
blink: bool,
|
||||
#[serde(skip)]
|
||||
last_blink_change: Instant,
|
||||
#[serde(skip)]
|
||||
new_hyperdeck_ip: String,
|
||||
|
||||
#[serde(skip)]
|
||||
new_hyperdeck_name: String,
|
||||
|
||||
#[serde(skip)]
|
||||
new_hyperdeck_port: String,
|
||||
hyperdecks: Vec<Hyperdeck>,
|
||||
websocket_message_queue: VecDeque<ClientRequest>,
|
||||
ws_sender: WsSender,
|
||||
ws_receiver: WsReceiver,
|
||||
}
|
||||
|
||||
impl Default for HyperdeckMonitorApp {
|
||||
fn default() -> Self {
|
||||
let (ws_sender, ws_receiver) =
|
||||
ewebsock::connect("ws://127.0.0.1:9681/ws", Options::default()).unwrap();
|
||||
Self {
|
||||
blink: false,
|
||||
last_blink_change: Instant::now(),
|
||||
new_hyperdeck_ip: "".to_owned(),
|
||||
new_hyperdeck_name: "".to_owned(),
|
||||
new_hyperdeck_port: 9993.to_string(),
|
||||
hyperdecks: vec![
|
||||
Hyperdeck {
|
||||
name: "Test Hyperdeck 1".to_string(),
|
||||
|
@ -52,27 +55,20 @@ impl Default for HyperdeckMonitorApp {
|
|||
}],
|
||||
},
|
||||
],
|
||||
websocket_message_queue: VecDeque::new(),
|
||||
ws_sender,
|
||||
ws_receiver,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl HyperdeckMonitorApp {
|
||||
pub fn new(cc: &eframe::CreationContext<'_>) -> Self {
|
||||
// Load previous app state (if any)
|
||||
if let Some(storage) = cc.storage {
|
||||
return eframe::get_value(storage, eframe::APP_KEY).unwrap_or_default();
|
||||
}
|
||||
|
||||
Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
impl eframe::App for HyperdeckMonitorApp {
|
||||
fn save(&mut self, storage: &mut dyn eframe::Storage) {
|
||||
eframe::set_value(storage, eframe::APP_KEY, self);
|
||||
}
|
||||
|
||||
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
|
||||
if let Some(message) = self.websocket_message_queue.pop_front() {
|
||||
self.ws_sender.send(ewebsock::WsMessage::Text(
|
||||
serde_json::to_string(&message).expect("Could not serialize message"),
|
||||
));
|
||||
}
|
||||
egui::TopBottomPanel::top("top_panel").show(ctx, |ui| {
|
||||
egui::menu::bar(ui, |ui| {
|
||||
egui::widgets::global_dark_light_mode_buttons(ui);
|
||||
|
@ -80,7 +76,13 @@ impl eframe::App for HyperdeckMonitorApp {
|
|||
});
|
||||
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
add_hyperdeck_panel(ui, &mut self.new_hyperdeck_ip, &mut self.new_hyperdeck_name);
|
||||
add_hyperdeck_panel(
|
||||
ui,
|
||||
&mut self.new_hyperdeck_name,
|
||||
&mut self.new_hyperdeck_ip,
|
||||
&mut self.new_hyperdeck_port,
|
||||
&mut self.websocket_message_queue,
|
||||
);
|
||||
ui.separator();
|
||||
|
||||
ui.vertical(|ui| {
|
||||
|
@ -105,8 +107,10 @@ impl eframe::App for HyperdeckMonitorApp {
|
|||
|
||||
fn add_hyperdeck_panel(
|
||||
ui: &mut egui::Ui,
|
||||
new_hyperdeck_ip: &mut String,
|
||||
new_hyperdeck_name: &mut String,
|
||||
new_hyperdeck_ip: &mut String,
|
||||
new_hyperdeck_port: &mut String,
|
||||
message_queue: &mut VecDeque<ClientRequest>,
|
||||
) {
|
||||
ui.heading("Add hyperdeck");
|
||||
ui.horizontal(|ui| {
|
||||
|
@ -114,8 +118,19 @@ fn add_hyperdeck_panel(
|
|||
ui.text_edit_singleline(new_hyperdeck_name);
|
||||
ui.label("IP");
|
||||
ui.text_edit_singleline(new_hyperdeck_ip);
|
||||
if ui.button("Add").clicked() {
|
||||
// Do Something
|
||||
ui.label("Port");
|
||||
ui.text_edit_singleline(new_hyperdeck_port);
|
||||
let button_enabled = new_hyperdeck_ip.parse::<IpAddr>().is_ok()
|
||||
&& !new_hyperdeck_name.is_empty()
|
||||
&& new_hyperdeck_port.parse::<u16>().is_ok();
|
||||
if ui.add_enabled(button_enabled, Button::new("Add")).clicked() {
|
||||
message_queue.push_back(ClientRequest::AddHyperdeck(AddHyperdeckRequest {
|
||||
name: mem::take(new_hyperdeck_name),
|
||||
ip: mem::take(new_hyperdeck_ip),
|
||||
port: mem::replace(new_hyperdeck_port, "9993".to_string())
|
||||
.parse::<u16>()
|
||||
.unwrap(),
|
||||
}));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,2 +1,4 @@
|
|||
mod app;
|
||||
mod websocket;
|
||||
|
||||
pub use app::HyperdeckMonitorApp;
|
||||
|
|
|
@ -11,7 +11,7 @@ fn main() -> eframe::Result<()> {
|
|||
eframe::run_native(
|
||||
"eframe template",
|
||||
native_options,
|
||||
Box::new(|cc| Box::new(hyperdeck_monitor_gui::HyperdeckMonitorApp::new(cc))),
|
||||
Box::new(|_| Box::new(hyperdeck_monitor_gui::HyperdeckMonitorApp::default())),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ fn main() {
|
|||
.start(
|
||||
"the_canvas_id", // Where to draw to.
|
||||
web_options,
|
||||
Box::new(|cc| Box::new(hyperdeck_monitor_gui::HyperdeckMonitorApp::new(cc))),
|
||||
Box::new(|_| Box::new(hyperdeck_monitor_gui::HyperdeckMonitorApp::default())),
|
||||
)
|
||||
.await
|
||||
.expect("failed to start eframe");
|
||||
|
|
|
@ -6,13 +6,19 @@ edition = "2021"
|
|||
default-run = "hyperdeck-monitor"
|
||||
|
||||
[dependencies]
|
||||
axum = { version = "0.6.10", features = ["macros", "ws"] }
|
||||
color-eyre = "0.6.3"
|
||||
futures = { version = "0.3.25" }
|
||||
futures-util = "0.3.30"
|
||||
serde = { version = "1.0.199", features = ["derive"] }
|
||||
serde_json = "1.0.116"
|
||||
tokio = { version = "1.37.0", features = ["full"] }
|
||||
tokio-stream = { version = "0.1.12", features = ["sync"] }
|
||||
tokio-tungstenite = "0.21.0"
|
||||
tokio-util = "0.7.10"
|
||||
tokio-util = { version = "0.7.11", features = ["full"] }
|
||||
tower = { version = "0.4.13", features = ["full"] }
|
||||
tower-http = { version = "0.4.0", features = ["full"] }
|
||||
tracing = "0.1.40"
|
||||
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
|
||||
url = "2.5.0"
|
||||
uuid = { version = "1.2.2", features = ["serde", "v4"] }
|
||||
|
|
|
@ -1,10 +1,35 @@
|
|||
import { Hyperdeck, Commands } from 'hyperdeck-connection';
|
||||
import WebSocket from 'ws';
|
||||
|
||||
interface WrappedHyperdeck {
|
||||
ip: String,
|
||||
port: number,
|
||||
hyperdeck: Hyperdeck
|
||||
}
|
||||
|
||||
const hyperdecks: Map<string, WrappedHyperdeck> = new Map()
|
||||
|
||||
enum WebSocketMessageType {
|
||||
AddHyperdeck = "add_hyperdeck"
|
||||
}
|
||||
|
||||
type WebSocketMessage = {
|
||||
type: WebSocketMessageType.AddHyperdeck,
|
||||
id: string,
|
||||
ip: string,
|
||||
port: number
|
||||
}
|
||||
|
||||
const wss = new WebSocket.Server({ port: 7867 });
|
||||
|
||||
wss.on('connection', function connection(ws) {
|
||||
ws.on('message', function message(data) {
|
||||
console.log('received: %s', data);
|
||||
try {
|
||||
const message = JSON.parse(data.toString()) as Partial<WebSocketMessage>;
|
||||
handle_message(message)
|
||||
} catch (_err) {
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
ws.send(JSON.stringify({
|
||||
|
@ -12,3 +37,55 @@ wss.on('connection', function connection(ws) {
|
|||
message: "Hello"
|
||||
}));
|
||||
});
|
||||
|
||||
function exhaustiveMatch(_never: never) {
|
||||
return;
|
||||
}
|
||||
|
||||
function handle_message(message: Partial<WebSocketMessage>) {
|
||||
console.log(JSON.stringify(message));
|
||||
if (message.type === undefined) return;
|
||||
|
||||
switch (message.type) {
|
||||
case WebSocketMessageType.AddHyperdeck:
|
||||
if (message.id === undefined) return;
|
||||
if (message.ip === undefined) return;
|
||||
if (message.port === undefined) return;
|
||||
if (isNaN(message.port)) return;
|
||||
if (message.port <= 0) return;
|
||||
|
||||
console.log("Adding hyperdeck");
|
||||
|
||||
const newHyperdeck = new Hyperdeck()
|
||||
|
||||
// hyperdecks.set(message.id, {
|
||||
// ip: message.ip,
|
||||
// port: message.port,
|
||||
// hyperdeck: newHyperdeck
|
||||
// });
|
||||
|
||||
newHyperdeck.on('connected', (info) => {
|
||||
console.log(JSON.stringify(info))
|
||||
|
||||
newHyperdeck.sendCommand(new Commands.TransportInfoCommand()).then((transportInfo) => {
|
||||
console.log(JSON.stringify(transportInfo))
|
||||
})
|
||||
})
|
||||
|
||||
newHyperdeck.on('notify.slot', function (state) {
|
||||
console.log(JSON.stringify(state)) // catch the slot state change.
|
||||
})
|
||||
newHyperdeck.on('notify.transport', function (state) {
|
||||
console.log(JSON.stringify(state)) // catch the transport state change.
|
||||
})
|
||||
newHyperdeck.on('error', (err) => {
|
||||
console.log('Hyperdeck error', JSON.stringify(err))
|
||||
})
|
||||
|
||||
newHyperdeck.connect(message.ip, message.port)
|
||||
|
||||
break;
|
||||
default:
|
||||
exhaustiveMatch(message.type)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,172 @@
|
|||
use axum::extract::ws::Message;
|
||||
use axum::extract::{State, WebSocketUpgrade};
|
||||
use axum::response::Html;
|
||||
use axum::{
|
||||
body::Bytes,
|
||||
extract::Path,
|
||||
http::{header, HeaderValue, Method},
|
||||
response::IntoResponse,
|
||||
routing::get,
|
||||
Router,
|
||||
};
|
||||
use message::{ClientRequest, HyperdeckMonitorState, ServerEvent};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
net::{Ipv4Addr, SocketAddr},
|
||||
sync::Arc,
|
||||
time::Duration,
|
||||
};
|
||||
use tokio::sync::{Mutex, RwLock};
|
||||
use tower::ServiceBuilder;
|
||||
use tower_http::timeout::TimeoutLayer;
|
||||
use tower_http::ServiceBuilderExt;
|
||||
use tower_http::{
|
||||
cors::{Any, CorsLayer},
|
||||
trace::{DefaultMakeSpan, DefaultOnResponse, TraceLayer},
|
||||
LatencyUnit,
|
||||
};
|
||||
use tracing::info;
|
||||
use uuid::Uuid;
|
||||
|
||||
pub mod message;
|
||||
mod ws;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Client {
|
||||
pub sender: Option<tokio::sync::broadcast::Sender<Message>>,
|
||||
}
|
||||
|
||||
type Clients = Arc<Mutex<HashMap<Uuid, Client>>>;
|
||||
|
||||
pub async fn initialize_api(
|
||||
mut state_rx: tokio::sync::broadcast::Receiver<HyperdeckMonitorState>,
|
||||
client_request_tx: tokio::sync::mpsc::UnboundedSender<ClientRequest>,
|
||||
) {
|
||||
info!("Initializing API");
|
||||
|
||||
let clients: Clients = Default::default();
|
||||
|
||||
let state = Arc::new(RwLock::new(state_rx.recv().await.unwrap()));
|
||||
|
||||
let state_clients = clients.clone();
|
||||
let state_loop = state.clone();
|
||||
tokio::spawn(async move {
|
||||
loop {
|
||||
if let Ok(hyperdeck_monitor_state) = state_rx.recv().await {
|
||||
let mut state = state_loop.write().await;
|
||||
*state = hyperdeck_monitor_state.clone();
|
||||
|
||||
let clients = state_clients.lock().await;
|
||||
let state_json = serde_json::to_string(&ServerEvent::HyperdeckMonitorState(
|
||||
hyperdeck_monitor_state.into(),
|
||||
))
|
||||
.unwrap();
|
||||
for (_, client) in clients.iter() {
|
||||
if let Some(sender) = &client.sender {
|
||||
let message: Message = Message::Text(state_json.clone());
|
||||
let _ = sender.send(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let app_state = AppState {
|
||||
state,
|
||||
client_request_tx,
|
||||
clients,
|
||||
port: 9681,
|
||||
};
|
||||
|
||||
let addr = SocketAddr::from((Ipv4Addr::UNSPECIFIED, app_state.port));
|
||||
info!("Listening on {}", addr);
|
||||
// TODO: This could fail, need to figure out how to get a result from this
|
||||
let _ = axum::Server::bind(&addr)
|
||||
.serve(app(app_state).into_make_service())
|
||||
.await;
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct AppState {
|
||||
state: Arc<RwLock<HyperdeckMonitorState>>,
|
||||
client_request_tx: tokio::sync::mpsc::UnboundedSender<ClientRequest>,
|
||||
clients: Clients,
|
||||
port: u16,
|
||||
}
|
||||
|
||||
fn app(state: AppState) -> Router {
|
||||
let sensitive_headers: Arc<[_]> = vec![header::AUTHORIZATION, header::COOKIE].into();
|
||||
let middleware = ServiceBuilder::new()
|
||||
// Mark the `Authorization` and `Cookie` headers as sensitive so it doesn't show in logs
|
||||
.sensitive_request_headers(sensitive_headers.clone())
|
||||
// Add high level tracing/logging to all requests
|
||||
.layer(
|
||||
TraceLayer::new_for_http()
|
||||
.on_body_chunk(|chunk: &Bytes, latency: Duration, _: &tracing::Span| {
|
||||
tracing::trace!(size_bytes = chunk.len(), latency = ?latency, "sending body chunk")
|
||||
})
|
||||
.make_span_with(DefaultMakeSpan::new().include_headers(true))
|
||||
.on_response(DefaultOnResponse::new().include_headers(true).latency_unit(LatencyUnit::Micros)),
|
||||
)
|
||||
.sensitive_response_headers(sensitive_headers)
|
||||
// Set a timeout
|
||||
.layer(TimeoutLayer::new(Duration::from_secs(10)))
|
||||
// Box the response body so it implements `Default` which is required by axum
|
||||
.map_response_body(axum::body::boxed)
|
||||
// Compress responses
|
||||
.compression()
|
||||
// Set a `Content-Type` if there isn't one already.
|
||||
.insert_response_header_if_not_present(
|
||||
header::CONTENT_TYPE,
|
||||
HeaderValue::from_static("application/octet-stream"),
|
||||
);
|
||||
|
||||
let cors = CorsLayer::new()
|
||||
.allow_methods(vec![
|
||||
Method::GET,
|
||||
Method::POST,
|
||||
Method::PUT,
|
||||
Method::DELETE,
|
||||
Method::OPTIONS,
|
||||
])
|
||||
.allow_headers(Any)
|
||||
.allow_origin(Any)
|
||||
.allow_credentials(false);
|
||||
|
||||
Router::new()
|
||||
.route("/", get(get_index))
|
||||
.route("/ws", get(upgrade_ws))
|
||||
.layer(middleware)
|
||||
.layer(cors)
|
||||
.with_state(state)
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct WebSocketUpgradeRequest {}
|
||||
|
||||
async fn get_index() -> Html<String> {
|
||||
Html(format!("Hello!"))
|
||||
}
|
||||
|
||||
#[axum::debug_handler]
|
||||
async fn upgrade_ws(state: State<AppState>, ws: WebSocketUpgrade) -> impl IntoResponse {
|
||||
info!("New client websocket connection");
|
||||
let client_id = uuid::Uuid::new_v4();
|
||||
state
|
||||
.clients
|
||||
.lock()
|
||||
.await
|
||||
.insert(client_id.clone(), Client { sender: None });
|
||||
let client = state.clients.lock().await.get(&client_id).cloned().unwrap();
|
||||
ws.on_upgrade(move |socket| {
|
||||
ws::client_connection(
|
||||
state.client_request_tx.clone(),
|
||||
socket,
|
||||
client_id,
|
||||
state.state.clone(),
|
||||
state.clients.clone(),
|
||||
client,
|
||||
)
|
||||
})
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
#[serde(tag = "type")]
|
||||
pub enum ClientRequest {
|
||||
AddHyperdeck(AddHyperdeckRequest),
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct AddHyperdeckRequest {
|
||||
pub name: String,
|
||||
pub ip: String,
|
||||
pub port: u16,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
#[serde(tag = "type")]
|
||||
pub enum ServerEvent {
|
||||
HyperdeckMonitorState(HyperdeckMonitorState),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
pub struct HyperdeckMonitorState {
|
||||
pub hyperdecks: HashMap<String, HyperdeckState>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct HyperdeckState {
|
||||
pub name: String,
|
||||
pub ip: String,
|
||||
pub port: u16,
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
use std::{future, sync::Arc};
|
||||
|
||||
use super::message::{ClientRequest, HyperdeckMonitorState};
|
||||
use crate::api::ServerEvent;
|
||||
use axum::extract::ws::{Message, WebSocket};
|
||||
use futures::StreamExt;
|
||||
use tokio::sync::RwLock;
|
||||
use tokio_stream::wrappers::BroadcastStream;
|
||||
use tracing::{debug, error, log::info};
|
||||
use uuid::Uuid;
|
||||
|
||||
use super::{Client, Clients};
|
||||
|
||||
pub async fn client_connection(
|
||||
client_request_tx: tokio::sync::mpsc::UnboundedSender<ClientRequest>,
|
||||
ws: WebSocket,
|
||||
id: Uuid,
|
||||
state: Arc<RwLock<HyperdeckMonitorState>>,
|
||||
clients: Clients,
|
||||
mut client: Client,
|
||||
) {
|
||||
let (client_ws_sender, mut client_ws_rcv) = ws.split();
|
||||
let (client_sender, client_rcv) = tokio::sync::broadcast::channel::<Message>(10);
|
||||
let client_rcv = BroadcastStream::new(client_rcv);
|
||||
|
||||
tokio::task::spawn(
|
||||
client_rcv
|
||||
.filter(|msg| future::ready(msg.is_ok()))
|
||||
.map(|msg| Ok(msg.unwrap()))
|
||||
.forward(client_ws_sender),
|
||||
);
|
||||
|
||||
let current_state = state.read().await.clone();
|
||||
let state_json =
|
||||
serde_json::to_string(&ServerEvent::HyperdeckMonitorState(current_state.into())).unwrap();
|
||||
client_sender.send(Message::Text(state_json.clone())).ok();
|
||||
|
||||
client.sender = Some(client_sender);
|
||||
clients.lock().await.insert(id, client);
|
||||
|
||||
info!("{} connected", id);
|
||||
|
||||
while let Some(result) = client_ws_rcv.next().await {
|
||||
let msg = match result {
|
||||
Ok(msg) => msg,
|
||||
Err(e) => {
|
||||
error!("error resolving ws message for id: {}: {}", id.clone(), e);
|
||||
break;
|
||||
}
|
||||
};
|
||||
client_msg(client_request_tx.clone(), &id, msg).await;
|
||||
}
|
||||
|
||||
clients.lock().await.remove(&id);
|
||||
info!("{} disconnected", id);
|
||||
}
|
||||
|
||||
async fn client_msg(
|
||||
client_request_tx: tokio::sync::mpsc::UnboundedSender<ClientRequest>,
|
||||
id: &Uuid,
|
||||
msg: Message,
|
||||
) {
|
||||
debug!("received message from {}: {:?}", id, msg);
|
||||
let message = match msg.into_text() {
|
||||
Ok(v) => v,
|
||||
Err(err) => {
|
||||
error!("error: {:?}", err);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
if message == "ping" || message == "ping\n" {
|
||||
return;
|
||||
}
|
||||
|
||||
let client_request: super::message::ClientRequest = match serde_json::from_str(&message) {
|
||||
Ok(v) => v,
|
||||
Err(_) => {
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let _ = client_request_tx.send(client_request);
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
use std::{net::IpAddr, time::Duration};
|
||||
use std::{process::Stdio, time::Duration};
|
||||
|
||||
use api::message::{AddHyperdeckRequest, ClientRequest, HyperdeckMonitorState, HyperdeckState};
|
||||
use color_eyre::Report;
|
||||
use futures_util::{
|
||||
pin_mut, select,
|
||||
|
@ -9,9 +10,14 @@ use futures_util::{
|
|||
use serde::{Deserialize, Serialize};
|
||||
use tokio::net::TcpStream;
|
||||
use tokio_tungstenite::{tungstenite::Message, MaybeTlsStream, WebSocketStream};
|
||||
use tokio_util::sync::CancellationToken;
|
||||
use tokio_util::{
|
||||
codec::{FramedRead, LinesCodec},
|
||||
sync::CancellationToken,
|
||||
};
|
||||
use tracing_subscriber::EnvFilter;
|
||||
|
||||
mod api;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
setup_logging().expect("Failed to setup logging");
|
||||
|
@ -20,35 +26,169 @@ async fn main() {
|
|||
let cancel = CancellationToken::new();
|
||||
let node_process = run_node_process(cancel.clone()).fuse();
|
||||
|
||||
let (ws_message_tx, ws_message_rx) = tokio::sync::mpsc::unbounded_channel();
|
||||
let (commands_tx, commands_rx) = tokio::sync::mpsc::unbounded_channel();
|
||||
let (node_ws_message_tx, node_ws_message_rx) = tokio::sync::mpsc::unbounded_channel();
|
||||
let (node_commands_tx, node_commands_rx) = tokio::sync::mpsc::unbounded_channel();
|
||||
let state = AppState::default();
|
||||
let ws_process = talk_to_node_ws(state, ws_message_tx, commands_rx, cancel.clone()).fuse();
|
||||
let node_ws_communication =
|
||||
talk_to_node_ws(state, node_ws_message_tx, node_commands_rx, cancel.clone()).fuse();
|
||||
|
||||
let (state_tx, state_rx) = tokio::sync::broadcast::channel(1);
|
||||
let (client_request_tx, client_request_rx) = tokio::sync::mpsc::unbounded_channel();
|
||||
let api = api::initialize_api(state_rx, client_request_tx).fuse();
|
||||
|
||||
let hyperdeck_monitor = run(
|
||||
node_commands_tx,
|
||||
node_ws_message_rx,
|
||||
state_tx,
|
||||
client_request_rx,
|
||||
cancel.clone(),
|
||||
)
|
||||
.fuse();
|
||||
|
||||
pin_mut!(node_process);
|
||||
pin_mut!(ws_process);
|
||||
pin_mut!(node_ws_communication);
|
||||
pin_mut!(api);
|
||||
pin_mut!(hyperdeck_monitor);
|
||||
|
||||
select! {
|
||||
_ = node_process => {},
|
||||
_ = ws_process => {},
|
||||
_ = node_ws_communication => {},
|
||||
_ = api => {},
|
||||
_ = hyperdeck_monitor => {},
|
||||
_ = cancel.cancelled().fuse() => {}
|
||||
};
|
||||
|
||||
cancel.cancel();
|
||||
}
|
||||
|
||||
async fn run(
|
||||
mut node_commands_tx: tokio::sync::mpsc::UnboundedSender<NodeWsCommand>,
|
||||
mut node_ws_message_rx: tokio::sync::mpsc::UnboundedReceiver<NodeWsMessageReceived>,
|
||||
mut state_tx: tokio::sync::broadcast::Sender<HyperdeckMonitorState>,
|
||||
mut client_request_rx: tokio::sync::mpsc::UnboundedReceiver<ClientRequest>,
|
||||
cancel: CancellationToken,
|
||||
) {
|
||||
let mut state = HyperdeckMonitorState::default();
|
||||
let _ = state_tx.send(state.clone());
|
||||
|
||||
let mut ping_interval = tokio::time::interval(Duration::from_millis(500));
|
||||
ping_interval.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Delay);
|
||||
|
||||
while !cancel.is_cancelled() {
|
||||
let state_modified = select! {
|
||||
_ = ping_interval.tick().fuse() => {
|
||||
// TODO: Ping node, check it's still alive
|
||||
false
|
||||
},
|
||||
message_from_node = node_ws_message_rx.recv().fuse() => {
|
||||
if let Some(msg) = message_from_node {
|
||||
handle_message_from_node(msg, &mut node_commands_tx, &mut state).await
|
||||
} else {
|
||||
false
|
||||
}
|
||||
},
|
||||
message_from_client = client_request_rx.recv().fuse() => {
|
||||
if let Some(msg) = message_from_client {
|
||||
handle_message_from_client(msg, &mut node_commands_tx, &mut state).await
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if state_modified {
|
||||
let _ = state_tx.send(state.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn handle_message_from_node(
|
||||
msg: NodeWsMessageReceived,
|
||||
node_commands_tx: &mut tokio::sync::mpsc::UnboundedSender<NodeWsCommand>,
|
||||
state: &mut HyperdeckMonitorState,
|
||||
) -> bool {
|
||||
match msg {
|
||||
NodeWsMessageReceived::Log { message } => {
|
||||
tracing::info!("[NODE] {message}");
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn handle_message_from_client(
|
||||
msg: ClientRequest,
|
||||
node_commands_tx: &mut tokio::sync::mpsc::UnboundedSender<NodeWsCommand>,
|
||||
state: &mut HyperdeckMonitorState,
|
||||
) -> bool {
|
||||
match msg {
|
||||
ClientRequest::AddHyperdeck(AddHyperdeckRequest { name, ip, port }) => {
|
||||
tracing::info!("Adding hyperdeck");
|
||||
let id = uuid::Uuid::new_v4();
|
||||
state.hyperdecks.insert(
|
||||
id.to_string(),
|
||||
HyperdeckState {
|
||||
name,
|
||||
ip: ip.clone(),
|
||||
port,
|
||||
},
|
||||
);
|
||||
let _ = node_commands_tx.send(NodeWsCommand::AddHyperdeck(AddHyperdeckCommand {
|
||||
id: id.to_string(),
|
||||
ip,
|
||||
port,
|
||||
}));
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn run_node_process(cancel: CancellationToken) {
|
||||
while !cancel.is_cancelled() {
|
||||
// Back-off in case we are immediately crashing in a loop.
|
||||
tokio::time::sleep(Duration::from_secs(1)).await;
|
||||
|
||||
let result = tokio::process::Command::new("node")
|
||||
.arg("monitor/index.js")
|
||||
.output()
|
||||
.await;
|
||||
if let Ok(output) = result {
|
||||
if !output.status.success() {
|
||||
let err = String::from_utf8(output.stderr).unwrap_or("Unknown".to_string());
|
||||
tracing::error!("Node process exited with error: {}", err);
|
||||
// Back-off in case we are immediately crashing in a loop.
|
||||
tokio::time::sleep(Duration::from_secs(1)).await;
|
||||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped())
|
||||
.spawn();
|
||||
match result {
|
||||
Ok(mut child_process) => {
|
||||
let Some(raw_stdout) = child_process.stdout.take() else {
|
||||
let _ = child_process.kill().await;
|
||||
continue;
|
||||
};
|
||||
|
||||
let Some(raw_stderr) = child_process.stderr.take() else {
|
||||
let _ = child_process.kill().await;
|
||||
continue;
|
||||
};
|
||||
|
||||
let mut stdout = FramedRead::new(raw_stdout, LinesCodec::new())
|
||||
.map(|data| data.expect("Could not read stdout"));
|
||||
let mut stderr = FramedRead::new(raw_stderr, LinesCodec::new())
|
||||
.map(|data| data.expect("Could not read stderr"));
|
||||
|
||||
while !cancel.is_cancelled() {
|
||||
select! {
|
||||
line = stdout.next().fuse() => {
|
||||
if let Some(line) = line {
|
||||
tracing::info!("[NODE] {line}");
|
||||
}
|
||||
}
|
||||
line = stderr.next().fuse() => {
|
||||
if let Some(line) = line {
|
||||
tracing::error!("[NODE] {line}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let _ = child_process.kill().await;
|
||||
}
|
||||
Err(err) => {
|
||||
tracing::error!("Error running Node child process: {err}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -56,9 +196,15 @@ async fn run_node_process(cancel: CancellationToken) {
|
|||
|
||||
#[derive(Default)]
|
||||
struct AppState {}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(tag = "type")]
|
||||
enum NodeWsCommand {
|
||||
#[serde(rename = "ping")]
|
||||
Ping,
|
||||
#[serde(rename = "add_hyperdeck")]
|
||||
AddHyperdeck(AddHyperdeckCommand),
|
||||
#[serde(rename = "remove_hyperdeck")]
|
||||
RemoveHyperdeck(RemoveHyperdeckCommand),
|
||||
}
|
||||
|
||||
|
@ -69,16 +215,18 @@ enum NodeWsMessageReceived {
|
|||
Log { message: String },
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct AddHyperdeckCommand {
|
||||
ip: IpAddr,
|
||||
id: String,
|
||||
ip: String,
|
||||
port: u16,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct RemoveHyperdeckCommand {
|
||||
ip: IpAddr,
|
||||
id: String,
|
||||
}
|
||||
|
||||
async fn talk_to_node_ws(
|
||||
|
@ -126,28 +274,13 @@ async fn handle_outbound_messages(
|
|||
mut socket_tx: SplitSink<WebSocketStream<MaybeTlsStream<TcpStream>>, Message>,
|
||||
) {
|
||||
while let Some(command) = commands_rx.recv().await {
|
||||
match command {
|
||||
NodeWsCommand::Ping => {
|
||||
let _ = socket_tx
|
||||
.send(tokio_tungstenite::tungstenite::Message::Ping(vec![]))
|
||||
.await;
|
||||
}
|
||||
NodeWsCommand::AddHyperdeck(command) => {
|
||||
let _ = socket_tx
|
||||
.send(tokio_tungstenite::tungstenite::Message::Text(
|
||||
serde_json::to_string(&command)
|
||||
.expect("Could not serialize AddHyperdeck command"),
|
||||
))
|
||||
.await;
|
||||
}
|
||||
NodeWsCommand::RemoveHyperdeck(command) => {
|
||||
let _ = socket_tx
|
||||
.send(tokio_tungstenite::tungstenite::Message::Text(
|
||||
serde_json::to_string(&command)
|
||||
.expect("Could not serialize RemoveHyperdeck command"),
|
||||
))
|
||||
.await;
|
||||
}
|
||||
if let Err(err) = socket_tx
|
||||
.send(tokio_tungstenite::tungstenite::Message::Text(
|
||||
serde_json::to_string(&command).expect("Could not serialize command"),
|
||||
))
|
||||
.await
|
||||
{
|
||||
tracing::error!("Error sending command to Node proccess: {err}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -161,11 +294,7 @@ async fn handle_inbound_messages(
|
|||
match message {
|
||||
Ok(tokio_tungstenite::tungstenite::Message::Text(text)) => {
|
||||
if let Ok(received) = serde_json::from_str::<NodeWsMessageReceived>(&text) {
|
||||
match received {
|
||||
NodeWsMessageReceived::Log { message } => {
|
||||
tracing::info!("Message from Node process: {message}");
|
||||
}
|
||||
}
|
||||
let _ = ws_message_tx.send(received);
|
||||
}
|
||||
}
|
||||
Ok(tokio_tungstenite::tungstenite::Message::Pong(_)) => {}
|
||||
|
|
Loading…
Reference in New Issue