v0.0.1 Proof of Concept for PDR (#6)

Communication between world server (Unity) and external test device (SoC) proven, as shown in logs.

Still TODO:
- [ ] REST endpoint to export data [likely going to be a unique repo]
- [ ] VDMA for image processing

Reviewed-on: #6
Reviewed-by: Isaacsouthwell <ias4117@rit.edu>
Co-authored-by: Blizzard Finnegan <blizzardfinnegan@gmail.com>
Co-committed-by: Blizzard Finnegan <blizzardfinnegan@gmail.com>
This commit is contained in:
Blizzard Finnegan 2024-03-29 11:13:12 -04:00 committed by Isaacsouthwell
parent cc8d347486
commit 61a94a14cd
9 changed files with 920 additions and 4 deletions

4
.gitignore vendored
View file

@ -1 +1,3 @@
/target
target/
logs/
test.png

627
Cargo.lock generated
View file

@ -2,6 +2,633 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "adler"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "android-tzdata"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
[[package]]
name = "android_system_properties"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
dependencies = [
"libc",
]
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bumpalo"
version = "3.15.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa"
[[package]]
name = "bytemuck"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d6d68c57235a3a081186990eca2867354726650f42f7516ca50c28d6281fd15"
[[package]]
name = "byteorder"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "cc"
version = "1.0.90"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chrono"
version = "0.4.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8eaf5903dcbc0a39312feb77df2ff4c76387d591b9fc7b04a238dcf8bb62639a"
dependencies = [
"android-tzdata",
"iana-time-zone",
"js-sys",
"num-traits",
"wasm-bindgen",
"windows-targets 0.52.4",
]
[[package]]
name = "color_quant"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
[[package]]
name = "communication-layer"
version = "0.1.0"
dependencies = [
"chrono",
"fern",
"image",
"ipnet",
"local-ip-address",
"log",
"rand",
]
[[package]]
name = "core-foundation-sys"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
[[package]]
name = "crc32fast"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa"
dependencies = [
"cfg-if",
]
[[package]]
name = "either"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a"
[[package]]
name = "fdeflate"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4f9bfee30e4dedf0ab8b422f03af778d9612b63f502710fc500a334ebe2de645"
dependencies = [
"simd-adler32",
]
[[package]]
name = "fern"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9f0c14694cbd524c8720dd69b0e3179344f04ebb5f90f2e4a440c6ea3b2f1ee"
dependencies = [
"log",
]
[[package]]
name = "flate2"
version = "1.0.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e"
dependencies = [
"crc32fast",
"miniz_oxide",
]
[[package]]
name = "getrandom"
version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "gif"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fb2d69b19215e18bb912fa30f7ce15846e301408695e44e0ef719f1da9e19f2"
dependencies = [
"color_quant",
"weezl",
]
[[package]]
name = "iana-time-zone"
version = "0.1.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141"
dependencies = [
"android_system_properties",
"core-foundation-sys",
"iana-time-zone-haiku",
"js-sys",
"wasm-bindgen",
"windows-core",
]
[[package]]
name = "iana-time-zone-haiku"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
dependencies = [
"cc",
]
[[package]]
name = "image"
version = "0.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9b4f005360d32e9325029b38ba47ebd7a56f3316df09249368939562d518645"
dependencies = [
"bytemuck",
"byteorder",
"color_quant",
"gif",
"num-traits",
"png",
]
[[package]]
name = "ipnet"
version = "2.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3"
[[package]]
name = "js-sys"
version = "0.3.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d"
dependencies = [
"wasm-bindgen",
]
[[package]]
name = "libc"
version = "0.2.153"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
[[package]]
name = "local-ip-address"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "136ef34e18462b17bf39a7826f8f3bbc223341f8e83822beb8b77db9a3d49696"
dependencies = [
"libc",
"neli",
"thiserror",
"windows-sys",
]
[[package]]
name = "log"
version = "0.4.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
[[package]]
name = "miniz_oxide"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7"
dependencies = [
"adler",
"simd-adler32",
]
[[package]]
name = "neli"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1100229e06604150b3becd61a4965d5c70f3be1759544ea7274166f4be41ef43"
dependencies = [
"byteorder",
"libc",
"log",
"neli-proc-macros",
]
[[package]]
name = "neli-proc-macros"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c168194d373b1e134786274020dae7fc5513d565ea2ebb9bc9ff17ffb69106d4"
dependencies = [
"either",
"proc-macro2",
"quote",
"serde",
"syn 1.0.109",
]
[[package]]
name = "num-traits"
version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a"
dependencies = [
"autocfg",
]
[[package]]
name = "once_cell"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "png"
version = "0.17.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06e4b0d3d1312775e782c86c91a111aa1f910cbb65e1337f9975b5f9a554b5e1"
dependencies = [
"bitflags",
"crc32fast",
"fdeflate",
"flate2",
"miniz_oxide",
]
[[package]]
name = "ppv-lite86"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]]
name = "proc-macro2"
version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom",
]
[[package]]
name = "serde"
version = "1.0.197"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.197"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.53",
]
[[package]]
name = "simd-adler32"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
[[package]]
name = "syn"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syn"
version = "2.0.53"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7383cd0e49fff4b6b90ca5670bfd3e9d6a733b3f90c686605aa7eec8c4996032"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "thiserror"
version = "1.0.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.53",
]
[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2",
"quote",
"syn 2.0.53",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.53",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
[[package]]
name = "weezl"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082"
[[package]]
name = "windows-core"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
dependencies = [
"windows-targets 0.52.4",
]
[[package]]
name = "windows-sys"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
"windows-targets 0.48.5",
]
[[package]]
name = "windows-targets"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
dependencies = [
"windows_aarch64_gnullvm 0.48.5",
"windows_aarch64_msvc 0.48.5",
"windows_i686_gnu 0.48.5",
"windows_i686_msvc 0.48.5",
"windows_x86_64_gnu 0.48.5",
"windows_x86_64_gnullvm 0.48.5",
"windows_x86_64_msvc 0.48.5",
]
[[package]]
name = "windows-targets"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b"
dependencies = [
"windows_aarch64_gnullvm 0.52.4",
"windows_aarch64_msvc 0.52.4",
"windows_i686_gnu 0.52.4",
"windows_i686_msvc 0.52.4",
"windows_x86_64_gnu 0.52.4",
"windows_x86_64_gnullvm 0.52.4",
"windows_x86_64_msvc 0.52.4",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9"
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675"
[[package]]
name = "windows_i686_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]]
name = "windows_i686_gnu"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3"
[[package]]
name = "windows_i686_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]]
name = "windows_i686_msvc"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02"
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177"
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8"

View file

@ -6,3 +6,10 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
chrono = "0.4.35"
fern = "0.6.2"
image = { version = "0.25.0", default-features = false, features = ["png","ff","gif"] }
ipnet = "2.9.0"
local-ip-address = "0.6.1"
log = "0.4.21"
rand = "0.8.5"

View file

@ -1,3 +1,13 @@
# virtual-camera
Library and server for dissemination of images obtained from the world server.
Currently uses TCP to stream images from the world server. Images are saved temporarily for testing purposes.
## Development
For development, you must first have Rust installed. This can be done by following the instructions found at [https://rustup.rs/](https://rustup.rs/). Once this is done, clone this repository, and in the root folder of the repository, run `cargo build --release`. This will both build the dependencies, install the correct toolchains, and create a final executable.
## Testing
To test this, first download the `comms-testing` branch of the World Server repository, open the `tennis` project, and run the project. Once this is done, build the latest version of this repository, as mentioned above. Finally, run this project, using `cargo run`.

BIN
logScreeenshot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 KiB

View file

@ -0,0 +1,7 @@
2024-03-21T14:47:31.759962308-04:00 - [INFO, communication_layer] - aggregating all IPs... This may take several minutes...
2024-03-21T14:47:36.825148581-04:00 - [INFO, communication_layer] - Stream connected to address: Ok(192.168.0.80:55001)
2024-03-21T14:47:36.825292754-04:00 - [INFO, communication_layer] - Start reading...
2024-03-21T14:47:38.021199638-04:00 - [INFO, communication_layer] - Image successfully recieved
2024-03-21T14:47:38.021453459-04:00 - [INFO, communication_layer] - Building image...
2024-03-21T14:47:39.127447553-04:00 - [INFO, communication_layer] - Image built, saving to file...
2024-03-21T14:47:44.733286335-04:00 - [INFO, communication_layer] - image saved!

View file

@ -1,5 +1,13 @@
<<<<<<< HEAD
Communication layer:
Add image resolution to initial handshake
unity: send x and y resolution
SOC: send back colour bit depth
unity: check bitdepth before beginning image transfer
=======
Rust Crate: `image-0.24.9`
Read image using `ImageBuffer::from_raw(w,h,bytes)`
image size: 4608 x 2592 x 3 [BGR]
>>>>>>> main

View file

@ -1,5 +1,5 @@
[toolchain]
channel="1.76.0-2024-02-08"
components = [ "rustc", "cargo", "rust-std", "rustfmt", "rust-docs", "rust-analyzer" ]
targets = [ "armv7-unknown-linux-musleabi" ]
targets = [ "armv7-unknown-linux-gnueabihf" ]
profile = "default"

View file

@ -1,3 +1,258 @@
use std::{ fs, io::{Bytes, stdin, BufReader, Error, ErrorKind, Read, Write}, net::{IpAddr, Ipv4Addr, SocketAddrV4, TcpStream}, path::Path, thread::{self, JoinHandle}, time::Duration};
use chrono::{DateTime, Local};
use image::{Rgb, RgbImage};
use ipnet::{Ipv4Net,PrefixLenError};
use local_ip_address::linux::local_ip;
use log::{LevelFilter, trace,debug,warn,error,info};
use fern::{log_file, Dispatch};
//RTSP port is 554; prepare for real world situations
const PORT_NUMBER:u16 = 55001;
const PORT_PROBE_TIMEOUT:Duration = Duration::new(5,0);
const SUBNET_SIZE:u8 = 24;
//These subnets are well documented;
///RIT owns the subnet 129.21.0.0/16; probing by attempting to open thousands of TCP streams
///simultaneously is unwise.
const UNSAFE_SUBNET:Result<Ipv4Net,PrefixLenError> = Ipv4Net::new(Ipv4Addr::new(129,21,0,0),16);
///This subnet is universally considered the "local" subnet. This results in 256 addresses, and can
///be probed both safely and efficiently, and as long as the world server on the LAN is running it
///is functionally guaranteeed to be found.
const HOME_SUBNET:Result<Ipv4Net,PrefixLenError> = Ipv4Net::new(Ipv4Addr::new(192,168,0,0),24);
fn main() {
println!("Hello, world!");
setup_logs(&true);
//Get host IP
let host_ip = local_ip().expect("No real IP address!");
trace!("Host IP: {:?}",host_ip);
let mut thread_list:Vec<JoinHandle<Result<TcpStream,Error>>> = Vec::new();
let mut port_list:Vec<TcpStream> = Vec::new();
if let IpAddr::V4(host_v4_ip) = host_ip{
//Check current subnet
let net = Ipv4Net::new(host_v4_ip,SUBNET_SIZE);
if let Ok(net) = net{
//RIT owns 129.21.0.0/16; DO NOT SPAM THIS NETWORK
if UNSAFE_SUBNET.unwrap().contains(&net){
//Request world server address from user
let address = manual_address_prompt();
if address.is_ok(){
port_list.push(address.unwrap());
//thread_list won't be added to, so the thread for loop won't execute
}
} else if net.contains(&HOME_SUBNET.unwrap()){
//Collect all Hosts on the current subnet
info!("aggregating all IPs... This may take several minutes...");
for net_address in net.hosts(){
thread_list.push(
thread::spawn(move ||{
let ip_port = std::net::SocketAddr::V4(SocketAddrV4::new(net_address, PORT_NUMBER));
//Attempt to open a TCP stream with this IP address, exit the thread
//returning the open TcpStream, or an error
return TcpStream::connect_timeout(&ip_port, PORT_PROBE_TIMEOUT);
})
);
}
}
}
}
//Multithread the port-sniffing block, only save sucessful connections
for thread in thread_list{
let output = thread.join().unwrap();
if let Ok(real_output) = output{
port_list.push(real_output);
}
}
//For all available ports, try the custom communication protocol
for mut stream in port_list{
info!("Stream connected to address: {:?}",stream.peer_addr());
send_processing_time(&mut stream, 2.7f64);
read_response(&mut stream);
}
//TODO: Document/implement RTSP client-side comms
//Currently using custom port and custom protocol, but if real-world cameras will
//be in use, we will likely need to be portable to the RTSP protocol, or similar
}
//Used to send the calculated time value to the world server
pub fn send_processing_time(stream:&mut TcpStream ,sent_value:f64){
debug!("Begin handshake; sending timestamp float...");
//Write the f64 value, in bytes, to the stream, and ensure it has been sent
stream.write(&sent_value.to_le_bytes()).unwrap();
stream.flush().unwrap();
debug!("Timestamp sent!");
}
//Used to recieve images from the world server
pub fn read_response(stream:&mut TcpStream){
//Buffer the incoming stream
let reader = BufReader::new(stream.try_clone().expect("Failed clone"));
//Create a storage point for the bytes
let mut recieved_bytes:Vec<u8> = Vec::new();
//Create an iterator over the stream's bytes
let mut iter = reader.bytes();
debug!("Continue handshake, read back image packet length...");
//The first values sent will always be a u32 containing the length of the message (without the
//length counted), followed by the image width and height
let length = bytes_to_u32(&mut iter);
debug!("Image packet length read as {:?}!",length);
debug!("Continue handshake, read back image width...");
let image_width = bytes_to_u32(&mut iter);
debug!("Image width read as {:?}!",image_width);
debug!("Continue handshake, read back image height...");
let image_height = bytes_to_u32(&mut iter);
debug!("Image height read as {:?}!",image_height);
//The length of the image is the total number of bytes
let byte_depth = length / (image_width * image_height);
debug!("Image bitdepth calculated as {:?}!", byte_depth);
//Confirm to world server the correct number of bytes
stream.write(&byte_depth.to_le_bytes()).unwrap();
stream.flush().unwrap();
//TODO: Remove assumption
//Always assumes world server will send image
info!("Start reading...");
//Recieve the rest of the message
for _ in 0..length{
recieved_bytes.push(iter.next().unwrap().unwrap_or(0));
}
info!("Image successfully recieved");
//Create a blank pane on which to store the read in pixels
let mut img = RgbImage::new(image_width,image_height);
//Create a temporary storage point for u8s when generating pixels
let mut temp:Vec<u8> = Vec::new();
//Iterate over bytes
info!("Building image...");
for i in 0..recieved_bytes.len(){
let byte = recieved_bytes.get(i).expect("Index does not exist!");
temp.push(byte.clone());
//Each pixel is composed of [byte_depth] u8s
if ((i as u32)+1) % byte_depth == 0{
//Coordinate in the pane = i/3
let pixel_number:u32 = (i as u32) /byte_depth;
//Insert the pixel into the pane
img.put_pixel(
//Pixels coming directly from Unity are sent "upside down", that is,
//starting at the bottom right, and iterating horizontally, then vertically.
//This line compensates and creates a properly-oriented image
(image_width-1)-(pixel_number%image_width), (image_height-1)-(pixel_number / image_width),
//Extract image from temporary storage, ang generate pixel
Rgb::<u8>{0:temp.clone().try_into().expect("bad vector length!")}
);
//Clear temporary storage
temp.clear();
}
}
//Dump image to file
//ONLY FOR EXPERIMENTATION AND TESTING PURPOSES
info!("Image built, saving to file...");
_ = img.save("./test.png");
info!("image saved!");
}
///Borrows an iterator over the bytes in a buffered-reader of a TcpStream; reads the next 4 bytes,
///outputs the generated u32
fn bytes_to_u32(iter:&mut Bytes<BufReader<TcpStream>>) -> u32{
let mut array:[u8;4] = [0;4];
for i in 0..4{
array[i] = iter.next().unwrap().unwrap();
}
return u32::from_le_bytes(array);
}
///Request the user to input the world server's address into stdin
fn manual_address_prompt() -> Result<TcpStream,Error>{
let return_val:Result<TcpStream,Error> = Err(Error::new(ErrorKind::AddrNotAvailable,"Invalid Address"));
while return_val.is_err(){
let mut user_input:String = String::default();
match stdin().read_line(&mut user_input){
Ok(_) => {
match user_input.trim().parse::<SocketAddrV4>(){
Ok(address) => {
//Test if the address is accurate
let stream = TcpStream::connect_timeout(&std::net::SocketAddr::V4(address), PORT_PROBE_TIMEOUT);
if stream.is_ok(){
return stream;
} else {
warn!("Address unavailable!");
debug!("{:?}",stream.unwrap_err());
}
},
Err(error) => {
error!("Unable to properly parse user input!");
debug!("{:?}",error);
}
}
},
Err(error) => {
error!("Unable to read user input!");
debug!("{:?}",error);
}
}
}
return return_val;
}
///Set up logging macros to be used throughout the program
fn setup_logs(debug:&bool){
//Get the current time
let chrono_now: DateTime<Local> = Local::now();
//Create a log directory, if it does not exist
if ! Path::new("logs").is_dir(){
_ = fs::create_dir("logs");
};
//Create a log macro listener
_ = fern::Dispatch::new()
//Format the output messages
.format(|out,message,record|{
out.finish(format_args!(
"{} - [{}, {}] - {}",
Local::now().to_rfc3339(),
record.level(),
record.target(),
message
))
})
//Output to the file
.chain({
let mut file_logger = Dispatch::new();
let date_format = chrono_now.format("%Y-%m-%d_%H.%M").to_string();
let local_log_file = log_file(format!("logs/{}.log",date_format)).unwrap();
//Set filter based on whether the command is being run in "debug" mode
if *debug{
file_logger = file_logger.level(LevelFilter::Trace);
}
else {
file_logger = file_logger.level(LevelFilter::Debug);
}
//Apply the filter and file formatting rules described above
file_logger.chain(local_log_file)
})
.chain({
//Also log to stdout
let mut stdout_logger = fern::Dispatch::new();
if *debug {
stdout_logger = stdout_logger.level(LevelFilter::Debug);
}
else {
stdout_logger = stdout_logger.level(LevelFilter::Info);
}
stdout_logger.chain(std::io::stdout())
})
//Start listening to macros
.apply();
}