kinda stuck at this point so making a commit
This commit is contained in:
360
Cargo.lock
generated
360
Cargo.lock
generated
@@ -125,7 +125,7 @@ dependencies = [
|
||||
"ndk",
|
||||
"ndk-context",
|
||||
"ndk-sys",
|
||||
"num_enum",
|
||||
"num_enum 0.7.3",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
@@ -201,9 +201,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.90"
|
||||
version = "1.0.91"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37bf3594c4c988a53154954629820791dde498571819ae4ca50ca811e060cc95"
|
||||
checksum = "c042108f3ed77fd83760a5fd79b53be043192bb3b9dba91d8c574c0ada7850c8"
|
||||
|
||||
[[package]]
|
||||
name = "anymap2"
|
||||
@@ -225,7 +225,7 @@ checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -266,7 +266,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -277,7 +277,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -329,7 +329,7 @@ dependencies = [
|
||||
"manyhow",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -345,7 +345,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"quote-use",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -381,9 +381,11 @@ dependencies = [
|
||||
"axum_session",
|
||||
"axum_session_sqlx",
|
||||
"base64 0.22.1",
|
||||
"dashmap 6.1.0",
|
||||
"derive_more",
|
||||
"dotenvy",
|
||||
"futures",
|
||||
"hash-ids",
|
||||
"http 1.1.0",
|
||||
"jsonwebtoken",
|
||||
"leptos",
|
||||
@@ -395,6 +397,7 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_qs 0.13.0",
|
||||
"sha256",
|
||||
"sqids",
|
||||
"sqlx",
|
||||
"tera",
|
||||
"thiserror",
|
||||
@@ -431,6 +434,7 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_qs 0.13.0",
|
||||
"sha256",
|
||||
"simconnect-sdk",
|
||||
"tauri-winrt-notification",
|
||||
"thiserror",
|
||||
"time",
|
||||
@@ -452,6 +456,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bincode",
|
||||
"derive_more",
|
||||
"flate2",
|
||||
"serde",
|
||||
"thiserror",
|
||||
@@ -568,7 +573,7 @@ checksum = "57d123550fa8d071b7255cb0cc04dc302baa6c8c4a79f55701552684d8399bce"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -656,6 +661,29 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bindgen"
|
||||
version = "0.65.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cfdf7b466f9a4903edc73f95d6d2bcd5baf8ae620638762244d3f60143643cc5"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"cexpr",
|
||||
"clang-sys",
|
||||
"lazy_static",
|
||||
"lazycell",
|
||||
"log",
|
||||
"peeking_take_while",
|
||||
"prettyplease",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"regex",
|
||||
"rustc-hash 1.1.0",
|
||||
"shlex",
|
||||
"syn 2.0.85",
|
||||
"which",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bit_field"
|
||||
version = "0.10.2"
|
||||
@@ -776,7 +804,7 @@ version = "0.18.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c878c71c2821aa2058722038a59a67583a4240524687c6028571c9b395ded61f"
|
||||
dependencies = [
|
||||
"darling",
|
||||
"darling 0.14.4",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
@@ -862,6 +890,15 @@ version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c"
|
||||
|
||||
[[package]]
|
||||
name = "cexpr"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
|
||||
dependencies = [
|
||||
"nom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-expr"
|
||||
version = "0.15.8"
|
||||
@@ -944,6 +981,17 @@ dependencies = [
|
||||
"inout",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clang-sys"
|
||||
version = "1.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4"
|
||||
dependencies = [
|
||||
"glob",
|
||||
"libc",
|
||||
"libloading 0.8.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.20"
|
||||
@@ -975,7 +1023,7 @@ dependencies = [
|
||||
"heck 0.5.0",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1294,6 +1342,27 @@ dependencies = [
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "csv"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe"
|
||||
dependencies = [
|
||||
"csv-core",
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "csv-core"
|
||||
version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ctr"
|
||||
version = "0.9.2"
|
||||
@@ -1325,8 +1394,18 @@ version = "0.14.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"darling_macro",
|
||||
"darling_core 0.14.4",
|
||||
"darling_macro 0.14.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling"
|
||||
version = "0.20.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989"
|
||||
dependencies = [
|
||||
"darling_core 0.20.10",
|
||||
"darling_macro 0.20.10",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1343,17 +1422,42 @@ dependencies = [
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_core"
|
||||
version = "0.20.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5"
|
||||
dependencies = [
|
||||
"fnv",
|
||||
"ident_case",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"strsim 0.11.1",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_macro"
|
||||
version = "0.14.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"darling_core 0.14.4",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_macro"
|
||||
version = "0.20.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806"
|
||||
dependencies = [
|
||||
"darling_core 0.20.10",
|
||||
"quote",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dashmap"
|
||||
version = "5.5.3"
|
||||
@@ -1415,7 +1519,38 @@ checksum = "62d671cc41a825ebabc75757b62d3d168c577f9149b2d49ece1dad1f72119d25"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive_builder"
|
||||
version = "0.20.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947"
|
||||
dependencies = [
|
||||
"derive_builder_macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive_builder_core"
|
||||
version = "0.20.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8"
|
||||
dependencies = [
|
||||
"darling 0.20.10",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive_builder_macro"
|
||||
version = "0.20.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c"
|
||||
dependencies = [
|
||||
"derive_builder_core",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1436,7 +1571,7 @@ dependencies = [
|
||||
"convert_case",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.85",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
@@ -1496,7 +1631,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1717,7 +1852,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1812,7 +1947,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2028,7 +2163,7 @@ dependencies = [
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2041,6 +2176,12 @@ dependencies = [
|
||||
"system-deps",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glob"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
|
||||
|
||||
[[package]]
|
||||
name = "globset"
|
||||
version = "0.4.15"
|
||||
@@ -2325,7 +2466,7 @@ dependencies = [
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2338,6 +2479,12 @@ dependencies = [
|
||||
"crunchy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hash-ids"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e637affe86ae6203fb90b3802aa235f00910799b60fbead4d770c42d3495a3af"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.13.2"
|
||||
@@ -2728,7 +2875,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2850,7 +2997,7 @@ checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3018,6 +3165,12 @@ dependencies = [
|
||||
"spin",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazycell"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
||||
|
||||
[[package]]
|
||||
name = "lebe"
|
||||
version = "0.5.2"
|
||||
@@ -3125,7 +3278,7 @@ dependencies = [
|
||||
"quote",
|
||||
"rstml",
|
||||
"serde",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.85",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
@@ -3161,7 +3314,7 @@ dependencies = [
|
||||
"quote",
|
||||
"rstml",
|
||||
"server_fn_macro",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.85",
|
||||
"tracing",
|
||||
"uuid",
|
||||
]
|
||||
@@ -3485,7 +3638,7 @@ dependencies = [
|
||||
"manyhow-macros",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3657,7 +3810,7 @@ dependencies = [
|
||||
"jni-sys",
|
||||
"log",
|
||||
"ndk-sys",
|
||||
"num_enum",
|
||||
"num_enum 0.7.3",
|
||||
"raw-window-handle",
|
||||
"thiserror",
|
||||
]
|
||||
@@ -3768,7 +3921,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3812,13 +3965,34 @@ dependencies = [
|
||||
"libm",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_enum"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a015b430d3c108a207fd776d2e2196aaf8b1cf8cf93253e3a097ff3085076a1"
|
||||
dependencies = [
|
||||
"num_enum_derive 0.6.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_enum"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179"
|
||||
dependencies = [
|
||||
"num_enum_derive",
|
||||
"num_enum_derive 0.7.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_enum_derive"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96667db765a921f7b295ffee8b60472b686a51d4f21c2ee4ffdb94c7013b65a6"
|
||||
dependencies = [
|
||||
"proc-macro-crate 1.3.1",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3830,7 +4004,7 @@ dependencies = [
|
||||
"proc-macro-crate 3.2.0",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4178,6 +4352,17 @@ dependencies = [
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parser"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"csv",
|
||||
"ctrlc",
|
||||
"serde",
|
||||
"simconnect-sdk",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "password-hash"
|
||||
version = "0.5.0"
|
||||
@@ -4201,6 +4386,12 @@ version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd"
|
||||
|
||||
[[package]]
|
||||
name = "peeking_take_while"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
|
||||
|
||||
[[package]]
|
||||
name = "pem"
|
||||
version = "3.0.4"
|
||||
@@ -4257,7 +4448,7 @@ dependencies = [
|
||||
"pest_meta",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4288,7 +4479,7 @@ checksum = "a4502d8515ca9f32f1fb543d987f63d95a14934883db45bdb48060b6b69257f8"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4392,7 +4583,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "479cf940fbbb3426c32c5d5176f62ad57549a0bb84773423ba8be9d089f5faba"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4507,7 +4698,7 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.85",
|
||||
"version_check",
|
||||
"yansi",
|
||||
]
|
||||
@@ -4528,7 +4719,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a65f2e60fbf1063868558d69c6beacf412dc755f9fc020f514b7955fc914fe30"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4649,7 +4840,7 @@ dependencies = [
|
||||
"proc-macro-utils 0.10.0",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4949,7 +5140,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"proc-macro2-diagnostics",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.85",
|
||||
"syn_derive",
|
||||
"thiserror",
|
||||
]
|
||||
@@ -5114,9 +5305,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.210"
|
||||
version = "1.0.213"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a"
|
||||
checksum = "3ea7893ff5e2466df8d720bb615088341b295f849602c6956047f8f80f0e9bc1"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
@@ -5145,13 +5336,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.210"
|
||||
version = "1.0.213"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f"
|
||||
checksum = "7e85ad2009c50b58e87caa8cd6dac16bdf511bbfb7af6c33df902396aa480fa5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5273,7 +5464,7 @@ dependencies = [
|
||||
"convert_case",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.85",
|
||||
"xxhash-rust",
|
||||
]
|
||||
|
||||
@@ -5284,7 +5475,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f2aa8119b558a17992e0ac1fd07f080099564f24532858811ce04f742542440"
|
||||
dependencies = [
|
||||
"server_fn_macro",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5356,6 +5547,27 @@ dependencies = [
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "simconnect-sdk"
|
||||
version = "0.2.2"
|
||||
dependencies = [
|
||||
"bindgen",
|
||||
"num_enum 0.6.1",
|
||||
"simconnect-sdk-derive",
|
||||
"thiserror",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "simconnect-sdk-derive"
|
||||
version = "0.2.2"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "simd-adler32"
|
||||
version = "0.3.7"
|
||||
@@ -5474,6 +5686,18 @@ dependencies = [
|
||||
"der",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sqids"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f328f10ae594f0da04e5b2f82c089232697312661bca22d5d015a680c84639d"
|
||||
dependencies = [
|
||||
"derive_builder",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sqlformat"
|
||||
version = "0.2.6"
|
||||
@@ -5551,7 +5775,7 @@ dependencies = [
|
||||
"quote",
|
||||
"sqlx-core",
|
||||
"sqlx-macros-core",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5574,7 +5798,7 @@ dependencies = [
|
||||
"sqlx-mysql",
|
||||
"sqlx-postgres",
|
||||
"sqlx-sqlite",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.85",
|
||||
"tempfile",
|
||||
"tokio",
|
||||
"url",
|
||||
@@ -5756,9 +5980,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.79"
|
||||
version = "2.0.85"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590"
|
||||
checksum = "5023162dfcd14ef8f32034d8bcd4cc5ddc61ef7a247c024a33e24e1f24d21b56"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -5774,7 +5998,7 @@ dependencies = [
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5800,7 +6024,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5880,7 +6104,7 @@ checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6020,7 +6244,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6220,7 +6444,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6343,7 +6567,7 @@ checksum = "1f718dfaf347dcb5b983bfc87608144b0bad87970aebcbea5ce44d2a30c08e63"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6633,7 +6857,7 @@ dependencies = [
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.85",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
@@ -6667,7 +6891,7 @@ checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.85",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
@@ -6835,6 +7059,18 @@ version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082"
|
||||
|
||||
[[package]]
|
||||
name = "which"
|
||||
version = "4.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7"
|
||||
dependencies = [
|
||||
"either",
|
||||
"home",
|
||||
"once_cell",
|
||||
"rustix",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "whoami"
|
||||
version = "1.5.2"
|
||||
@@ -6932,7 +7168,7 @@ checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6943,7 +7179,7 @@ checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -7419,7 +7655,7 @@ checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.85",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
@@ -7441,7 +7677,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -7461,7 +7697,7 @@ checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.85",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
@@ -7490,7 +7726,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@@ -1,5 +1,5 @@
|
||||
[workspace]
|
||||
members = [".", "avam-client", "avam-protocol", "avam-wasm"]
|
||||
members = [".", "avam-client", "avam-protocol", "avam-wasm", "parser"]
|
||||
resolver = "2"
|
||||
|
||||
[package]
|
||||
@@ -31,6 +31,7 @@ ssr = [
|
||||
"dep:avam-protocol",
|
||||
|
||||
"dep:argon2",
|
||||
"dep:dashmap",
|
||||
|
||||
"dep:axum",
|
||||
"dep:axum-extra",
|
||||
@@ -67,6 +68,7 @@ avam-protocol = { path = "./avam-protocol", optional = true }
|
||||
anyhow = { version = "1.0.89", optional = false }
|
||||
argon2 = { version = "0.5.3", optional = true }
|
||||
derive_more = { version = "1.0.0", features = ["full"], optional = false }
|
||||
dashmap = { version = "6.1.0", optional = true }
|
||||
dotenvy = { version = "0.15.7", optional = true }
|
||||
futures = { version = "0.3.31", optional = true }
|
||||
rand = { version = "0.8.5", optional = true }
|
||||
@@ -127,6 +129,8 @@ base64 = { version = "0.22.1", default-features = false }
|
||||
jsonwebtoken = { version = "9.3.0", optional = true }
|
||||
serde_qs = "0.13.0"
|
||||
sha256 = { version = "1.5.0", optional = true } # this fucker has a dependency on tokio?!
|
||||
sqids = "0.4.1"
|
||||
hash-ids = "0.3.1"
|
||||
|
||||
[[workspace.metadata.leptos]]
|
||||
name = "avam"
|
||||
|
BIN
SimConnect.dll
Normal file
BIN
SimConnect.dll
Normal file
Binary file not shown.
@@ -4,8 +4,8 @@ version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
avam-protocol = { path = "../avam-protocol" }
|
||||
anyhow = { version = "1.0" }
|
||||
avam-protocol = { path = "../avam-protocol" }
|
||||
base64 = { version = "0.22.1", default-features = false }
|
||||
clap = { version = "4.5.20", features = ["derive"] }
|
||||
config = "0.14.0"
|
||||
@@ -28,6 +28,9 @@ reqwest = { version = "0.12.8", default-features = false, features = [
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_qs = "0.13.0"
|
||||
sha256 = "1.5.0"
|
||||
simconnect-sdk = { path = "D:/source/MSFS/simconnect-sdk-rs/simconnect-sdk", features = [
|
||||
"derive",
|
||||
] }
|
||||
tauri-winrt-notification = "0.6.0"
|
||||
thiserror = { version = "1.0" }
|
||||
time = "0.3.36"
|
||||
@@ -37,7 +40,7 @@ tokio-tungstenite = { version = "0.24.0", features = [
|
||||
] }
|
||||
toml = "0.8"
|
||||
tracing = "0.1.40"
|
||||
tracing-subscriber = { version = "0.3.18", features = ["time"] }
|
||||
tracing-subscriber = { version = "0.3.18", features = ["time", "fmt", "std"] }
|
||||
tray-icon = "0.19"
|
||||
uuid = { version = "1.10.0", features = ["fast-rng", "serde", "v4"] }
|
||||
winit = "0.30"
|
||||
|
@@ -1,5 +1,27 @@
|
||||
use windres::Build;
|
||||
|
||||
fn main() {
|
||||
Build::new().compile("icon.rc").unwrap();
|
||||
fn main() -> std::io::Result<()> {
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
let target_os = std::env::var("CARGO_CFG_TARGET_OS");
|
||||
if target_os.as_deref() == Ok("windows") {
|
||||
let name = "Avii's Virtual Airline Manager";
|
||||
let version = env!("CARGO_PKG_VERSION");
|
||||
let mut sv = version.split('.').collect::<Vec<_>>();
|
||||
while sv.len() < 4 {
|
||||
sv.push("0");
|
||||
}
|
||||
let file_version = format!("{}, {}, {}, {}", sv[0], sv[1], sv[2], sv[3]);
|
||||
windres::Build::new()
|
||||
.define(
|
||||
"THE_FILE",
|
||||
Some(format!(r#""{name} Client Module""#).as_str()),
|
||||
)
|
||||
.define("THE_PROJECT", Some(format!(r#""{name}""#).as_str()))
|
||||
.define("THE_VERSION", Some(format!(r#""{version}""#).as_str()))
|
||||
.define("THE_FILEVERSION", Some(file_version.as_str()))
|
||||
.compile("res/resource.rc")?;
|
||||
for entry in std::fs::read_dir("res")? {
|
||||
let entry = entry?;
|
||||
println!("cargo:rerun-if-changed={}", entry.path().display());
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@@ -1 +0,0 @@
|
||||
1 ICON "icon.ico"
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
28
avam-client/res/resource.rc
Normal file
28
avam-client/res/resource.rc
Normal file
@@ -0,0 +1,28 @@
|
||||
#pragma code_page(65001)
|
||||
|
||||
1 VERSIONINFO
|
||||
FILEVERSION THE_FILEVERSION
|
||||
PRODUCTVERSION THE_FILEVERSION
|
||||
FILEFLAGSMASK 0x0000003Fl //VS_FFI_FILEFLAGSMASK
|
||||
FILEFLAGS 0x0
|
||||
FILEOS 0x00040004l //VOS_NT_WINDOWS32
|
||||
FILETYPE 0x00000001l //VFT_APP
|
||||
FILESUBTYPE 0x00000000l //VFT2_UNKNOWN
|
||||
{
|
||||
BLOCK "StringFileInfo"
|
||||
{
|
||||
BLOCK "040904B0"
|
||||
{
|
||||
VALUE "FileDescription", THE_FILE
|
||||
VALUE "FileVersion", THE_VERSION
|
||||
VALUE "ProductVersion", THE_VERSION
|
||||
VALUE "ProductName", THE_PROJECT
|
||||
}
|
||||
}
|
||||
BLOCK "VarFileInfo"
|
||||
{
|
||||
VALUE "Translation", 0x409, 0x4B0
|
||||
}
|
||||
}
|
||||
|
||||
1 ICON "res/icon.ico"
|
@@ -86,7 +86,7 @@ pub async fn start(
|
||||
Message::Binary(encoded_message)
|
||||
}
|
||||
d => {
|
||||
tracing::info!("sending packet: {:?}", &d);
|
||||
// tracing::info!("sending packet: {:#?}", &d);
|
||||
let Ok(encoded_message) = d.encode() else {
|
||||
tracing::error!(
|
||||
"Unable to encode message for sending: {:#?}",
|
||||
|
@@ -262,13 +262,15 @@ fn init_logging() -> Result<(), anyhow::Error> {
|
||||
#[cfg(not(debug_assertions))]
|
||||
let file = File::options().append(true).open(&log_file)?;
|
||||
|
||||
let fmt = tracing_subscriber::fmt::layer().with_filter(tracing_subscriber::filter::filter_fn(
|
||||
|metadata| metadata.level() < &Level::TRACE,
|
||||
));
|
||||
let fmt = tracing_subscriber::fmt::layer();
|
||||
|
||||
#[cfg(not(debug_assertions))]
|
||||
let fmt = fmt.with_ansi(false).with_writer(Arc::new(file));
|
||||
|
||||
let fmt = fmt.with_filter(tracing_subscriber::filter::filter_fn(|metadata| {
|
||||
metadata.level() < &Level::TRACE
|
||||
}));
|
||||
|
||||
tracing_subscriber::registry().with(fmt).init();
|
||||
|
||||
Ok(())
|
||||
|
@@ -194,34 +194,6 @@ impl AuthorizeRequest {
|
||||
scope,
|
||||
}
|
||||
}
|
||||
|
||||
// pub fn client_id(&self) -> uuid::Uuid {
|
||||
// self.client_id
|
||||
// }
|
||||
|
||||
// pub fn response_type(&self) -> ResponseType {
|
||||
// self.response_type.clone()
|
||||
// }
|
||||
|
||||
// pub fn state(&self) -> Option<String> {
|
||||
// self.state.clone()
|
||||
// }
|
||||
|
||||
// pub fn code_challenge(&self) -> String {
|
||||
// self.code_challenge.clone()
|
||||
// }
|
||||
|
||||
// pub fn code_challenge_method(&self) -> Option<CodeChallengeMethod> {
|
||||
// self.code_challenge_method.clone()
|
||||
// }
|
||||
|
||||
// pub fn redirect_uri(&self) -> String {
|
||||
// self.redirect_uri.clone()
|
||||
// }
|
||||
|
||||
// pub fn scope(&self) -> Option<String> {
|
||||
// self.scope.clone()
|
||||
// }
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
|
@@ -1,18 +1,210 @@
|
||||
use std::time::Duration;
|
||||
mod models;
|
||||
|
||||
use avam_protocol::SimConnectPacket;
|
||||
use core::ops::ControlFlow;
|
||||
use models::*;
|
||||
use simconnect_sdk::{Notification, Object, SimConnect as SC, SystemEvent, SystemEventRequest};
|
||||
use std::{sync::Arc, time::Duration};
|
||||
use tokio::{
|
||||
sync::broadcast::{Receiver, Sender},
|
||||
sync::{
|
||||
broadcast::{Receiver, Sender},
|
||||
RwLock,
|
||||
},
|
||||
time::sleep,
|
||||
};
|
||||
|
||||
use crate::state_machine::Event;
|
||||
|
||||
pub struct SimState {
|
||||
atc_id: String,
|
||||
// gps location
|
||||
// fuel state
|
||||
// cargo state
|
||||
// is landed
|
||||
// is stopped
|
||||
// etc
|
||||
// basically, all the data we wanna send to socket
|
||||
|
||||
// we also need to know if we're in a flight here, and what flight,
|
||||
// mission parameters etc maybe
|
||||
// unless we just wanna keep that purely serverside..
|
||||
// and only process incoming packets if there is an activem mission.
|
||||
|
||||
// the thing i _dont_ want, is to be invasive with alerts and notifications
|
||||
// that the user is "forgetting" to start a flight etc with AVAM running
|
||||
// basically, avam should be able to be running always without the user noticing
|
||||
// any interaction is done via the dashboard
|
||||
// starting, stopping, status etc
|
||||
|
||||
// eventually even with "realistic" flightplans, from time of takeoff, estimate time of arrival,
|
||||
// and even have time-critical jobs that need to get finished before a set time
|
||||
}
|
||||
|
||||
impl Default for SimState {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
atc_id: String::from("AVAM"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SimConnect {
|
||||
simconnect_receiver: Receiver<SimConnectPacket>, // Data from the socket
|
||||
socket_sender: Sender<SimConnectPacket>, // Data to the socket
|
||||
sender: Sender<Event>,
|
||||
receiver: Receiver<Event>,
|
||||
state: Arc<RwLock<SimState>>,
|
||||
}
|
||||
|
||||
impl SimConnect {
|
||||
async fn open(&self, client: &mut SC) -> Result<(), anyhow::Error> {
|
||||
client.subscribe_to_system_event(SystemEventRequest::AircraftLoaded)?;
|
||||
client.subscribe_to_system_event(SystemEventRequest::SimStart)?;
|
||||
|
||||
let id = client.register_object::<AtcID>()?;
|
||||
client.register_object::<Airplane>()?;
|
||||
client.register_object::<Fuel>()?;
|
||||
client.register_object::<Gps>()?;
|
||||
client.register_object::<OnGround>()?;
|
||||
client.register_object::<IsParked>()?;
|
||||
|
||||
let value = self.state.read().await.atc_id.clone();
|
||||
tracing::info!("Updating ATC_ID: {}", &value);
|
||||
client.set_data_on_sim_object_with_id(id, &mut atc_id(&value)?)?;
|
||||
|
||||
let _ = self.sender.send(Event::SimConnected);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn object(&self, _: &mut SC, object: &Object) -> Result<(), anyhow::Error> {
|
||||
if let Ok(data) = Airplane::try_from(object) {
|
||||
self.socket_sender
|
||||
.send(SimConnectPacket::Airplane(avam_protocol::Airplane {
|
||||
atc_type: data.atc_type,
|
||||
atc_model: data.atc_model,
|
||||
title: data.title,
|
||||
category: data.category,
|
||||
}))?;
|
||||
// We've already got our data, there's no point in trying another in this iteration
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if let Ok(data) = Fuel::try_from(object) {
|
||||
self.socket_sender
|
||||
.send(SimConnectPacket::Fuel(avam_protocol::Fuel {
|
||||
weight: data.weight,
|
||||
center_quantity: data.center_quantity,
|
||||
center_capacity: data.center_capacity,
|
||||
center2_quantity: data.center2_quantity,
|
||||
center2_capacity: data.center2_capacity,
|
||||
center3_quantity: data.center3_quantity,
|
||||
center3_capacity: data.center3_capacity,
|
||||
left_main_quantity: data.left_main_quantity,
|
||||
left_main_capacity: data.left_main_capacity,
|
||||
left_aux_quantity: data.left_aux_quantity,
|
||||
left_aux_capacity: data.left_aux_capacity,
|
||||
left_tip_quantity: data.left_tip_quantity,
|
||||
left_tip_capacity: data.left_tip_capacity,
|
||||
right_main_quantity: data.right_main_quantity,
|
||||
right_main_capacity: data.right_main_capacity,
|
||||
right_aux_quantity: data.right_aux_quantity,
|
||||
right_aux_capacity: data.right_aux_capacity,
|
||||
right_tip_quantity: data.right_tip_quantity,
|
||||
right_tip_capacity: data.right_tip_capacity,
|
||||
external1_quantity: data.external1_quantity,
|
||||
external1_capacity: data.external1_capacity,
|
||||
external2_quantity: data.external2_quantity,
|
||||
external2_capacity: data.external2_capacity,
|
||||
}))?;
|
||||
// We've already got our data, there's no point in trying another in this iteration
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if let Ok(data) = Gps::try_from(object) {
|
||||
self.socket_sender
|
||||
.send(SimConnectPacket::Gps(avam_protocol::Gps {
|
||||
lat: data.lat,
|
||||
lon: data.lon,
|
||||
alt: data.alt,
|
||||
}))?;
|
||||
// We've already got our data, there's no point in trying another in this iteration
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if let Ok(data) = OnGround::try_from(object) {
|
||||
self.socket_sender
|
||||
.send(SimConnectPacket::OnGround(avam_protocol::OnGround {
|
||||
sim_on_ground: data.sim_on_ground,
|
||||
}))?;
|
||||
// We've already got our data, there's no point in trying another in this iteration
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Change to parking break state or something, unless we're a helicopter, then we dont have one
|
||||
if let Ok(data) = IsParked::try_from(object) {
|
||||
self.socket_sender
|
||||
.send(SimConnectPacket::IsParked(avam_protocol::IsParked {
|
||||
is_parked: data.is_parked,
|
||||
}))?;
|
||||
// We've already got our data, there's no point in trying another in this iteration
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn system_event(
|
||||
&self,
|
||||
client: &mut SC,
|
||||
event: &SystemEvent,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
match event {
|
||||
SystemEvent::AircraftLoaded { .. } => {
|
||||
tracing::info!("Aircraft Loaded!");
|
||||
let id = client.get_object_id::<AtcID>()?;
|
||||
|
||||
let value = self.state.read().await.atc_id.clone();
|
||||
tracing::info!("Updating ATC_ID: {}", &value);
|
||||
for _ in 1..=10 {
|
||||
client.set_data_on_sim_object_with_id(id, &mut atc_id(&value)?)?;
|
||||
sleep(Duration::from_millis(50)).await;
|
||||
}
|
||||
}
|
||||
SystemEvent::SimStart => {
|
||||
tracing::info!("Sim Start");
|
||||
}
|
||||
|
||||
// SystemEvent::OneSecond => todo!(),
|
||||
// SystemEvent::FourSeconds => todo!(),
|
||||
// SystemEvent::SixTimesPerSecond => todo!(),
|
||||
// SystemEvent::AircraftLoaded { file_name } => todo!(),
|
||||
// SystemEvent::Crashed => todo!(),
|
||||
// SystemEvent::CrashReset => todo!(),
|
||||
// SystemEvent::FlightSaved { file_name } => todo!(),
|
||||
// SystemEvent::FlightPlanActivated { file_name } => todo!(),
|
||||
// SystemEvent::FlightPlanDeactivated => todo!(),
|
||||
// SystemEvent::Frame {
|
||||
// frame_rate,
|
||||
// sim_speed,
|
||||
// } => todo!(),
|
||||
// SystemEvent::Pause { state } => todo!(),
|
||||
// SystemEvent::Paused => todo!(),
|
||||
// SystemEvent::PauseFrame {
|
||||
// frame_rate,
|
||||
// sim_speed,
|
||||
// } => todo!(),
|
||||
// SystemEvent::PositionChanged => todo!(),
|
||||
// SystemEvent::Sim { state } => todo!(),
|
||||
// SystemEvent::SimStart => todo!(),
|
||||
// SystemEvent::SimStop => todo!(),
|
||||
// SystemEvent::Sound { state } => todo!(),
|
||||
// SystemEvent::Unpaused => todo!(),
|
||||
// SystemEvent::View { view } => todo!(),
|
||||
_ => todo!(),
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl SimConnect {
|
||||
@@ -27,23 +219,83 @@ impl SimConnect {
|
||||
socket_sender,
|
||||
sender,
|
||||
receiver,
|
||||
state: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn run(&self) -> Result<(), anyhow::Error> {
|
||||
let mut receiver = self.receiver.resubscribe();
|
||||
let mut simconnect_receiver = self.simconnect_receiver.resubscribe();
|
||||
let state = self.state.clone();
|
||||
let mut sc: Option<SC> = None;
|
||||
loop {
|
||||
if let Ok(Event::Quit) = receiver.try_recv() {
|
||||
break;
|
||||
}
|
||||
|
||||
// handle simconnect stuff here
|
||||
if let Ok(packet) = simconnect_receiver.try_recv() {
|
||||
match packet {
|
||||
SimConnectPacket::AtcID(value) => {
|
||||
state.write().await.atc_id = value.clone();
|
||||
if let Some(client) = sc.as_mut() {
|
||||
if let Ok(id) = client.get_object_id::<AtcID>() {
|
||||
tracing::info!("Updating ATC_ID: {}", &value);
|
||||
client.set_data_on_sim_object_with_id(id, &mut atc_id(&value)?)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
SimConnectPacket::Fuel(_) => unreachable!(), // Outgoing packet, not handled here (yet) we probably need to set fuel state somehow
|
||||
SimConnectPacket::Airplane(_) => unreachable!(),
|
||||
SimConnectPacket::Gps(_) => unreachable!(), // Outgoing packet, not handled here (yet) we probably need to set position somehow
|
||||
SimConnectPacket::OnGround(_) => unreachable!(), // Outgoing packet, not handled here
|
||||
SimConnectPacket::IsParked(_) => unreachable!(), // Outgoing packet, not handled here
|
||||
}
|
||||
}
|
||||
|
||||
if sc.is_none() {
|
||||
if let Ok(simconnect) = SC::new("Avii's Virtual Airline Manager") {
|
||||
sc = Some(simconnect);
|
||||
tracing::info!("Connected");
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(client) = sc.as_mut() {
|
||||
if self.handle(client).await.is_break() {
|
||||
tracing::info!("Disconnected");
|
||||
sc = None;
|
||||
}
|
||||
}
|
||||
|
||||
sleep(Duration::from_millis(100)).await;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn handle(&self, client: &mut SC) -> ControlFlow<(), ()> {
|
||||
if let Ok(Some(event)) = client.get_next_dispatch() {
|
||||
if let Err(e) = match event {
|
||||
Notification::Open => self.open(client).await,
|
||||
Notification::Object(ref object) => self.object(client, object).await,
|
||||
Notification::SystemEvent(ref system_event) => {
|
||||
self.system_event(client, system_event).await
|
||||
}
|
||||
// Notification::ClientEvent(ref client_event) => todo!(),
|
||||
// Notification::AirportList(ref vec) => todo!(),
|
||||
// Notification::WaypointList(ref vec) => todo!(),
|
||||
// Notification::NdbList(ref vec) => todo!(),
|
||||
// Notification::VorList(ref vec) => todo!(),
|
||||
Notification::Quit => {
|
||||
let _ = self.sender.send(Event::SimDisconnected);
|
||||
return ControlFlow::Break(());
|
||||
}
|
||||
_ => todo!(),
|
||||
} {
|
||||
tracing::error!("Error handling SimConnect::Notification: {:#?}", e);
|
||||
};
|
||||
}
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn start(
|
||||
|
123
avam-client/src/simconnect/models.rs
Normal file
123
avam-client/src/simconnect/models.rs
Normal file
@@ -0,0 +1,123 @@
|
||||
use std::ffi::CString;
|
||||
|
||||
use simconnect_sdk::SimConnectObject;
|
||||
|
||||
#[allow(unused)]
|
||||
#[derive(Debug, Clone, SimConnectObject)]
|
||||
#[simconnect(period = "second", condition = "changed")]
|
||||
pub(super) struct AtcID {
|
||||
#[simconnect(name = "ATC ID")]
|
||||
pub value: String,
|
||||
}
|
||||
|
||||
pub(super) fn atc_id(value: &str) -> Result<AtcIDCPacked, anyhow::Error> {
|
||||
if value.len() > 10 {
|
||||
return Err(anyhow::anyhow!("ATC_ID exceeding 10 characters"));
|
||||
}
|
||||
let cs = CString::new(value.to_uppercase())?;
|
||||
let mut buffer = [0i8; 256];
|
||||
for (i, b) in cs.to_bytes_with_nul().iter().enumerate() {
|
||||
buffer[i] = *b as i8;
|
||||
}
|
||||
Ok(AtcIDCPacked { value: buffer })
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, SimConnectObject)]
|
||||
#[simconnect(period = "second", condition = "changed")]
|
||||
pub(super) struct Airplane {
|
||||
#[simconnect(name = "ATC TYPE")]
|
||||
pub atc_type: String,
|
||||
#[simconnect(name = "ATC MODEL")]
|
||||
pub atc_model: String,
|
||||
#[simconnect(name = "TITLE")]
|
||||
pub title: String,
|
||||
#[simconnect(name = "CATEGORY")]
|
||||
pub category: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, SimConnectObject)]
|
||||
#[simconnect(period = "second", condition = "changed")]
|
||||
pub(super) struct Fuel {
|
||||
#[simconnect(name = "FUEL TANK CENTER QUANTITY", unit = "gallons")]
|
||||
pub center_quantity: f64,
|
||||
#[simconnect(name = "FUEL TANK CENTER CAPACITY", unit = "gallons")]
|
||||
pub center_capacity: f64,
|
||||
|
||||
#[simconnect(name = "FUEL TANK CENTER2 QUANTITY", unit = "gallons")]
|
||||
pub center2_quantity: f64,
|
||||
#[simconnect(name = "FUEL TANK CENTER2 CAPACITY", unit = "gallons")]
|
||||
pub center2_capacity: f64,
|
||||
|
||||
#[simconnect(name = "FUEL TANK CENTER3 QUANTITY", unit = "gallons")]
|
||||
pub center3_quantity: f64,
|
||||
#[simconnect(name = "FUEL TANK CENTER3 CAPACITY", unit = "gallons")]
|
||||
pub center3_capacity: f64,
|
||||
|
||||
#[simconnect(name = "FUEL TANK LEFT MAIN QUANTITY", unit = "gallons")]
|
||||
pub left_main_quantity: f64,
|
||||
#[simconnect(name = "FUEL TANK LEFT MAIN CAPACITY", unit = "gallons")]
|
||||
pub left_main_capacity: f64,
|
||||
|
||||
#[simconnect(name = "FUEL TANK LEFT AUX QUANTITY", unit = "gallons")]
|
||||
pub left_aux_quantity: f64,
|
||||
#[simconnect(name = "FUEL TANK LEFT AUX CAPACITY", unit = "gallons")]
|
||||
pub left_aux_capacity: f64,
|
||||
|
||||
#[simconnect(name = "FUEL TANK LEFT TIP QUANTITY", unit = "gallons")]
|
||||
pub left_tip_quantity: f64,
|
||||
#[simconnect(name = "FUEL TANK LEFT TIP CAPACITY", unit = "gallons")]
|
||||
pub left_tip_capacity: f64,
|
||||
|
||||
#[simconnect(name = "FUEL TANK RIGHT MAIN QUANTITY", unit = "gallons")]
|
||||
pub right_main_quantity: f64,
|
||||
#[simconnect(name = "FUEL TANK RIGHT MAIN CAPACITY", unit = "gallons")]
|
||||
pub right_main_capacity: f64,
|
||||
|
||||
#[simconnect(name = "FUEL TANK RIGHT AUX QUANTITY", unit = "gallons")]
|
||||
pub right_aux_quantity: f64,
|
||||
#[simconnect(name = "FUEL TANK RIGHT AUX CAPACITY", unit = "gallons")]
|
||||
pub right_aux_capacity: f64,
|
||||
|
||||
#[simconnect(name = "FUEL TANK RIGHT TIP QUANTITY", unit = "gallons")]
|
||||
pub right_tip_quantity: f64,
|
||||
#[simconnect(name = "FUEL TANK RIGHT TIP CAPACITY", unit = "gallons")]
|
||||
pub right_tip_capacity: f64,
|
||||
|
||||
#[simconnect(name = "FUEL TANK EXTERNAL1 QUANTITY", unit = "gallons")]
|
||||
pub external1_quantity: f64,
|
||||
#[simconnect(name = "FUEL TANK EXTERNAL1 CAPACITY", unit = "gallons")]
|
||||
pub external1_capacity: f64,
|
||||
|
||||
#[simconnect(name = "FUEL TANK EXTERNAL2 QUANTITY", unit = "gallons")]
|
||||
pub external2_quantity: f64,
|
||||
#[simconnect(name = "FUEL TANK EXTERNAL2 CAPACITY", unit = "gallons")]
|
||||
pub external2_capacity: f64,
|
||||
|
||||
#[simconnect(name = "FUEL WEIGHT PER GALLON", unit = "pounds")]
|
||||
pub weight: f64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, SimConnectObject)]
|
||||
#[simconnect(period = "second", condition = "changed")]
|
||||
pub(super) struct Gps {
|
||||
#[simconnect(name = "PLANE LATITUDE", unit = "degrees")]
|
||||
pub lat: f64,
|
||||
#[simconnect(name = "PLANE LONGITUDE", unit = "degrees")]
|
||||
pub lon: f64,
|
||||
#[simconnect(name = "PLANE ALTITUDE", unit = "feet")]
|
||||
pub alt: f64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, SimConnectObject)]
|
||||
#[simconnect(period = "second", condition = "changed")]
|
||||
pub(super) struct OnGround {
|
||||
#[simconnect(name = "SIM ON GROUND")]
|
||||
pub sim_on_ground: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, SimConnectObject)]
|
||||
#[simconnect(period = "second", condition = "changed")]
|
||||
pub(super) struct IsParked {
|
||||
#[simconnect(name = "PLANE IN PARKING STATE")]
|
||||
pub is_parked: bool,
|
||||
}
|
@@ -6,6 +6,7 @@ edition = "2021"
|
||||
[dependencies]
|
||||
anyhow = "1.0.90"
|
||||
bincode = "1.3.3"
|
||||
derive_more = "1.0.0"
|
||||
flate2 = { version = "1.0.34", features = ["zlib-rs"] }
|
||||
serde = { version = "1.0.210", features = ["derive"] }
|
||||
thiserror = "1.0.64"
|
||||
|
@@ -1,18 +1,153 @@
|
||||
use derive_more::derive::Display;
|
||||
use serde::{de, Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
|
||||
#[derive(Debug, Display, Clone, PartialEq, Eq, Deserialize, Serialize)]
|
||||
pub enum SystemPacket {
|
||||
Ping,
|
||||
Pong,
|
||||
Close { reason: String },
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
|
||||
#[derive(Debug, Display, Clone, Deserialize, Serialize)]
|
||||
pub enum SimConnectPacket {
|
||||
// ..
|
||||
AtcID(String),
|
||||
Airplane(Airplane),
|
||||
Fuel(Fuel),
|
||||
Gps(Gps),
|
||||
OnGround(OnGround),
|
||||
IsParked(IsParked),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
|
||||
#[derive(Debug, Clone, Display, Deserialize, Serialize)]
|
||||
#[display("[{atc_type} - {atc_model}] {title} ({category})")]
|
||||
pub struct Airplane {
|
||||
pub atc_type: String,
|
||||
pub atc_model: String,
|
||||
pub title: String,
|
||||
pub category: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub struct Fuel {
|
||||
pub center_quantity: f64,
|
||||
pub center_capacity: f64,
|
||||
|
||||
pub center2_quantity: f64,
|
||||
pub center2_capacity: f64,
|
||||
|
||||
pub center3_quantity: f64,
|
||||
pub center3_capacity: f64,
|
||||
|
||||
pub left_main_quantity: f64,
|
||||
pub left_main_capacity: f64,
|
||||
|
||||
pub left_aux_quantity: f64,
|
||||
pub left_aux_capacity: f64,
|
||||
|
||||
pub left_tip_quantity: f64,
|
||||
pub left_tip_capacity: f64,
|
||||
|
||||
pub right_main_quantity: f64,
|
||||
pub right_main_capacity: f64,
|
||||
|
||||
pub right_aux_quantity: f64,
|
||||
pub right_aux_capacity: f64,
|
||||
|
||||
pub right_tip_quantity: f64,
|
||||
pub right_tip_capacity: f64,
|
||||
|
||||
pub external1_quantity: f64,
|
||||
pub external1_capacity: f64,
|
||||
|
||||
pub external2_quantity: f64,
|
||||
pub external2_capacity: f64,
|
||||
|
||||
pub weight: f64,
|
||||
}
|
||||
|
||||
impl Fuel {
|
||||
pub fn total_quantity(&self) -> f64 {
|
||||
self.center_quantity
|
||||
+ self.center2_quantity
|
||||
+ self.center3_quantity
|
||||
+ self.left_main_quantity
|
||||
+ self.left_aux_quantity
|
||||
+ self.left_tip_quantity
|
||||
+ self.right_main_quantity
|
||||
+ self.right_aux_quantity
|
||||
+ self.right_tip_quantity
|
||||
+ self.external1_quantity
|
||||
+ self.external2_quantity
|
||||
}
|
||||
|
||||
pub fn total_capacity(&self) -> f64 {
|
||||
self.center_capacity
|
||||
+ self.center2_capacity
|
||||
+ self.center3_capacity
|
||||
+ self.left_main_capacity
|
||||
+ self.left_aux_capacity
|
||||
+ self.left_tip_capacity
|
||||
+ self.right_main_capacity
|
||||
+ self.right_aux_capacity
|
||||
+ self.right_tip_capacity
|
||||
+ self.external1_capacity
|
||||
+ self.external2_capacity
|
||||
}
|
||||
}
|
||||
|
||||
impl core::fmt::Display for Fuel {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let percent = (100.0 / self.total_capacity()) * self.total_quantity();
|
||||
|
||||
write!(
|
||||
f,
|
||||
"{}GL/{}GL ({}%)",
|
||||
self.total_quantity(),
|
||||
self.total_capacity(),
|
||||
percent
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Display, Deserialize, Serialize)]
|
||||
#[display("{lat}, {lon} at {alt}ft")]
|
||||
pub struct Gps {
|
||||
pub lat: f64,
|
||||
pub lon: f64,
|
||||
pub alt: f64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Display, Deserialize, Serialize)]
|
||||
pub struct OnGround {
|
||||
pub sim_on_ground: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Display, Deserialize, Serialize)]
|
||||
pub struct IsParked {
|
||||
pub is_parked: bool,
|
||||
}
|
||||
|
||||
// #[derive(Debug, Display, Clone, Deserialize, Serialize)]
|
||||
// #[display("[{icao}] {lat} {lon} {alt}")]
|
||||
// pub struct Airport {
|
||||
// pub icao: String,
|
||||
// pub region: String,
|
||||
// pub lat: f64,
|
||||
// pub lon: f64,
|
||||
// pub alt: f64,
|
||||
// }
|
||||
|
||||
impl PartialEq for SimConnectPacket {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
matches!(
|
||||
(self, other),
|
||||
(Self::AtcID(_), Self::AtcID(_)) | (Self::Fuel(_), Self::Fuel(_))
|
||||
)
|
||||
}
|
||||
}
|
||||
impl Eq for SimConnectPacket {}
|
||||
|
||||
#[derive(Debug, Display, Clone, PartialEq, Eq, Deserialize, Serialize)]
|
||||
pub enum Packets {
|
||||
System(SystemPacket),
|
||||
SimConnect(SimConnectPacket),
|
||||
|
2
migrations/20241027203520_airport.down.sql
Normal file
2
migrations/20241027203520_airport.down.sql
Normal file
@@ -0,0 +1,2 @@
|
||||
-- Add down migration script here
|
||||
DROP TABLE "airports";
|
42844
migrations/20241027203520_airport.up.sql
Normal file
42844
migrations/20241027203520_airport.up.sql
Normal file
File diff suppressed because it is too large
Load Diff
3
migrations/20241028150902_aircraft.down.sql
Normal file
3
migrations/20241028150902_aircraft.down.sql
Normal file
@@ -0,0 +1,3 @@
|
||||
-- Add down migration script here
|
||||
DROP TABLE "ower_history";
|
||||
DROP TABLE "aircrafts";
|
66
migrations/20241028150902_aircraft.up.sql
Normal file
66
migrations/20241028150902_aircraft.up.sql
Normal file
@@ -0,0 +1,66 @@
|
||||
-- Add up migration script here
|
||||
CREATE TABLE "aircrafts" (
|
||||
"id" uuid NOT NULL,
|
||||
"registration" text NOT NULL,
|
||||
"category" text NOT NULL,
|
||||
|
||||
"manufacturer" text NOT NULL,
|
||||
"model" text NOT NULL,
|
||||
|
||||
"on_ground" boolean NOT NULL DEFAULT 1,
|
||||
|
||||
"created_at" timestamp DEFAULT CURRENT_TIMESTAMP,
|
||||
"updated_at" timestamp DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "aircrafts_pkey" PRIMARY KEY ("id"),
|
||||
CONSTRAINT "aircrafts_registration_unique" UNIQUE ("registration")
|
||||
) WITH (oids = false);
|
||||
|
||||
CREATE TABLE "gps" (
|
||||
"aircraft_id" uuid NOT NULL,
|
||||
|
||||
"latitude_deg" numeric NOT NULL,
|
||||
"longitude_deg" numeric NOT NULL,
|
||||
"elevation_ft" numeric NOT NULL,
|
||||
|
||||
"created_at" timestamp DEFAULT CURRENT_TIMESTAMP,
|
||||
"updated_at" timestamp DEFAULT CURRENT_TIMESTAMP,
|
||||
CONSTRAINT "gps_pkey" PRIMARY KEY ("aircraft_id")
|
||||
)
|
||||
|
||||
CREATE TABLE "fuel" (
|
||||
"aircraft_id" uuid NOT NULL,
|
||||
"center_quantity" numeric,
|
||||
"center_capacity" numeric,
|
||||
"center2_quantity" numeric,
|
||||
"center2_capacity" numeric,
|
||||
"center3_quantity" numeric,
|
||||
"center3_capacity" numeric,
|
||||
"left_main_quantity" numeric,
|
||||
"left_main_capacity" numeric,
|
||||
"left_aux_quantity" numeric,
|
||||
"left_aux_capacity" numeric,
|
||||
"left_tip_quantity" numeric,
|
||||
"left_tip_capacity" numeric,
|
||||
"right_main_quantity" numeric,
|
||||
"right_main_capacity" numeric,
|
||||
"right_aux_quantity" numeric,
|
||||
"right_aux_capacity" numeric,
|
||||
"right_tip_quantity" numeric,
|
||||
"right_tip_capacity" numeric,
|
||||
"external1_quantity" numeric,
|
||||
"external1_capacity" numeric,
|
||||
"external2_quantity" numeric,
|
||||
"external2_capacity" numeric,
|
||||
"fuel_weight" numeric,
|
||||
|
||||
"created_at" timestamp DEFAULT CURRENT_TIMESTAMP,
|
||||
"updated_at" timestamp DEFAULT CURRENT_TIMESTAMP,
|
||||
CONSTRAINT "fuel_pkey" PRIMARY KEY ("aircraft_id")
|
||||
)
|
||||
|
||||
-- If a player is in an aircraft that doesnt exist on our end, ask them to "purchace" it from the factory
|
||||
-- What's the pricing going to look like though... hmm
|
||||
|
||||
-- If a pilot buys a new aircraft they need to get in it at least once to get all the fuel-cell data, we don't know beforehand how many tanks it has
|
||||
-- after updating, the capacity should be > 0 to indicate which ones are used
|
2
migrations/20241028214336_pilot.down.sql
Normal file
2
migrations/20241028214336_pilot.down.sql
Normal file
@@ -0,0 +1,2 @@
|
||||
-- Add down migration script here
|
||||
DROP TABLE "pilots";
|
25
migrations/20241028214336_pilot.up.sql
Normal file
25
migrations/20241028214336_pilot.up.sql
Normal file
@@ -0,0 +1,25 @@
|
||||
-- Add up migration script here
|
||||
CREATE TABLE "pilots" (
|
||||
"id" uuid NOT NULL, -- use the random-person-generator's id?
|
||||
"user_id" uuid NOT NULL,
|
||||
|
||||
"full_name" text NOT NULL,
|
||||
"date_of_birth" timestamp NOT NULL,
|
||||
"gender" text NOT NULL,
|
||||
"nationality" text NOT NULL,
|
||||
"photo" text NOT NULL, -- base64 encoded image from RPG?
|
||||
|
||||
-- Pilot also needs to keep track of career progress
|
||||
-- Flight lessons etc?
|
||||
|
||||
-- current location, i think we can use lat/lon to infer an airport location
|
||||
"latitude_deg" numeric NOT NULL,
|
||||
"longitude_deg" numeric NOT NULL,
|
||||
|
||||
CONSTRAINT "pilots_pkey" PRIMARY KEY ("id")
|
||||
) WITH (oids = false);
|
||||
|
||||
-- Creating a new pilot from the following inputs:
|
||||
-- Age (will determine year, but pick a random date) - depending if the RPG's API supports this
|
||||
-- Gender
|
||||
-- Nationality
|
4
migrations/20241028221013_pivot_tables.down.sql
Normal file
4
migrations/20241028221013_pivot_tables.down.sql
Normal file
@@ -0,0 +1,4 @@
|
||||
-- Add down migration script here
|
||||
DROP TABLE "owner_history";
|
||||
DROP TABLE "pilot_aircraft";
|
||||
DROP TABLE "flight_log";
|
31
migrations/20241028221013_pivot_tables.up.sql
Normal file
31
migrations/20241028221013_pivot_tables.up.sql
Normal file
@@ -0,0 +1,31 @@
|
||||
-- Add up migration script here
|
||||
|
||||
CREATE TABLE "owner_history" (
|
||||
"id" BIGSERIAL NOT NULL,
|
||||
"aircraft_id" BIGSERIAL NOT NULL,
|
||||
"pilot_id" uuid NOT NULL,
|
||||
"since" timestamp DEFAULT CURRENT_TIMESTAMP,
|
||||
CONSTRAINT "owner_history_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- Pilot currently occupying/flying aircraft
|
||||
CREATE TABLE "pilot_current_aircraft" (
|
||||
"pilot_id" uuid NOT NULL,
|
||||
"aircraft_id" uuid NOT NULL,
|
||||
CONSTRAINT "pilot_aircraft_pkey" PRIMARY KEY ("pilot_id", "aircraft_id"),
|
||||
) WITH (oids = false);
|
||||
|
||||
CREATE TABLE "flight_log" (
|
||||
"id" BIGSERIAL NOT NULL,
|
||||
"pilot_id" uuid NOT NULL,
|
||||
"aircraft_id" uuid NOT NULL,
|
||||
"takeoff_time" timestamp DEFAULT CURRENT_TIMESTAMP,
|
||||
"takeoff_latitude_deg" NUMERIC NOT NULL,
|
||||
"takeoff_longitude_deg" NUMERIC NOT NULL,
|
||||
"takeoff_elevation_ft" NUMERIC NOT NULL DEFAULT 0,
|
||||
"landing" timestamp,
|
||||
"landing_latitude_deg" NUMERIC NOT NULL,
|
||||
"landing_longitude_deg" NUMERIC NOT NULL,
|
||||
"landing_elevation_ft" NUMERIC NOT NULL DEFAULT 0,
|
||||
CONSTRAINT "flight_log_pkey" PRIMARY KEY ("id")
|
||||
);
|
13
parser/Cargo.toml
Normal file
13
parser/Cargo.toml
Normal file
@@ -0,0 +1,13 @@
|
||||
[package]
|
||||
name = "parser"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.91"
|
||||
csv = "1.3.0"
|
||||
ctrlc = "3.4.5"
|
||||
serde = { version = "1.0.213", features = ["derive"] }
|
||||
simconnect-sdk = { path = "D:/source/MSFS/simconnect-sdk-rs/simconnect-sdk", features = [
|
||||
"derive",
|
||||
] }
|
28
parser/src/ctrl_c.rs
Normal file
28
parser/src/ctrl_c.rs
Normal file
@@ -0,0 +1,28 @@
|
||||
use std::sync::{
|
||||
atomic::{AtomicU8, Ordering},
|
||||
Arc,
|
||||
};
|
||||
|
||||
pub struct CtrlC {
|
||||
counter: Arc<AtomicU8>,
|
||||
}
|
||||
|
||||
impl CtrlC {
|
||||
pub fn new() -> Self {
|
||||
let counter: Arc<AtomicU8> = Default::default();
|
||||
let c = counter.clone();
|
||||
ctrlc::set_handler(move || {
|
||||
c.fetch_add(1, Ordering::SeqCst);
|
||||
if c.load(Ordering::SeqCst) >= 3 {
|
||||
std::process::exit(1);
|
||||
}
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
Self { counter }
|
||||
}
|
||||
|
||||
pub fn count(&self) -> u8 {
|
||||
self.counter.load(Ordering::SeqCst)
|
||||
}
|
||||
}
|
153
parser/src/main.rs
Normal file
153
parser/src/main.rs
Normal file
@@ -0,0 +1,153 @@
|
||||
mod ctrl_c;
|
||||
|
||||
use ctrl_c::CtrlC;
|
||||
use std::{fs, io::Write, thread::sleep, time::Duration};
|
||||
|
||||
use serde::Deserialize;
|
||||
use simconnect_sdk::{Notification, SimConnect, SystemEventRequest};
|
||||
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
struct Airport {
|
||||
id: usize,
|
||||
ident: String,
|
||||
#[serde(rename = "type")]
|
||||
airport_type: String,
|
||||
name: String,
|
||||
latitude_deg: f64,
|
||||
longitude_deg: f64,
|
||||
elevation_ft: Option<i32>,
|
||||
continent: String,
|
||||
iso_country: String,
|
||||
iso_region: String,
|
||||
municipality: String,
|
||||
scheduled_service: String,
|
||||
gps_code: String,
|
||||
iata_code: String,
|
||||
local_code: String,
|
||||
home_link: String,
|
||||
wikipedia_link: String,
|
||||
keywords: String,
|
||||
}
|
||||
|
||||
// cross reference ICAOs with data from the sim
|
||||
|
||||
fn main() -> Result<(), anyhow::Error> {
|
||||
let Ok(mut simconnect) = SimConnect::new("Airport Crawler") else {
|
||||
panic!("Game not running, gotta wait for it here");
|
||||
};
|
||||
|
||||
let mut csv = csv::ReaderBuilder::new()
|
||||
.has_headers(true)
|
||||
.delimiter(b',')
|
||||
.trim(csv::Trim::All)
|
||||
.from_path("./airports.csv")?;
|
||||
|
||||
let airports = csv.deserialize::<Airport>().flatten().collect::<Vec<_>>();
|
||||
|
||||
let mut list = vec![];
|
||||
|
||||
let ctrl_c = CtrlC::new();
|
||||
|
||||
loop {
|
||||
if ctrl_c.count() > 0 {
|
||||
break;
|
||||
}
|
||||
|
||||
if let Ok(Some(event)) = simconnect.get_next_dispatch() {
|
||||
match event {
|
||||
Notification::Open => {
|
||||
// simconnect.subscribe_to_system_event(SystemEventRequest::FlightLoaded)?;
|
||||
simconnect.request_facilities_list(simconnect_sdk::FacilityType::Airport)?;
|
||||
}
|
||||
Notification::AirportList(vec) => {
|
||||
for a in &vec {
|
||||
let Some(ap) = airports
|
||||
.iter()
|
||||
.find(|e| e.ident.to_lowercase() == a.ident.to_lowercase())
|
||||
else {
|
||||
let Some(ap) = airports
|
||||
.iter()
|
||||
.find(|e| e.local_code.to_lowercase() == a.ident.to_lowercase())
|
||||
else {
|
||||
// eprintln!("{} not found in as ident nor local_code", a.ident.to_lowercase());
|
||||
list.push(Airport {
|
||||
id: 0,
|
||||
ident: a.ident.clone(),
|
||||
airport_type: "N/A".to_string(),
|
||||
name: "N/A".to_string(),
|
||||
latitude_deg: a.lat,
|
||||
longitude_deg: a.lon,
|
||||
elevation_ft: Some(a.alt.round() as i32),
|
||||
continent: "N/A".to_string(),
|
||||
iso_country: "N/A".to_string(),
|
||||
iso_region: "N/A".to_string(),
|
||||
municipality: "N/A".to_string(),
|
||||
scheduled_service: "N/A".to_string(),
|
||||
gps_code: "N/A".to_string(),
|
||||
iata_code: "N/A".to_string(),
|
||||
local_code: "N/A".to_string(),
|
||||
home_link: "N/A".to_string(),
|
||||
wikipedia_link: "N/A".to_string(),
|
||||
keywords: "N/A".to_string(),
|
||||
});
|
||||
|
||||
continue;
|
||||
};
|
||||
let mut ap = ap.to_owned();
|
||||
ap.ident = ap.local_code.clone();
|
||||
|
||||
list.push(ap);
|
||||
continue;
|
||||
};
|
||||
list.push(ap.to_owned());
|
||||
}
|
||||
|
||||
dbg!(&vec.len());
|
||||
}
|
||||
Notification::Quit => break,
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
sleep(Duration::from_millis(16));
|
||||
}
|
||||
|
||||
let mut writer = fs::File::create("./airports.sql")?;
|
||||
let mut string_builder = String::new();
|
||||
let mut i = 0;
|
||||
string_builder += "INSERT INTO airports ( ident, airport_type, name, latitude_deg, longitude_deg, elevation_ft, iso_country, iso_region, municipality, scheduled_service, gps_code, iata_code, local_code, keywords ) VALUES\n";
|
||||
|
||||
for airport in list {
|
||||
string_builder += &format!(
|
||||
"\t('{}', '{}', '{}', {}, {}, {}, '{}', '{}', '{}', '{}', '{}', '{}', '{}', '{}')",
|
||||
airport.ident.replace('\'', "''"),
|
||||
airport.airport_type.replace('\'', "''"),
|
||||
airport.name.replace('\'', "''"),
|
||||
airport.latitude_deg,
|
||||
airport.longitude_deg,
|
||||
airport.elevation_ft.unwrap_or(0),
|
||||
airport.iso_country.replace('\'', "''"),
|
||||
airport.iso_region.replace('\'', "''"),
|
||||
airport.municipality.replace('\'', "''"),
|
||||
airport.scheduled_service.replace('\'', "''"),
|
||||
airport.gps_code.replace('\'', "''"),
|
||||
airport.iata_code.replace('\'', "''"),
|
||||
airport.local_code.replace('\'', "''"),
|
||||
airport.keywords.replace('\'', "''"),
|
||||
);
|
||||
|
||||
if i == 50 {
|
||||
i = 0;
|
||||
string_builder += ";\n\nINSERT INTO airports ( ident, airport_type, name, latitude_deg, longitude_deg, elevation_ft, iso_country, iso_region, municipality, scheduled_service, gps_code, iata_code, local_code, keywords ) VALUES\n";
|
||||
|
||||
continue;
|
||||
} else {
|
||||
string_builder += ",\n";
|
||||
}
|
||||
|
||||
i += 1;
|
||||
}
|
||||
|
||||
writer.write_all(string_builder.as_bytes())?;
|
||||
|
||||
Ok(())
|
||||
}
|
@@ -9,6 +9,7 @@ const SMTP_USERNAME: &str = "SMTP_USERNAME";
|
||||
const SMTP_PASSWORD: &str = "SMTP_PASSWORD";
|
||||
const SMTP_SENDER: &str = "SMTP_SENDER";
|
||||
const JWT_SECRET: &str = "JWT_SECRET";
|
||||
const HASH_ID: &str = "HASH_ID";
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct Config {
|
||||
@@ -21,6 +22,7 @@ pub struct Config {
|
||||
pub smtp_sender: String,
|
||||
|
||||
pub jwt_secret: String,
|
||||
pub hash_id: String,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
@@ -32,6 +34,7 @@ impl Config {
|
||||
let smtp_password = load_env(SMTP_PASSWORD)?;
|
||||
let smtp_sender = load_env(SMTP_SENDER)?;
|
||||
let jwt_secret = load_env(JWT_SECRET)?;
|
||||
let hash_id = load_env(HASH_ID)?;
|
||||
|
||||
Ok(Config {
|
||||
database_url,
|
||||
@@ -41,6 +44,7 @@ impl Config {
|
||||
smtp_password,
|
||||
smtp_sender,
|
||||
jwt_secret,
|
||||
hash_id,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@@ -23,12 +23,16 @@ pub mod prelude {
|
||||
pub use super::ports::*;
|
||||
pub use super::service::*;
|
||||
|
||||
pub use crate::domain::leptos::check_user;
|
||||
|
||||
pub use crate::domain::leptos::flashbag::Alert;
|
||||
pub use crate::domain::leptos::flashbag::Flash;
|
||||
pub use crate::domain::leptos::flashbag::FlashBag;
|
||||
pub use crate::domain::leptos::flashbag::FlashMessage;
|
||||
|
||||
pub use axum_session::SessionAnySession as Session;
|
||||
|
||||
pub use avam_protocol::*;
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "ssr"))]
|
||||
|
32
src/lib/domain/api/models/aircraft.rs
Normal file
32
src/lib/domain/api/models/aircraft.rs
Normal file
@@ -0,0 +1,32 @@
|
||||
// max limit: 1.336.335
|
||||
|
||||
// Ok so i kinda wanna go all out on this one
|
||||
|
||||
// The basic things like
|
||||
// Aircraft Manufacturer
|
||||
// Aircraft Type
|
||||
// Registration Number (up to 1.336.335, generated with auto incremented ids and hash_id)
|
||||
// - Custom registration nr should be possible, "auto" increment will be a manual thing, check if it exists, if so, skip
|
||||
// Build date
|
||||
|
||||
// Usage things
|
||||
// Current fuel level in all possible tanks
|
||||
// Current location and altitude
|
||||
// Passangers and Cargo
|
||||
|
||||
// But also Logs
|
||||
// Owner history
|
||||
// Flight Logs which contains weights and balances, to and from etc
|
||||
// Crashes and maintanance logs
|
||||
|
||||
// Most of these things can and will be automated / generated without the need for user input
|
||||
// Maybe maintanance can be a thing where a plane can't be used for x time
|
||||
|
||||
// -----------------------
|
||||
|
||||
// The thing we actually need first is a factory
|
||||
// Using the webinterface, we actually need to go to a factory to build us a new aircraft
|
||||
|
||||
// Hangars
|
||||
// Hangars are on airports
|
||||
// so we need those too
|
@@ -1,3 +1,6 @@
|
||||
use avam_protocol::Packets;
|
||||
use tokio::sync::mpsc::Sender;
|
||||
|
||||
use crate::{
|
||||
domain::api::models::oauth::*,
|
||||
inbound::http::handlers::oauth::{AuthorizationCodeRequest, VerifyClientAuthorizationRequest},
|
||||
@@ -7,6 +10,21 @@ use super::super::models::user::*;
|
||||
use std::future::Future;
|
||||
|
||||
pub trait ApiService: Clone + Send + Sync + 'static {
|
||||
// -- -
|
||||
// Websocket
|
||||
// ---
|
||||
fn add_connection(&self, user: &User, sender: Sender<Packets>);
|
||||
|
||||
fn has_connection(&self, user: &User) -> bool;
|
||||
|
||||
fn remove_connection(&self, user: &User);
|
||||
|
||||
fn send(
|
||||
&self,
|
||||
user: &User,
|
||||
packet: Packets,
|
||||
) -> impl Future<Output = Result<(), anyhow::Error>> + Send;
|
||||
|
||||
// ---
|
||||
// USER
|
||||
// ---
|
||||
|
@@ -2,7 +2,10 @@
|
||||
Module `service` provides the canonical implementation of the [ApiService] port. All
|
||||
user-domain logic is defined here.
|
||||
*/
|
||||
use avam_protocol::Packets;
|
||||
use axum_session::SessionAnySession;
|
||||
use dashmap::DashMap;
|
||||
use tokio::sync::mpsc::Sender;
|
||||
|
||||
use crate::inbound::http::handlers::oauth::AuthorizationCodeRequest;
|
||||
use crate::inbound::http::handlers::oauth::GrantType;
|
||||
@@ -25,6 +28,7 @@ where
|
||||
{
|
||||
repo: R,
|
||||
notifier: N,
|
||||
connections: DashMap<uuid::Uuid, Sender<Packets>>,
|
||||
}
|
||||
|
||||
impl<R, N> Service<R, N>
|
||||
@@ -33,7 +37,11 @@ where
|
||||
N: Email,
|
||||
{
|
||||
pub fn new(repo: R, notifier: N) -> Self {
|
||||
Self { repo, notifier }
|
||||
Self {
|
||||
repo,
|
||||
notifier,
|
||||
connections: DashMap::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +50,25 @@ where
|
||||
R: UserRepository + OAuthRepository,
|
||||
N: Email,
|
||||
{
|
||||
fn add_connection(&self, user: &User, sender: Sender<Packets>) {
|
||||
self.connections.insert(user.id(), sender);
|
||||
}
|
||||
|
||||
fn has_connection(&self, user: &User) -> bool {
|
||||
self.connections.contains_key(&user.id())
|
||||
}
|
||||
|
||||
fn remove_connection(&self, user: &User) {
|
||||
self.connections.remove(&user.id());
|
||||
}
|
||||
|
||||
async fn send(&self, user: &User, packet: Packets) -> Result<(), anyhow::Error> {
|
||||
if let Some(sender) = self.connections.get(&user.id()) {
|
||||
sender.send(packet).await?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn create_user(&self, req: CreateUserRequest) -> Result<User, CreateUserError> {
|
||||
let result = self.repo.create_user(req).await;
|
||||
|
||||
|
@@ -1,46 +1,54 @@
|
||||
use leptos::*;
|
||||
use leptos_router::ActionForm;
|
||||
|
||||
use crate::domain::api::prelude::User;
|
||||
use crate::domain::api::prelude::*;
|
||||
#[server]
|
||||
async fn login_action(ident: String) -> Result<(), ServerFnError<String>> {
|
||||
use crate::domain::api::prelude::*;
|
||||
|
||||
if ident.len() > 10 {
|
||||
return Err(ServerFnError::WrappedServerError(
|
||||
"ATC_ID exceeding 10 characters".into(),
|
||||
));
|
||||
}
|
||||
|
||||
let Some(user) = check_user().await? else {
|
||||
return Err(ServerFnError::WrappedServerError("No user".into()));
|
||||
};
|
||||
|
||||
let app = use_context::<AppService>().unwrap();
|
||||
|
||||
app.send(&user, Packets::SimConnect(SimConnectPacket::AtcID(ident)))
|
||||
.await
|
||||
.map_err(|e| format!("{:#?}", e))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Renders the home page of your application.
|
||||
#[component]
|
||||
pub fn DashboardPage(user: User) -> impl IntoView {
|
||||
let submit = Action::<LoginAction, _>::server();
|
||||
// let response = submit.value().read_only();
|
||||
|
||||
view! {
|
||||
<section class="login is-fullheight">
|
||||
<div class="columns is-fullheight">
|
||||
<div class="column is-one-third-fullhd is-half-widescreen">
|
||||
<div class="login_container">
|
||||
<div style="margin: auto 0">
|
||||
<div class="has-text-centered">
|
||||
<img src="/android-chrome-192x192.png" alt={ crate::PROJECT_NAME }/>
|
||||
</div>
|
||||
|
||||
<pre>Hello, { user.email().to_string() }!</pre>
|
||||
<div class="content has-text-centered">
|
||||
<a href="/auth/logout">Logout</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<footer>
|
||||
<div class="content has-text-centered">
|
||||
<p>
|
||||
{ crate::PROJECT_NAME }
|
||||
</p>
|
||||
<p>
|
||||
<span class="icon"><a href="https://git.avii.nl/AVAM/avam" class="is-link" target="_BLANK"><i class="fab fa-git-alt"></i></a></span>
|
||||
<span class="icon"><a href="#" class="is-link" target="_BLANK"><i class="fab fa-discord"></i></a></span>
|
||||
</p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="column is-fullheight background is-hidden-mobile has-background-primary has-text-primary-invert">
|
||||
</div>
|
||||
<div class="p-10">
|
||||
<pre>Hello, { user.email().to_string() }!</pre>
|
||||
<div class="content has-text-centered link">
|
||||
<a href="/auth/logout">Logout</a>
|
||||
</div>
|
||||
</section>
|
||||
}.into_view()
|
||||
<div>
|
||||
<ActionForm action=submit>
|
||||
<label class="input input-bordered flex items-center gap-2">
|
||||
<i class="fas fa-envelope"></i>
|
||||
<input type="text" placeholder="Registration Number" maxlength="10" name="ident" />
|
||||
</label>
|
||||
<div>
|
||||
<input type="submit" value="Update" class="btn btn-block" />
|
||||
</div>
|
||||
</ActionForm>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
.into_view()
|
||||
}
|
||||
|
@@ -19,6 +19,7 @@ use tokio::{
|
||||
sync::mpsc,
|
||||
time::{sleep, Instant},
|
||||
};
|
||||
use tracing::info;
|
||||
|
||||
use crate::{
|
||||
domain::api::{
|
||||
@@ -39,10 +40,14 @@ pub async fn ws_handler<S: ApiService>(
|
||||
) -> Result<impl IntoResponse, StatusCode> {
|
||||
let auth_token = match auth_token {
|
||||
Some(TypedHeader(token)) => Some(token.token().to_string()),
|
||||
None => return Err(StatusCode::UNAUTHORIZED),
|
||||
None => {
|
||||
tracing::error!("No Authorization Header Supplied");
|
||||
return Err(StatusCode::UNAUTHORIZED);
|
||||
}
|
||||
};
|
||||
|
||||
let Some(auth_token) = auth_token else {
|
||||
tracing::error!("No Token Supplied");
|
||||
return Err(StatusCode::UNAUTHORIZED);
|
||||
};
|
||||
|
||||
@@ -72,10 +77,11 @@ pub async fn ws_handler<S: ApiService>(
|
||||
.verify_client_authorization(VerifyClientAuthorizationRequest::new(user_id, client_id))
|
||||
.await
|
||||
else {
|
||||
tracing::error!("Client {} not authorized by {}", client_id, user_id);
|
||||
return Err(StatusCode::UNAUTHORIZED);
|
||||
};
|
||||
|
||||
if app_state.has_connection(&user).await {
|
||||
if app_state.api_service().has_connection(&user) {
|
||||
return Err(StatusCode::CONFLICT);
|
||||
}
|
||||
|
||||
@@ -93,7 +99,7 @@ async fn handle_socket<S: ApiService>(
|
||||
// It'd know who's connected at all times and be able to send messages
|
||||
|
||||
let (sender, mut receiver) = mpsc::channel(10);
|
||||
app_state.add_connection(&user, sender).await;
|
||||
app_state.api_service().add_connection(&user, sender);
|
||||
|
||||
// This can probably be hella-abstracted away and be made a lot cleaner
|
||||
let (mut writer, mut reader) = socket.split();
|
||||
@@ -175,11 +181,12 @@ async fn handle_socket<S: ApiService>(
|
||||
};
|
||||
|
||||
// remove the user/channel from AppState
|
||||
app_state.remove_connection(&user).await;
|
||||
app_state.api_service().remove_connection(&user);
|
||||
|
||||
// returning from the handler closes the websocket connection
|
||||
tracing::debug!("Websocket context {who} destroyed");
|
||||
}
|
||||
|
||||
async fn process_system_packet<S>(
|
||||
app_state: AppState<S>,
|
||||
user: &User,
|
||||
@@ -193,6 +200,7 @@ where
|
||||
SystemPacket::Ping => {
|
||||
// send back pong
|
||||
let _ = app_state
|
||||
.api_service()
|
||||
.send(user, Packets::System(SystemPacket::Pong))
|
||||
.await;
|
||||
}
|
||||
@@ -216,7 +224,24 @@ async fn process_message<S>(
|
||||
where
|
||||
S: ApiService,
|
||||
{
|
||||
tracing::info!("< [{}]: {:?}", user.email(), packet);
|
||||
// This needs to be abstracted away from here like actually
|
||||
match packet {
|
||||
SimConnectPacket::AtcID(id) => info!("[{}] Registration to {}", user.email(), id),
|
||||
SimConnectPacket::Fuel(fuel) => info!("[{}] Fuel state: {}", user.email(), fuel),
|
||||
SimConnectPacket::Airplane(airplane) => info!("[{}] Airplane: {}", user.email(), airplane),
|
||||
SimConnectPacket::Gps(gps) => info!("[{}] Location: {}", user.email(), gps),
|
||||
SimConnectPacket::OnGround(on_ground) => {
|
||||
info!("[{}] On Ground: {}", user.email(), on_ground)
|
||||
}
|
||||
SimConnectPacket::IsParked(is_parked) => {
|
||||
info!("[{}] Is Parked: {}", user.email(), is_parked)
|
||||
}
|
||||
}
|
||||
|
||||
// The airplane variant checks if the player is in the correct airplane for the selected job etc
|
||||
// Send error if not and don't handle the flight
|
||||
|
||||
// tracing::info!("< [{}]: {:?}", user.email(), packet);
|
||||
|
||||
// On incoming packets, we use the internal api to store stuff to the database
|
||||
// We'll use Server Side Events (SSE) to keep the dashboard up to date with the state of the database
|
||||
|
@@ -1,14 +1,9 @@
|
||||
use std::{collections::HashMap, sync::Arc};
|
||||
use std::sync::Arc;
|
||||
|
||||
use avam_protocol::Packets;
|
||||
use axum::extract::FromRef;
|
||||
use leptos::get_configuration;
|
||||
use tokio::sync::{mpsc::Sender, RwLock};
|
||||
|
||||
use crate::{
|
||||
config::Config,
|
||||
domain::api::{ports::ApiService, prelude::User},
|
||||
};
|
||||
use crate::{config::Config, domain::api::ports::ApiService};
|
||||
|
||||
#[derive(Clone)]
|
||||
/// The global application state shared between all request handlers.
|
||||
@@ -19,7 +14,6 @@ where
|
||||
pub leptos_options: leptos::LeptosOptions,
|
||||
config: Arc<Config>,
|
||||
api_service: Arc<S>,
|
||||
connections: Arc<RwLock<HashMap<uuid::Uuid, Sender<Packets>>>>,
|
||||
}
|
||||
|
||||
impl<S> AppState<S>
|
||||
@@ -31,7 +25,6 @@ where
|
||||
config: Arc::new(config),
|
||||
leptos_options: get_configuration(None).await.unwrap().leptos_options,
|
||||
api_service: Arc::new(api_service),
|
||||
connections: Arc::new(RwLock::new(HashMap::new())),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,30 +37,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> AppState<S>
|
||||
where
|
||||
S: ApiService,
|
||||
{
|
||||
pub async fn add_connection(&self, user: &User, sender: Sender<Packets>) {
|
||||
self.connections.write().await.insert(user.id(), sender);
|
||||
}
|
||||
|
||||
pub async fn has_connection(&self, user: &User) -> bool {
|
||||
self.connections.read().await.contains_key(&user.id())
|
||||
}
|
||||
|
||||
pub async fn remove_connection(&self, user: &User) {
|
||||
self.connections.write().await.remove(&user.id());
|
||||
}
|
||||
|
||||
pub async fn send(&self, user: &User, packet: Packets) -> Result<(), anyhow::Error> {
|
||||
if let Some(sender) = self.connections.read().await.get(&user.id()) {
|
||||
sender.send(packet).await?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> FromRef<AppState<S>> for leptos::LeptosOptions
|
||||
where
|
||||
S: ApiService,
|
||||
|
@@ -968,34 +968,6 @@ html {
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
display: grid;
|
||||
width: 100%;
|
||||
grid-auto-flow: row;
|
||||
place-items: start;
|
||||
-moz-column-gap: 1rem;
|
||||
column-gap: 1rem;
|
||||
row-gap: 2.5rem;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.25rem;
|
||||
}
|
||||
|
||||
.footer > * {
|
||||
display: grid;
|
||||
place-items: start;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
@media (min-width: 48rem) {
|
||||
.footer {
|
||||
grid-auto-flow: column;
|
||||
}
|
||||
|
||||
.footer-center {
|
||||
grid-auto-flow: row dense;
|
||||
}
|
||||
}
|
||||
|
||||
.label {
|
||||
display: flex;
|
||||
-webkit-user-select: none;
|
||||
@@ -1448,10 +1420,6 @@ html {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.contents {
|
||||
display: contents;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
@@ -1504,6 +1472,10 @@ html {
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
.p-10 {
|
||||
padding: 2.5rem;
|
||||
}
|
||||
|
||||
.px-1 {
|
||||
padding-left: 0.25rem;
|
||||
padding-right: 0.25rem;
|
||||
|
Reference in New Issue
Block a user