Compare commits
No commits in common. "feat/ble" and "main" have entirely different histories.
8 changed files with 10 additions and 741 deletions
183
Cargo.lock
generated
183
Cargo.lock
generated
|
|
@ -166,29 +166,6 @@ dependencies = [
|
||||||
"generic-array",
|
"generic-array",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "bt-hci"
|
|
||||||
version = "0.8.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "211713d2e9fb4793ce4360a712c0764264aff6be48932ccf02ca2a331c0436a9"
|
|
||||||
dependencies = [
|
|
||||||
"btuuid",
|
|
||||||
"embassy-sync 0.8.0",
|
|
||||||
"embedded-io 0.7.1",
|
|
||||||
"embedded-io-async 0.7.0",
|
|
||||||
"futures-intrusive",
|
|
||||||
"heapless 0.9.2",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "btuuid"
|
|
||||||
version = "0.1.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f5f48f1e9b0aad0a4f05d17bdeae0fa20ff798e272a03a6940ca27ad9c5a6ae7"
|
|
||||||
dependencies = [
|
|
||||||
"uuid",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bumpalo"
|
name = "bumpalo"
|
||||||
version = "3.20.2"
|
version = "3.20.2"
|
||||||
|
|
@ -267,15 +244,6 @@ version = "1.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0b396d1f76d455557e1218ec8066ae14bba60b4b36ecd55577ba979f5db7ecaa"
|
checksum = "0b396d1f76d455557e1218ec8066ae14bba60b4b36ecd55577ba979f5db7ecaa"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "convert_case"
|
|
||||||
version = "0.8.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "baaaa0ecca5b51987b9423ccdc971514dd8b0bb7b4060b983d3664dad3f1f89f"
|
|
||||||
dependencies = [
|
|
||||||
"unicode-segmentation",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cordyceps"
|
name = "cordyceps"
|
||||||
version = "0.3.4"
|
version = "0.3.4"
|
||||||
|
|
@ -988,7 +956,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "23fbff98b06a96b6ce3791ecec5c668524052a068e23aacd23afe17ddba844ce"
|
checksum = "23fbff98b06a96b6ce3791ecec5c668524052a068e23aacd23afe17ddba844ce"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"allocator-api2",
|
"allocator-api2",
|
||||||
"bt-hci",
|
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"docsplay",
|
"docsplay",
|
||||||
"document-features",
|
"document-features",
|
||||||
|
|
@ -1185,14 +1152,11 @@ name = "esp32-c_its-companion"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"assert_float_eq",
|
"assert_float_eq",
|
||||||
"bt-hci",
|
|
||||||
"c-its-parser",
|
"c-its-parser",
|
||||||
"chrono",
|
"chrono",
|
||||||
"critical-section",
|
"critical-section",
|
||||||
"crossbeam-queue",
|
"crossbeam-queue",
|
||||||
"embassy-executor",
|
"embassy-executor",
|
||||||
"embassy-futures",
|
|
||||||
"embassy-sync 0.7.2",
|
|
||||||
"embassy-time",
|
"embassy-time",
|
||||||
"embassy_gps",
|
"embassy_gps",
|
||||||
"embedded-graphics",
|
"embedded-graphics",
|
||||||
|
|
@ -1215,8 +1179,6 @@ dependencies = [
|
||||||
"profont",
|
"profont",
|
||||||
"prost",
|
"prost",
|
||||||
"prost-build",
|
"prost-build",
|
||||||
"static_cell",
|
|
||||||
"trouble-host",
|
|
||||||
"ublox",
|
"ublox",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -1358,52 +1320,12 @@ version = "2.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
|
checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "futures"
|
|
||||||
version = "0.3.32"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d"
|
|
||||||
dependencies = [
|
|
||||||
"futures-channel",
|
|
||||||
"futures-core",
|
|
||||||
"futures-io",
|
|
||||||
"futures-sink",
|
|
||||||
"futures-task",
|
|
||||||
"futures-util",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "futures-channel"
|
|
||||||
version = "0.3.32"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d"
|
|
||||||
dependencies = [
|
|
||||||
"futures-core",
|
|
||||||
"futures-sink",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-core"
|
name = "futures-core"
|
||||||
version = "0.3.32"
|
version = "0.3.32"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d"
|
checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "futures-intrusive"
|
|
||||||
version = "0.5.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f"
|
|
||||||
dependencies = [
|
|
||||||
"futures-core",
|
|
||||||
"lock_api",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "futures-io"
|
|
||||||
version = "0.3.32"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-sink"
|
name = "futures-sink"
|
||||||
version = "0.3.32"
|
version = "0.3.32"
|
||||||
|
|
@ -1423,10 +1345,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6"
|
checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-sink",
|
|
||||||
"futures-task",
|
"futures-task",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"slab",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -1641,18 +1561,6 @@ dependencies = [
|
||||||
"syn 2.0.117",
|
"syn 2.0.117",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "js-sys"
|
|
||||||
version = "0.3.98"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "67df7112613f8bfd9150013a0314e196f4800d3201ae742489d999db2f979f08"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"futures-util",
|
|
||||||
"once_cell",
|
|
||||||
"wasm-bindgen",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lazy_static"
|
name = "lazy_static"
|
||||||
version = "1.5.0"
|
version = "1.5.0"
|
||||||
|
|
@ -1695,15 +1603,6 @@ version = "1.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092"
|
checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "lock_api"
|
|
||||||
version = "0.4.14"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"
|
|
||||||
dependencies = [
|
|
||||||
"scopeguard",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.29"
|
version = "0.4.29"
|
||||||
|
|
@ -2285,12 +2184,6 @@ version = "1.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
|
checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "scopeguard"
|
|
||||||
version = "1.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "semver"
|
name = "semver"
|
||||||
version = "1.0.28"
|
version = "1.0.28"
|
||||||
|
|
@ -2368,12 +2261,6 @@ version = "1.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "slab"
|
|
||||||
version = "0.4.12"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smallvec"
|
name = "smallvec"
|
||||||
version = "1.15.1"
|
version = "1.15.1"
|
||||||
|
|
@ -2422,15 +2309,6 @@ version = "1.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"
|
checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "static_cell"
|
|
||||||
version = "2.1.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0530892bb4fa575ee0da4b86f86c667132a94b74bb72160f58ee5a4afec74c23"
|
|
||||||
dependencies = [
|
|
||||||
"portable-atomic",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strsim"
|
name = "strsim"
|
||||||
version = "0.11.1"
|
version = "0.11.1"
|
||||||
|
|
@ -2620,39 +2498,6 @@ dependencies = [
|
||||||
"tracing-log",
|
"tracing-log",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "trouble-host"
|
|
||||||
version = "0.6.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1df7817cead4b83dfbeeaa59736ecbc97c30b21dc3bfc0cc2ce8a6687f70b37a"
|
|
||||||
dependencies = [
|
|
||||||
"bt-hci",
|
|
||||||
"embassy-futures",
|
|
||||||
"embassy-sync 0.7.2",
|
|
||||||
"embassy-time",
|
|
||||||
"embedded-io 0.7.1",
|
|
||||||
"futures",
|
|
||||||
"heapless 0.9.2",
|
|
||||||
"rand_core 0.6.4",
|
|
||||||
"static_cell",
|
|
||||||
"trouble-host-macros",
|
|
||||||
"zerocopy",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "trouble-host-macros"
|
|
||||||
version = "0.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2d809ae05f510cf8f1d863749281eb28e049d9ae4ad52d92ea7a0ac068a0e17c"
|
|
||||||
dependencies = [
|
|
||||||
"convert_case",
|
|
||||||
"darling 0.20.11",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn 2.0.117",
|
|
||||||
"uuid",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typenum"
|
name = "typenum"
|
||||||
version = "1.20.0"
|
version = "1.20.0"
|
||||||
|
|
@ -2694,12 +2539,6 @@ version = "1.0.24"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "unicode-segmentation"
|
|
||||||
version = "1.13.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-width"
|
name = "unicode-width"
|
||||||
version = "0.1.14"
|
version = "0.1.14"
|
||||||
|
|
@ -2731,8 +2570,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76"
|
checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"getrandom",
|
"getrandom",
|
||||||
"js-sys",
|
|
||||||
"wasm-bindgen",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -3038,26 +2875,6 @@ dependencies = [
|
||||||
"syn 2.0.117",
|
"syn 2.0.117",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "zerocopy"
|
|
||||||
version = "0.8.49"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "bce33a6288fa3f072a8c2c7d0f2fdbb90e28298f0135c1f99b96c3db2efcc60b"
|
|
||||||
dependencies = [
|
|
||||||
"zerocopy-derive",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "zerocopy-derive"
|
|
||||||
version = "0.8.49"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8fd425244944f4ab65ccff928e7323354c5a018c75838362fdce749dfad2ee1e"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn 2.0.117",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zmij"
|
name = "zmij"
|
||||||
version = "1.0.21"
|
version = "1.0.21"
|
||||||
|
|
|
||||||
14
Cargo.toml
14
Cargo.toml
|
|
@ -23,8 +23,6 @@ esp = [
|
||||||
"dep:esp-rtos",
|
"dep:esp-rtos",
|
||||||
"dep:esp-bootloader-esp-idf",
|
"dep:esp-bootloader-esp-idf",
|
||||||
"dep:embassy-executor",
|
"dep:embassy-executor",
|
||||||
"dep:embassy-futures",
|
|
||||||
"dep:embassy-sync",
|
|
||||||
"dep:embassy-time",
|
"dep:embassy-time",
|
||||||
"dep:embedded-io",
|
"dep:embedded-io",
|
||||||
"dep:embedded-io-async",
|
"dep:embedded-io-async",
|
||||||
|
|
@ -32,7 +30,6 @@ esp = [
|
||||||
"dep:esp-backtrace",
|
"dep:esp-backtrace",
|
||||||
"dep:esp-println",
|
"dep:esp-println",
|
||||||
"dep:esp-radio",
|
"dep:esp-radio",
|
||||||
"dep:bt-hci",
|
|
||||||
"esp32-cits-core/esp32c5",
|
"esp32-cits-core/esp32c5",
|
||||||
"esp32-cits-core/log-04",
|
"esp32-cits-core/log-04",
|
||||||
]
|
]
|
||||||
|
|
@ -55,7 +52,7 @@ spat_debug = []
|
||||||
# enable ST7789 based display
|
# enable ST7789 based display
|
||||||
screen = ["dep:mipidsi", "dep:embedded-graphics", "dep:embedded-hal-bus", "dep:profont"]
|
screen = ["dep:mipidsi", "dep:embedded-graphics", "dep:embedded-hal-bus", "dep:profont"]
|
||||||
# enable I/O via UART
|
# enable I/O via UART
|
||||||
uart = ["_uart", "_gnss"]
|
uart = ["_uart", "_gnss", "dep:prost"]
|
||||||
|
|
||||||
# internal feature, that any UART I/O is enabled
|
# internal feature, that any UART I/O is enabled
|
||||||
_uart = []
|
_uart = []
|
||||||
|
|
@ -69,7 +66,6 @@ esp-rtos = { version = "0.3.0", optional = true, features = [
|
||||||
"embassy",
|
"embassy",
|
||||||
"esp-alloc",
|
"esp-alloc",
|
||||||
"esp-radio",
|
"esp-radio",
|
||||||
"embassy",
|
|
||||||
"esp32c5",
|
"esp32c5",
|
||||||
"log-04",
|
"log-04",
|
||||||
] }
|
] }
|
||||||
|
|
@ -78,10 +74,7 @@ esp-bootloader-esp-idf = { version = "0.5.0", optional = true, features = ["esp3
|
||||||
log = "0.4.27"
|
log = "0.4.27"
|
||||||
|
|
||||||
critical-section = "1.2.0"
|
critical-section = "1.2.0"
|
||||||
bt-hci = { version = "0.8.0", optional = true }
|
|
||||||
embassy-executor = { version = "0.10.0", optional = true, features = ["log"] }
|
embassy-executor = { version = "0.10.0", optional = true, features = ["log"] }
|
||||||
embassy-futures = { version = "0.1.2", optional = true }
|
|
||||||
embassy-sync = { version = "0.7", optional = true }
|
|
||||||
embassy-time = { version = "0.5.0", optional = true, features = ["log"] }
|
embassy-time = { version = "0.5.0", optional = true, features = ["log"] }
|
||||||
embedded-io = { version = "0.7.1", optional = true }
|
embedded-io = { version = "0.7.1", optional = true }
|
||||||
embedded-io-async = { version = "0.7.0", optional = true }
|
embedded-io-async = { version = "0.7.0", optional = true }
|
||||||
|
|
@ -99,10 +92,7 @@ esp-radio = { version = "0.18.0", optional = true, features = [
|
||||||
"unstable",
|
"unstable",
|
||||||
"wifi",
|
"wifi",
|
||||||
"sniffer",
|
"sniffer",
|
||||||
"ble",
|
|
||||||
] }
|
] }
|
||||||
trouble-host = { version = "0.6.0", features = ["gatt", "central", "derive", "default-packet-pool"] }
|
|
||||||
static_cell = "2"
|
|
||||||
|
|
||||||
embassy_gps = { version = "0.1.0", optional = true, default-features = false, features = ["esp", "log-04"], git = "https://github.com/jbeyerstedt/embassy_gps.git", branch = "feat/rework-gpsfix" }
|
embassy_gps = { version = "0.1.0", optional = true, default-features = false, features = ["esp", "log-04"], git = "https://github.com/jbeyerstedt/embassy_gps.git", branch = "feat/rework-gpsfix" }
|
||||||
esp32-cits-core = { version = "0.1.0", default-features = false, git = "https://git.hamburg.ccc.de/jtbx/esp32-cits-core", branch = "main" }
|
esp32-cits-core = { version = "0.1.0", default-features = false, git = "https://git.hamburg.ccc.de/jtbx/esp32-cits-core", branch = "main" }
|
||||||
|
|
@ -121,7 +111,7 @@ geo-types = { version = "0.7.19", default-features = false }
|
||||||
mipidsi = { version = "0.10.0", optional = true }
|
mipidsi = { version = "0.10.0", optional = true }
|
||||||
num-traits = { version = "0.2.19", default-features = false, features = ["libm"] }
|
num-traits = { version = "0.2.19", default-features = false, features = ["libm"] }
|
||||||
profont = { version = "0.7.0", optional = true }
|
profont = { version = "0.7.0", optional = true }
|
||||||
prost = { version = "0.14", default-features = false, features = ["derive"] }
|
prost = { version = "0.14", optional = true, default-features = false, features = ["derive"] }
|
||||||
ublox = { version = "0.10", optional = true, default-features = false, features = ["alloc", "ubx_proto27"] }
|
ublox = { version = "0.10", optional = true, default-features = false, features = ["alloc", "ubx_proto27"] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@ rustup target add riscv32imac-unknown-none-elf
|
||||||
cargo install espflash --locked
|
cargo install espflash --locked
|
||||||
```
|
```
|
||||||
|
|
||||||
(Project was setup using esp-generate with the options `--chip esp32c5 -o esp32c5-wroom-1-psram -o alloc -o log -o unstable-hal -o wifi -o esp-backtrace -o embassy -o ble-trouble`.)
|
(Project was setup using esp-generate with the options `--chip esp32c5 -o esp32c5-wroom-1-psram -o alloc -o log -o unstable-hal -o wifi -o esp-backtrace -o embassy`.)
|
||||||
|
|
||||||
To use the proper rustfmt features, enable the nightly toolchain:
|
To use the proper rustfmt features, enable the nightly toolchain:
|
||||||
```shell
|
```shell
|
||||||
|
|
|
||||||
|
|
@ -35,65 +35,15 @@ All data types are defined in one `.proto` file: [c_its-messages.proto](./c_its-
|
||||||
|
|
||||||
When there's no GNSS receiver connected to the ESP, position, heading and speed information can be set using a `PositionState` message (see [c_its-messages.proto](./c_its-messages.proto)).
|
When there's no GNSS receiver connected to the ESP, position, heading and speed information can be set using a `PositionState` message (see [c_its-messages.proto](./c_its-messages.proto)).
|
||||||
|
|
||||||
Maximum message size (assuming realistic value ranges):
|
|
||||||
|
|
||||||
field name | tag size | (max.) data size
|
|
||||||
----------------- | -------- | ---------
|
|
||||||
timestamp_ms | 1 | 8 (I64)
|
|
||||||
position | 1 | 1 (LEN(10)) + sub-fields below
|
|
||||||
\+ latitude_deg | 1 | 4 (I32)
|
|
||||||
\+ longitude_deg | 1 | 4 (I32)
|
|
||||||
heading | 1 | 2 (VARINT(3600))
|
|
||||||
speed | 1 | 2 (VARINT(~163 m/s))
|
|
||||||
**SUM** | 6 + | 21 = 27 byte
|
|
||||||
|
|
||||||
|
|
||||||
### DENM Event
|
### DENM Event
|
||||||
|
|
||||||
Each received DENM will be "published" as a `DenmEvent` message (see [c_its-messages.proto](./c_its-messages.proto)).
|
Each received DENM will be "published" as a `DenmEvent` message (see [c_its-messages.proto](./c_its-messages.proto)).
|
||||||
Repetitions of the same message (e.g. no changes to the validity timeframe and location) may be dropped by the BLE server.
|
Repetitions of the same message (e.g. no changes to the validity timeframe and location) may be dropped by the BLE server.
|
||||||
|
|
||||||
Maximum message size (assuming realistic value ranges):
|
|
||||||
|
|
||||||
field name | tag size | (max.) data size
|
|
||||||
----------------- | -------- | ---------
|
|
||||||
timestamp | 1 | 8 (I64)
|
|
||||||
validity_end_ts | 1 | 8 (I64)
|
|
||||||
station_id | 1 | 8 (I64)
|
|
||||||
seq_num | 1 | 3 (VARINT(65535))
|
|
||||||
event_position | 1 | 1 (LEN(10)) + sub-fields below
|
|
||||||
\+ latitude_deg | 1 | 4 (I32)
|
|
||||||
\+ longitude_deg | 1 | 4 (I32)
|
|
||||||
event_heading_deg | 1 | 1 (VARINT(360))
|
|
||||||
direction | 1 | 1 (VARINT(3))
|
|
||||||
cause_code | 1 | 1 (VARINT(127))
|
|
||||||
sub_cause_code | 1 | 1 (VARINT(127))
|
|
||||||
**SUM** | 11 + | 40 = 51 byte
|
|
||||||
|
|
||||||
Note: Cause code and sub-cause code are technically 0..255 in the ASN.1 spec, but that's mainly to ensure backwards-compatibility of the CHOICE with the old wire format.
|
|
||||||
Realistically only cause codes up to 100 are defined and common sub-cause codes use values up to 22.
|
|
||||||
|
|
||||||
### CAM Event
|
### CAM Event
|
||||||
|
|
||||||
Each received (low-frequency) CAM will be "published" as a `CamEvent` message (see [c_its-messages.proto](./c_its-messages.proto)).
|
Each received (low-frequency) CAM will be "published" as a `CamEvent` message (see [c_its-messages.proto](./c_its-messages.proto)).
|
||||||
|
|
||||||
Maximum message size (assuming realistic value ranges):
|
|
||||||
|
|
||||||
field name | tag size | (max.) data size
|
|
||||||
--------------------- | -------- | ---------
|
|
||||||
station_id | 1 | 8 (I64)
|
|
||||||
station_type | 1 | 1 (VARINT(15))
|
|
||||||
position | 1 | 1 (LEN(10)) + sub-fields below
|
|
||||||
\+ latitude_deg | 1 | 4 (I32)
|
|
||||||
\+ longitude_deg | 1 | 4 (I32)
|
|
||||||
vehicle_role | 1 | 1 (VARINT(15))
|
|
||||||
vehicle_data | 1 | 1 (LEN(11)) + sub-fields below
|
|
||||||
\+ heading_deg | 1 | 2 (VARINT(360))
|
|
||||||
\+ speed | 1 | 2 (VARINT(~163 m/s))
|
|
||||||
\+ vehicle_length_dm | 1 | 2 (VARINT(1023))
|
|
||||||
\+ vehicle_width_dm | 1 | 1 (VARINT(62))
|
|
||||||
**SUM** | 11 + | 27 = 38 byte
|
|
||||||
|
|
||||||
### Raw Received Message
|
### Raw Received Message
|
||||||
|
|
||||||
Received V2X messages will be "published" as a `RawMsgRx` message (see [c_its-messages.proto](./c_its-messages.proto)).
|
Received V2X messages will be "published" as a `RawMsgRx` message (see [c_its-messages.proto](./c_its-messages.proto)).
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,7 @@ message PositionState {
|
||||||
}
|
}
|
||||||
|
|
||||||
message DenmEvent {
|
message DenmEvent {
|
||||||
required fixed64 timestamp = 1; // DENM reference time as UNIX time (in seconds)
|
required fixed64 timestamp = 1; // DENM reference time as UNIX time
|
||||||
required fixed64 validity_end_ts = 2; // UNIX time when event validity ends (from denm.management.validityDuration)
|
required fixed64 validity_end_ts = 2; // UNIX time when event validity ends (from denm.management.validityDuration)
|
||||||
required fixed32 station_id = 3; // unique ID of the event when combined with `seq_num`
|
required fixed32 station_id = 3; // unique ID of the event when combined with `seq_num`
|
||||||
required uint32 seq_num = 4; // unique ID of the event when combined with `station_id`
|
required uint32 seq_num = 4; // unique ID of the event when combined with `station_id`
|
||||||
|
|
|
||||||
256
src/ble.rs
256
src/ble.rs
|
|
@ -1,256 +0,0 @@
|
||||||
#![allow(
|
|
||||||
clippy::needless_borrows_for_generic_args,
|
|
||||||
reason = "gatt_service creates false positives"
|
|
||||||
)]
|
|
||||||
|
|
||||||
use core::cell::RefCell;
|
|
||||||
|
|
||||||
use critical_section::Mutex;
|
|
||||||
use esp_backtrace as _;
|
|
||||||
use log::{info, warn};
|
|
||||||
use trouble_host::prelude::*;
|
|
||||||
|
|
||||||
pub const CONTROLLER_SLOTS: usize = 20;
|
|
||||||
const CONNECTIONS_MAX: usize = 1;
|
|
||||||
const L2CAP_CHANNELS_MAX: usize = 1;
|
|
||||||
|
|
||||||
pub static TX_DATA: Mutex<RefCell<Option<BleSendable>>> = Mutex::new(RefCell::new(None));
|
|
||||||
pub static RX_DATA: Mutex<RefCell<Option<crate::io::msg::PositionState>>> =
|
|
||||||
Mutex::new(RefCell::new(None));
|
|
||||||
|
|
||||||
pub enum BleSendable {
|
|
||||||
#[cfg(feature = "cam")]
|
|
||||||
Cam(crate::io::msg::CamEvent),
|
|
||||||
#[cfg(feature = "denm")]
|
|
||||||
Denm(crate::io::msg::DenmEvent),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[gatt_server]
|
|
||||||
struct Server {
|
|
||||||
c_its_events: CITSEvents,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "cam")]
|
|
||||||
const CAM_EVENT_SIZE: usize = 38;
|
|
||||||
#[cfg(feature = "denm")]
|
|
||||||
const DENM_EVENT_SIZE: usize = 51;
|
|
||||||
|
|
||||||
#[gatt_service(uuid = "c0b70000-d4f4-4000-ada8-f99a02ee315c")]
|
|
||||||
struct CITSEvents {
|
|
||||||
#[descriptor(uuid = descriptors::MEASUREMENT_DESCRIPTION, name = "Position", read, value = "PositionState proto msg", type = &'static str)]
|
|
||||||
#[characteristic(uuid = "c0b70001-d4f4-4001-ada8-f99a02ee315c", write)]
|
|
||||||
position: [u8; 27],
|
|
||||||
|
|
||||||
#[cfg(feature = "cam")]
|
|
||||||
#[descriptor(uuid = descriptors::MEASUREMENT_DESCRIPTION, name = "CAM_Event", read, value = "CamEvent proto msg", type = &'static str)]
|
|
||||||
#[characteristic(uuid = "c0b70001-d4f4-4002-ada8-f99a02ee315c", read, notify, value = [0u8; CAM_EVENT_SIZE])]
|
|
||||||
cam_event: [u8; CAM_EVENT_SIZE],
|
|
||||||
|
|
||||||
#[cfg(feature = "denm")]
|
|
||||||
#[descriptor(uuid = descriptors::MEASUREMENT_DESCRIPTION, name = "DENM_Event", read, value = "DenmEvent proto msg", type = &'static str)]
|
|
||||||
#[characteristic(uuid = "c0b70001-d4f4-4004-ada8-f99a02ee315c", read, notify, value = [0u8; DENM_EVENT_SIZE])]
|
|
||||||
denm_event: [u8; DENM_EVENT_SIZE],
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates the BLE controller
|
|
||||||
pub fn make_controller(
|
|
||||||
bt_peripheral: esp_hal::peripherals::BT<'static>,
|
|
||||||
) -> bt_hci::controller::ExternalController<
|
|
||||||
esp_radio::ble::controller::BleConnector<'static>,
|
|
||||||
CONTROLLER_SLOTS,
|
|
||||||
> {
|
|
||||||
let transport = esp_radio::ble::controller::BleConnector::new(
|
|
||||||
bt_peripheral,
|
|
||||||
esp_radio::ble::Config::default(),
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
bt_hci::controller::ExternalController::<_, { CONTROLLER_SLOTS }>::new(transport)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Run the BLE stack.
|
|
||||||
#[embassy_executor::task]
|
|
||||||
pub async fn run(
|
|
||||||
controller: bt_hci::controller::ExternalController<
|
|
||||||
esp_radio::ble::controller::BleConnector<'static>,
|
|
||||||
CONTROLLER_SLOTS,
|
|
||||||
>,
|
|
||||||
) {
|
|
||||||
let mut resources: HostResources<DefaultPacketPool, CONNECTIONS_MAX, L2CAP_CHANNELS_MAX> =
|
|
||||||
HostResources::new();
|
|
||||||
let stack = trouble_host::new(controller, &mut resources);
|
|
||||||
let Host {
|
|
||||||
mut peripheral,
|
|
||||||
runner,
|
|
||||||
..
|
|
||||||
} = stack.build();
|
|
||||||
|
|
||||||
info!("Starting advertising and GATT service");
|
|
||||||
let server = Server::new_with_config(GapConfig::Peripheral(PeripheralConfig {
|
|
||||||
name: "ESP32 C-ITS",
|
|
||||||
appearance: &appearance::UNKNOWN,
|
|
||||||
}))
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let _ = embassy_futures::join::join(ble_task(runner), async {
|
|
||||||
loop {
|
|
||||||
match advertise("ESP32 C-ITS", &mut peripheral, &server).await {
|
|
||||||
Ok(conn) => {
|
|
||||||
// set up tasks when the connection is established to a central, so they don't run when no one is connected.
|
|
||||||
let a = gatt_events_task(&server, &conn);
|
|
||||||
let b = custom_task(&server, &conn, &stack);
|
|
||||||
// run until any task ends (usually because the connection has been closed),
|
|
||||||
// then return to advertising state.
|
|
||||||
embassy_futures::select::select(a, b).await;
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
panic!("BLE ADV: fatal error {e:?}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.await;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create an advertiser to use to connect to a BLE Central, and wait for it to connect.
|
|
||||||
async fn advertise<'values, 'server, C: Controller>(
|
|
||||||
name: &'values str,
|
|
||||||
peripheral: &mut Peripheral<'values, C, DefaultPacketPool>,
|
|
||||||
server: &'server Server<'values>,
|
|
||||||
) -> Result<GattConnection<'values, 'server, DefaultPacketPool>, BleHostError<C::Error>> {
|
|
||||||
let mut advertiser_data = [0; 35];
|
|
||||||
let len = AdStructure::encode_slice(
|
|
||||||
&[
|
|
||||||
AdStructure::Flags(LE_GENERAL_DISCOVERABLE | BR_EDR_NOT_SUPPORTED),
|
|
||||||
AdStructure::CompleteLocalName(name.as_bytes()),
|
|
||||||
],
|
|
||||||
&mut advertiser_data[..],
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let advertiser = peripheral
|
|
||||||
.advertise(
|
|
||||||
&trouble_host::advertise::AdvertisementParameters {
|
|
||||||
timeout: Some(embassy_time::Duration::from_secs(2)),
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
Advertisement::ConnectableScannableUndirected {
|
|
||||||
adv_data: &advertiser_data[..len],
|
|
||||||
scan_data: &[],
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
// info!("[adv] advertising {len} bytes");
|
|
||||||
let conn = advertiser.accept().await?.with_attribute_server(server)?;
|
|
||||||
// info!("[adv] connection established");
|
|
||||||
Ok(conn)
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn ble_task<C: Controller, P: PacketPool>(mut runner: Runner<'_, C, P>) {
|
|
||||||
loop {
|
|
||||||
if let Err(e) = runner.run().await {
|
|
||||||
panic!("BLE Task: fatal error {e:?}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Stream Events until the connection closes.
|
|
||||||
///
|
|
||||||
/// This function will handle the GATT events and process them.
|
|
||||||
/// This is how we interact with read and write requests.
|
|
||||||
async fn gatt_events_task<P: PacketPool>(
|
|
||||||
server: &Server<'_>,
|
|
||||||
conn: &GattConnection<'_, '_, P>,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
let reason = loop {
|
|
||||||
match conn.next().await {
|
|
||||||
GattConnectionEvent::Disconnected { reason } => break reason,
|
|
||||||
GattConnectionEvent::Gatt { event } => {
|
|
||||||
match &event {
|
|
||||||
GattEvent::Write(event)
|
|
||||||
if event.handle() == server.c_its_events.position.handle =>
|
|
||||||
{
|
|
||||||
info!("[gatt] Write Event to Position: {:?}", event.data()); // TODO dev only
|
|
||||||
// TODO: parse proto and send to main thread
|
|
||||||
}
|
|
||||||
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This step is also performed at drop(), but writing it explicitly is necessary
|
|
||||||
// in order to ensure reply is sent.
|
|
||||||
match event.accept() {
|
|
||||||
Ok(reply) => reply.send().await,
|
|
||||||
Err(e) => warn!("BLE: error sending response: {e:?}"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {} // ignore other Gatt Connection Events
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
info!("BLE: disconnected b/c {reason:?}");
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Example task to use the BLE notifier interface.
|
|
||||||
/// This task will notify the connected central of a counter value every 2 seconds.
|
|
||||||
/// It will also read the RSSI value every 2 seconds.
|
|
||||||
/// and will stop when the connection is closed by the central or an error occurs.
|
|
||||||
async fn custom_task<C: Controller, P: PacketPool>(
|
|
||||||
server: &Server<'_>,
|
|
||||||
conn: &GattConnection<'_, '_, P>,
|
|
||||||
stack: &Stack<'_, C, P>,
|
|
||||||
) {
|
|
||||||
loop {
|
|
||||||
embassy_time::Timer::after(embassy_time::Duration::from_millis(10)).await;
|
|
||||||
|
|
||||||
let mut new_data = None;
|
|
||||||
critical_section::with(|cs| {
|
|
||||||
let tx_data_ref = TX_DATA.borrow(cs);
|
|
||||||
|
|
||||||
if let Some(tx_data) = tx_data_ref.replace(None) {
|
|
||||||
new_data = Some(tx_data);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
match new_data {
|
|
||||||
#[cfg(feature = "cam")]
|
|
||||||
Some(BleSendable::Cam(cam_event)) => {
|
|
||||||
let mut buf = cam_event.serialize_ble_proto();
|
|
||||||
|
|
||||||
if buf.len() <= CAM_EVENT_SIZE {
|
|
||||||
// pad with zeros
|
|
||||||
let pad = alloc::vec![0u8; CAM_EVENT_SIZE - buf.len()];
|
|
||||||
buf.extend_from_slice(&pad);
|
|
||||||
|
|
||||||
// unwrap should be fine since we ensured the vector size before
|
|
||||||
let value = buf.try_into().unwrap();
|
|
||||||
|
|
||||||
if let Err(err) = server.c_its_events.cam_event.notify(conn, &value).await {
|
|
||||||
warn!("BLE: failed notifying connection of new CAM event: {err:?}");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
warn!("BLE: CAM event too big with {} bytes", buf.len());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(feature = "denm")]
|
|
||||||
Some(BleSendable::Denm(denm_event)) => {
|
|
||||||
let mut buf = denm_event.serialize_ble_proto();
|
|
||||||
|
|
||||||
if buf.len() <= DENM_EVENT_SIZE {
|
|
||||||
// pad with zeros
|
|
||||||
let pad = alloc::vec![0u8; DENM_EVENT_SIZE - buf.len()];
|
|
||||||
buf.extend_from_slice(&pad);
|
|
||||||
|
|
||||||
// unwrap should be fine since we ensured the vector size before
|
|
||||||
let value = buf.try_into().unwrap();
|
|
||||||
|
|
||||||
if let Err(err) = server.c_its_events.denm_event.notify(conn, &value).await {
|
|
||||||
warn!("BLE: failed notifying connection of new DENM event: {err:?}");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
warn!("BLE: DENM event too big with {} bytes", buf.len());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
213
src/io.rs
213
src/io.rs
|
|
@ -5,12 +5,12 @@ pub mod msg {
|
||||||
include!(concat!(env!("OUT_DIR"), "/c_its_io.rs"));
|
include!(concat!(env!("OUT_DIR"), "/c_its_io.rs"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
use alloc::string::ToString;
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
|
|
||||||
#[cfg(feature = "uart")]
|
|
||||||
use c_its_parser::gn as geonetworking;
|
use c_its_parser::gn as geonetworking;
|
||||||
|
use log::error;
|
||||||
|
|
||||||
#[cfg(feature = "uart")]
|
|
||||||
impl From<msg::RawMsgRx> for msg::SerialOutputMsg {
|
impl From<msg::RawMsgRx> for msg::SerialOutputMsg {
|
||||||
fn from(value: msg::RawMsgRx) -> Self {
|
fn from(value: msg::RawMsgRx) -> Self {
|
||||||
use msg::serial_output_msg::Payload;
|
use msg::serial_output_msg::Payload;
|
||||||
|
|
@ -21,7 +21,6 @@ impl From<msg::RawMsgRx> for msg::SerialOutputMsg {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "uart")]
|
|
||||||
impl From<msg::DenmEvent> for msg::SerialOutputMsg {
|
impl From<msg::DenmEvent> for msg::SerialOutputMsg {
|
||||||
fn from(value: msg::DenmEvent) -> Self {
|
fn from(value: msg::DenmEvent) -> Self {
|
||||||
use msg::serial_output_msg::Payload;
|
use msg::serial_output_msg::Payload;
|
||||||
|
|
@ -33,41 +32,22 @@ impl From<msg::DenmEvent> for msg::SerialOutputMsg {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl msg::RawMsgRx {
|
impl msg::RawMsgRx {
|
||||||
#[cfg(feature = "uart")]
|
|
||||||
pub fn serialize_uart_proto(&self) -> Vec<u8> {
|
pub fn serialize_uart_proto(&self) -> Vec<u8> {
|
||||||
serialize_serial_msg(&Into::<msg::SerialOutputMsg>::into(self.clone()))
|
serialize_serial_msg(&Into::<msg::SerialOutputMsg>::into(self.clone()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl msg::DenmEvent {
|
impl msg::DenmEvent {
|
||||||
#[cfg(feature = "uart")]
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub fn serialize_uart_proto(&self) -> Vec<u8> {
|
pub fn serialize_uart_proto(&self) -> Vec<u8> {
|
||||||
serialize_serial_msg(&Into::<msg::SerialOutputMsg>::into(*self))
|
serialize_serial_msg(&Into::<msg::SerialOutputMsg>::into(*self))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "denm")]
|
|
||||||
pub fn serialize_ble_proto(&self) -> Vec<u8> {
|
|
||||||
use prost::Message as _;
|
|
||||||
|
|
||||||
self.encode_to_vec()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl msg::CamEvent {
|
|
||||||
#[cfg(feature = "cam")]
|
|
||||||
pub fn serialize_ble_proto(&self) -> Vec<u8> {
|
|
||||||
use prost::Message as _;
|
|
||||||
|
|
||||||
self.encode_to_vec()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "uart")]
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct Parser {
|
pub struct Parser {
|
||||||
buffer: alloc::vec::Vec<u8>,
|
buffer: alloc::vec::Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "uart")]
|
|
||||||
impl Parser {
|
impl Parser {
|
||||||
const SOF_LEN: u16 = 4;
|
const SOF_LEN: u16 = 4;
|
||||||
const SOF1: u8 = 0x56;
|
const SOF1: u8 = 0x56;
|
||||||
|
|
@ -111,7 +91,7 @@ impl Parser {
|
||||||
Ok(data) => {
|
Ok(data) => {
|
||||||
output.push(data);
|
output.push(data);
|
||||||
}
|
}
|
||||||
Err(err) => log::error!("Failed to parse input: {err:?}"),
|
Err(err) => error!("Failed to parse input: {err:?}"),
|
||||||
}
|
}
|
||||||
|
|
||||||
// consume buffer
|
// consume buffer
|
||||||
|
|
@ -142,7 +122,6 @@ impl Parser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "uart")]
|
|
||||||
fn serialize_serial_msg<T>(msg: &T) -> Vec<u8>
|
fn serialize_serial_msg<T>(msg: &T) -> Vec<u8>
|
||||||
where
|
where
|
||||||
T: prost::Message,
|
T: prost::Message,
|
||||||
|
|
@ -162,7 +141,6 @@ where
|
||||||
out
|
out
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "uart")]
|
|
||||||
impl From<msg::PositionState> for crate::applogic::GnssFix {
|
impl From<msg::PositionState> for crate::applogic::GnssFix {
|
||||||
fn from(value: msg::PositionState) -> Self {
|
fn from(value: msg::PositionState) -> Self {
|
||||||
let time =
|
let time =
|
||||||
|
|
@ -191,7 +169,6 @@ impl From<msg::PositionState> for crate::applogic::GnssFix {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "uart")]
|
|
||||||
impl From<msg::PositionState> for esp32_cits_core::PosVel {
|
impl From<msg::PositionState> for esp32_cits_core::PosVel {
|
||||||
fn from(value: msg::PositionState) -> Self {
|
fn from(value: msg::PositionState) -> Self {
|
||||||
let position = geo_types::Point::new(
|
let position = geo_types::Point::new(
|
||||||
|
|
@ -217,7 +194,6 @@ impl From<msg::PositionState> for esp32_cits_core::PosVel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "uart")]
|
|
||||||
impl From<msg::ItsPosition> for esp32_cits_core::PosVel {
|
impl From<msg::ItsPosition> for esp32_cits_core::PosVel {
|
||||||
fn from(value: msg::ItsPosition) -> Self {
|
fn from(value: msg::ItsPosition) -> Self {
|
||||||
let latitude_deg = f64::from(value.latitude) / 10_000_000.;
|
let latitude_deg = f64::from(value.latitude) / 10_000_000.;
|
||||||
|
|
@ -232,7 +208,6 @@ impl From<msg::ItsPosition> for esp32_cits_core::PosVel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "uart")]
|
|
||||||
impl esp32_cits_core::tx::GnItsPayload for msg::RawMsgTx {
|
impl esp32_cits_core::tx::GnItsPayload for msg::RawMsgTx {
|
||||||
fn make_eh(
|
fn make_eh(
|
||||||
&self,
|
&self,
|
||||||
|
|
@ -248,8 +223,6 @@ impl esp32_cits_core::tx::GnItsPayload for msg::RawMsgTx {
|
||||||
),
|
),
|
||||||
alloc::string::String,
|
alloc::string::String,
|
||||||
> {
|
> {
|
||||||
use alloc::string::ToString as _;
|
|
||||||
|
|
||||||
let station_type = self
|
let station_type = self
|
||||||
.station_type
|
.station_type
|
||||||
.and_then(|v| {
|
.and_then(|v| {
|
||||||
|
|
@ -331,7 +304,6 @@ impl esp32_cits_core::tx::GnItsPayload for msg::RawMsgTx {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "uart")]
|
|
||||||
impl msg::RawMsgTx {
|
impl msg::RawMsgTx {
|
||||||
fn make_geobcast(
|
fn make_geobcast(
|
||||||
address: [u8; 6],
|
address: [u8; 6],
|
||||||
|
|
@ -412,189 +384,12 @@ impl msg::RawMsgTx {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "cam")]
|
|
||||||
impl From<alloc::boxed::Box<c_its_parser::standards::cam_1_4_1::cam_pdu_descriptions::CAM>>
|
|
||||||
for msg::CamEvent
|
|
||||||
{
|
|
||||||
fn from(
|
|
||||||
value: alloc::boxed::Box<c_its_parser::standards::cam_1_4_1::cam_pdu_descriptions::CAM>,
|
|
||||||
) -> Self {
|
|
||||||
use c_its_parser::standards::cam_1_4_1::cam_pdu_descriptions;
|
|
||||||
|
|
||||||
let station_id = value.header.station_id.0;
|
|
||||||
let station_type = u32::from(value.cam.cam_parameters.basic_container.station_type.0);
|
|
||||||
let position = value
|
|
||||||
.cam
|
|
||||||
.cam_parameters
|
|
||||||
.basic_container
|
|
||||||
.reference_position
|
|
||||||
.into();
|
|
||||||
|
|
||||||
let vehicle_role = value
|
|
||||||
.cam
|
|
||||||
.cam_parameters
|
|
||||||
.low_frequency_container
|
|
||||||
.and_then(|v| match v {
|
|
||||||
cam_pdu_descriptions::LowFrequencyContainer::basicVehicleContainerLowFrequency(
|
|
||||||
basic_vehicle_container_low_frequency,
|
|
||||||
) => Some(basic_vehicle_container_low_frequency.vehicle_role as u32),
|
|
||||||
_ => None,
|
|
||||||
});
|
|
||||||
|
|
||||||
let vehicle_data = match value.cam.cam_parameters.high_frequency_container {
|
|
||||||
cam_pdu_descriptions::HighFrequencyContainer::basicVehicleContainerHighFrequency(
|
|
||||||
basic_vehicle_container_high_frequency,
|
|
||||||
) => Some(basic_vehicle_container_high_frequency.into()),
|
|
||||||
_ => None,
|
|
||||||
};
|
|
||||||
|
|
||||||
Self {
|
|
||||||
station_id,
|
|
||||||
station_type,
|
|
||||||
position,
|
|
||||||
vehicle_role,
|
|
||||||
vehicle_data,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "cam")]
|
|
||||||
impl From<c_its_parser::standards::cam_1_4_1::cam_pdu_descriptions::BasicVehicleContainerHighFrequency> for msg::VehicleContainer {
|
|
||||||
fn from(value: c_its_parser::standards::cam_1_4_1::cam_pdu_descriptions::BasicVehicleContainerHighFrequency) -> Self {
|
|
||||||
let heading_deg = if value.heading.heading_value.is_unavailable() {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(u32::from(value.heading.heading_value.0))
|
|
||||||
};
|
|
||||||
let speed = if value.speed.speed_value.is_unavailable() {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(u32::from(value.speed.speed_value.0))
|
|
||||||
};
|
|
||||||
let vehicle_length_dm = if value.vehicle_length.vehicle_length_value.is_unavailable() {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(u32::from(value.vehicle_length.vehicle_length_value.0))
|
|
||||||
};
|
|
||||||
let vehicle_width_dm = if value.vehicle_width.is_unavailable() {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(u32::from(value.vehicle_width.0))
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
Self { heading_deg, speed, vehicle_length_dm, vehicle_width_dm }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "denm")]
|
|
||||||
impl From<alloc::boxed::Box<c_its_parser::standards::denm_2_2_1::denm_pdu_description::DENM>>
|
|
||||||
for msg::DenmEvent
|
|
||||||
{
|
|
||||||
fn from(
|
|
||||||
value: alloc::boxed::Box<c_its_parser::standards::denm_2_2_1::denm_pdu_description::DENM>,
|
|
||||||
) -> Self {
|
|
||||||
let denm_mgmt = &value.denm.management;
|
|
||||||
|
|
||||||
let station_id = value.header.station_id.0; // TODO: or from action ID?
|
|
||||||
|
|
||||||
let ref_time = chrono::DateTime::<chrono::Utc>::from(denm_mgmt.reference_time.clone());
|
|
||||||
let end_time = ref_time + chrono::Duration::seconds(denm_mgmt.validity_duration.0.into());
|
|
||||||
|
|
||||||
#[allow(clippy::cast_sign_loss)]
|
|
||||||
let timestamp = ref_time.timestamp_millis() as u64;
|
|
||||||
#[allow(clippy::cast_sign_loss)]
|
|
||||||
let validity_end_ts = end_time.timestamp_millis() as u64;
|
|
||||||
let seq_num = denm_mgmt.action_id.sequence_number.0.into();
|
|
||||||
|
|
||||||
let event_position = Some(denm_mgmt.event_position.clone().into());
|
|
||||||
let event_heading_deg = value
|
|
||||||
.denm
|
|
||||||
.location
|
|
||||||
.and_then(|v| v.event_position_heading)
|
|
||||||
.map(|v| {
|
|
||||||
#[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
|
|
||||||
let conv = v.value.as_deg() as u32;
|
|
||||||
conv
|
|
||||||
});
|
|
||||||
let direction = denm_mgmt
|
|
||||||
.traffic_direction
|
|
||||||
.map(|v| msg::TrafficDir::from(v) as i32);
|
|
||||||
let cc_tuple = value
|
|
||||||
.denm
|
|
||||||
.situation
|
|
||||||
.map(|v| v.event_type.cc_and_scc.to_u8_tuple());
|
|
||||||
let cause_code = cc_tuple.map(|v| v.0.into());
|
|
||||||
let sub_cause_code = cc_tuple.map(|v| v.1.into());
|
|
||||||
|
|
||||||
Self {
|
|
||||||
timestamp,
|
|
||||||
validity_end_ts,
|
|
||||||
station_id,
|
|
||||||
seq_num,
|
|
||||||
event_position,
|
|
||||||
event_heading_deg,
|
|
||||||
direction,
|
|
||||||
cause_code,
|
|
||||||
sub_cause_code,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<c_its_parser::standards::cdd_1_3_1_1::its_container::ReferencePosition>
|
|
||||||
for msg::Position
|
|
||||||
{
|
|
||||||
fn from(value: c_its_parser::standards::cdd_1_3_1_1::its_container::ReferencePosition) -> Self {
|
|
||||||
#[allow(clippy::cast_precision_loss, clippy::cast_possible_truncation)]
|
|
||||||
let latitude_deg = value.latitude.as_deg() as f32;
|
|
||||||
#[allow(clippy::cast_precision_loss, clippy::cast_possible_truncation)]
|
|
||||||
let longitude_deg = value.longitude.as_deg() as f32;
|
|
||||||
|
|
||||||
Self {
|
|
||||||
latitude_deg,
|
|
||||||
longitude_deg,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<c_its_parser::standards::cdd_2_2_1::etsi_its_cdd::ReferencePosition> for msg::Position {
|
|
||||||
fn from(value: c_its_parser::standards::cdd_2_2_1::etsi_its_cdd::ReferencePosition) -> Self {
|
|
||||||
#[allow(clippy::cast_precision_loss, clippy::cast_possible_truncation)]
|
|
||||||
let latitude_deg = value.latitude.as_deg() as f32;
|
|
||||||
#[allow(clippy::cast_precision_loss, clippy::cast_possible_truncation)]
|
|
||||||
let longitude_deg = value.longitude.as_deg() as f32;
|
|
||||||
|
|
||||||
Self {
|
|
||||||
latitude_deg,
|
|
||||||
longitude_deg,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<c_its_parser::standards::cdd_2_2_1::etsi_its_cdd::TrafficDirection> for msg::TrafficDir {
|
|
||||||
fn from(value: c_its_parser::standards::cdd_2_2_1::etsi_its_cdd::TrafficDirection) -> Self {
|
|
||||||
use c_its_parser::standards::cdd_2_2_1::etsi_its_cdd::TrafficDirection;
|
|
||||||
|
|
||||||
match value {
|
|
||||||
TrafficDirection::allTrafficDirections => Self::AllDirections,
|
|
||||||
TrafficDirection::sameAsReferenceDirection_upstreamOfReferencePosition => {
|
|
||||||
Self::Upstream
|
|
||||||
}
|
|
||||||
TrafficDirection::sameAsReferenceDirection_downstreamOfReferencePosition => {
|
|
||||||
Self::Downstream
|
|
||||||
}
|
|
||||||
TrafficDirection::oppositeToReferenceDirection => Self::Opposite,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::init_test_env_logger;
|
use crate::init_test_env_logger;
|
||||||
|
|
||||||
#[cfg(feature = "uart")]
|
|
||||||
impl From<msg::RawMsgTx> for msg::SerialInputMsg {
|
impl From<msg::RawMsgTx> for msg::SerialInputMsg {
|
||||||
fn from(value: msg::RawMsgTx) -> Self {
|
fn from(value: msg::RawMsgTx) -> Self {
|
||||||
use msg::serial_input_msg::Payload;
|
use msg::serial_input_msg::Payload;
|
||||||
|
|
@ -605,7 +400,6 @@ mod tests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "uart")]
|
|
||||||
impl From<msg::PositionState> for msg::SerialInputMsg {
|
impl From<msg::PositionState> for msg::SerialInputMsg {
|
||||||
fn from(value: msg::PositionState) -> Self {
|
fn from(value: msg::PositionState) -> Self {
|
||||||
use msg::serial_input_msg::Payload;
|
use msg::serial_input_msg::Payload;
|
||||||
|
|
@ -620,7 +414,6 @@ mod tests {
|
||||||
// SerialInputMsg(RawMsgTx): 5632582b0040123e0a340202c173256817284029d5b3400f1feaf01ffffffc23b7743e00000fc0007e8138250737feebfff600000dffff7ffff1ce40400010011807220028020d0a
|
// SerialInputMsg(RawMsgTx): 5632582b0040123e0a340202c173256817284029d5b3400f1feaf01ffffffc23b7743e00000fc0007e8138250737feebfff600000dffff7ffff1ce40400010011807220028020d0a
|
||||||
// SerialInputMsg(PositionState): 5632582b00170a1509a0bbe2a29f010000120a0d00002842150000b8410d0a
|
// SerialInputMsg(PositionState): 5632582b00170a1509a0bbe2a29f010000120a0d00002842150000b8410d0a
|
||||||
|
|
||||||
#[cfg(feature = "uart")]
|
|
||||||
#[test]
|
#[test]
|
||||||
fn uart_parser() {
|
fn uart_parser() {
|
||||||
// generate some test UART input messages
|
// generate some test UART input messages
|
||||||
|
|
|
||||||
31
src/main.rs
31
src/main.rs
|
|
@ -45,10 +45,9 @@ use log::{error, info, warn};
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
|
||||||
mod applogic;
|
mod applogic;
|
||||||
#[cfg(any(feature = "cam", feature = "denm"))]
|
|
||||||
mod ble;
|
|
||||||
mod cache;
|
mod cache;
|
||||||
mod geo_alg;
|
mod geo_alg;
|
||||||
|
#[cfg(feature = "uart")]
|
||||||
mod io;
|
mod io;
|
||||||
#[cfg(feature = "screen")]
|
#[cfg(feature = "screen")]
|
||||||
mod screen;
|
mod screen;
|
||||||
|
|
@ -90,7 +89,7 @@ static SERIAL: Mutex<RefCell<Option<esp_hal::uart::Uart<'static, esp_hal::Blocki
|
||||||
#[esp_rtos::main]
|
#[esp_rtos::main]
|
||||||
async fn main(spawner: Spawner) -> ! {
|
async fn main(spawner: Spawner) -> ! {
|
||||||
// generator version: 1.3.0
|
// generator version: 1.3.0
|
||||||
// generator parameters: --chip esp32c5 -o esp32c5-wroom-1-psram -o alloc -o log -o unstable-hal -o wifi -o esp-backtrace -o embassy -o ble-trouble
|
// generator parameters: --chip esp32c5 -o esp32c5-wroom-1-psram -o alloc -o log -o unstable-hal -o wifi -o esp-backtrace -o embassy
|
||||||
|
|
||||||
esp_println::logger::init_logger_from_env();
|
esp_println::logger::init_logger_from_env();
|
||||||
|
|
||||||
|
|
@ -108,8 +107,6 @@ async fn main(spawner: Spawner) -> ! {
|
||||||
// - GPIO28
|
// - GPIO28
|
||||||
|
|
||||||
esp_alloc::heap_allocator!(#[esp_hal::ram(reclaimed)] size: 65536);
|
esp_alloc::heap_allocator!(#[esp_hal::ram(reclaimed)] size: 65536);
|
||||||
// COEX needs more RAM - so we've added some more
|
|
||||||
esp_alloc::heap_allocator!(size: 64 * 1024);
|
|
||||||
esp_alloc::psram_allocator!(peripherals.PSRAM, esp_hal::psram);
|
esp_alloc::psram_allocator!(peripherals.PSRAM, esp_hal::psram);
|
||||||
|
|
||||||
let timg0 = TimerGroup::new(peripherals.TIMG0);
|
let timg0 = TimerGroup::new(peripherals.TIMG0);
|
||||||
|
|
@ -191,13 +188,6 @@ async fn main(spawner: Spawner) -> ! {
|
||||||
let mac = esp_hal::efuse::base_mac_address();
|
let mac = esp_hal::efuse::base_mac_address();
|
||||||
info!("WiFi MAC: {mac}");
|
info!("WiFi MAC: {mac}");
|
||||||
|
|
||||||
// Setup BLE
|
|
||||||
#[cfg(any(feature = "cam", feature = "denm"))]
|
|
||||||
{
|
|
||||||
let controller = ble::make_controller(peripherals.BT);
|
|
||||||
spawner.spawn(ble::run(controller).expect("Failed to spawn BLE task"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup GNSS:
|
// Setup GNSS:
|
||||||
// Seeed XIAO L67K:
|
// Seeed XIAO L67K:
|
||||||
// RX: D7/ GPIO12
|
// RX: D7/ GPIO12
|
||||||
|
|
@ -484,13 +474,6 @@ async fn main(spawner: Spawner) -> ! {
|
||||||
} => {
|
} => {
|
||||||
#[cfg(feature = "cam")]
|
#[cfg(feature = "cam")]
|
||||||
applogic::cam::handle_cam(&etsi);
|
applogic::cam::handle_cam(&etsi);
|
||||||
|
|
||||||
// Send data to BLE thread
|
|
||||||
#[cfg(feature = "cam")]
|
|
||||||
critical_section::with(|cs| {
|
|
||||||
let ble_update_ref = ble::TX_DATA.borrow(cs);
|
|
||||||
ble_update_ref.replace(Some(ble::BleSendable::Cam(etsi.into())));
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "denm")]
|
#[cfg(feature = "denm")]
|
||||||
|
|
@ -498,15 +481,7 @@ async fn main(spawner: Spawner) -> ! {
|
||||||
geonetworking: _,
|
geonetworking: _,
|
||||||
transport: _,
|
transport: _,
|
||||||
etsi,
|
etsi,
|
||||||
} => {
|
} => applogic::denm::handle_denm(&etsi),
|
||||||
applogic::denm::handle_denm(&etsi);
|
|
||||||
|
|
||||||
// Send data to BLE thread
|
|
||||||
critical_section::with(|cs| {
|
|
||||||
let ble_update_ref = ble::TX_DATA.borrow(cs);
|
|
||||||
ble_update_ref.replace(Some(ble::BleSendable::Denm(etsi.into())));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
#[cfg(feature = "denm")]
|
#[cfg(feature = "denm")]
|
||||||
ItsMessage::DenmV1 {
|
ItsMessage::DenmV1 {
|
||||||
geonetworking: _,
|
geonetworking: _,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue