ble: Add device information service
This commit is contained in:
parent
cd84754465
commit
dc54b55230
4 changed files with 152 additions and 1 deletions
22
build.rs
22
build.rs
|
|
@ -9,6 +9,7 @@ fn main() -> std::io::Result<()> {
|
|||
println!("cargo:rustc-link-arg=-Tlinkall.x");
|
||||
}
|
||||
|
||||
// compile protobuf definition to rust code
|
||||
let descriptor_path =
|
||||
std::path::PathBuf::from(env::var("OUT_DIR").unwrap()).join("proto_descriptor.bin");
|
||||
|
||||
|
|
@ -17,6 +18,27 @@ fn main() -> std::io::Result<()> {
|
|||
.compile_well_known_types()
|
||||
.compile_protos(&["docs/c_its-messages.proto"], &["docs/"])?;
|
||||
|
||||
// get git revision
|
||||
println!("cargo:rustc-rerun-if-changed=.git/HEAD");
|
||||
|
||||
// length:
|
||||
// - tag name: 6-8 chars (v0.1.0 to v1.23.42)
|
||||
// - offset+hash: 0-12 chars (up to 99 commits from tag + 8 char hash)
|
||||
// - SUM: 6-20
|
||||
let git_output = std::process::Command::new("git")
|
||||
.args(["describe", "--tags", "--match", "v*", "--always"])
|
||||
.output()
|
||||
.unwrap();
|
||||
assert!(
|
||||
git_output.stderr.is_empty(),
|
||||
"{}",
|
||||
String::from_utf8(git_output.stderr).unwrap()
|
||||
);
|
||||
println!(
|
||||
"cargo:rustc-env=GIT_REVISION={}",
|
||||
String::from_utf8(git_output.stdout).unwrap()
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
|||
80
src/ble.rs
80
src/ble.rs
|
|
@ -39,9 +39,73 @@ pub enum BleSendable {
|
|||
SpatemRaw(io::msg::RawMsgRx),
|
||||
}
|
||||
|
||||
pub const DIS_SERIAL_MAX_LEN: usize = 17;
|
||||
pub const DIS_FW_REVISION_MAX_LEN: usize = 20; // git-describe
|
||||
pub const DIS_SW_REVISION_MAX_LEN: usize = 66; // max length of get_feature_list, joined with comma
|
||||
|
||||
pub struct DeviceInfo {
|
||||
/// WiFi MAC
|
||||
pub serial_number: [u8; DIS_SERIAL_MAX_LEN],
|
||||
/// git tag/ revision
|
||||
pub fw_revision: [u8; DIS_FW_REVISION_MAX_LEN],
|
||||
/// used for feature flags
|
||||
pub sw_revision: [u8; DIS_SW_REVISION_MAX_LEN],
|
||||
}
|
||||
|
||||
impl DeviceInfo {
|
||||
pub fn new(serial_number: &str, fw_revision: &str, sw_revision: &str) -> Self {
|
||||
Self {
|
||||
serial_number: string_as_padded_buf(serial_number, DIS_SERIAL_MAX_LEN)
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
fw_revision: string_as_padded_buf(fw_revision, DIS_FW_REVISION_MAX_LEN)
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
sw_revision: string_as_padded_buf(sw_revision, DIS_SW_REVISION_MAX_LEN)
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn string_as_padded_buf(value: &str, length: usize) -> alloc::vec::Vec<u8> {
|
||||
let buf = value.as_bytes();
|
||||
let buf_len = buf.len();
|
||||
|
||||
// cut buffer at maximum length or pad with whitespace
|
||||
if buf_len > length {
|
||||
buf[..length].to_vec()
|
||||
} else {
|
||||
let padding_len = length - buf_len;
|
||||
let padding = alloc::vec![b' '; padding_len];
|
||||
|
||||
[buf, &padding].concat()
|
||||
}
|
||||
}
|
||||
|
||||
#[gatt_server]
|
||||
struct Server {
|
||||
c_its_events: CITSEvents,
|
||||
device_info_service: DeviceInfoService,
|
||||
}
|
||||
|
||||
#[gatt_service(uuid = service::DEVICE_INFORMATION)]
|
||||
struct DeviceInfoService {
|
||||
/// Manufacturer name
|
||||
#[characteristic(uuid = characteristic::MANUFACTURER_NAME_STRING, read, value = "jtbx")]
|
||||
mfg_name: &'static str,
|
||||
/// Model number
|
||||
#[characteristic(uuid = characteristic::MODEL_NUMBER_STRING, read, value = "ESP32-C5 C-ITS Companion")]
|
||||
model_number: &'static str,
|
||||
// Serial Number String
|
||||
#[characteristic(uuid = characteristic::SERIAL_NUMBER_STRING, read, value = [0u8; DIS_SERIAL_MAX_LEN])]
|
||||
serial_number: [u8; DIS_SERIAL_MAX_LEN],
|
||||
// Firmware Revision String
|
||||
#[characteristic(uuid = characteristic::FIRMWARE_REVISION_STRING, read, value = [0u8; DIS_FW_REVISION_MAX_LEN])]
|
||||
fw_revision: [u8; DIS_FW_REVISION_MAX_LEN],
|
||||
// Software Revision String
|
||||
#[characteristic(uuid = characteristic::SOFTWARE_REVISION_STRING, read, value = [0u8; DIS_SW_REVISION_MAX_LEN])]
|
||||
sw_revision: [u8; DIS_SW_REVISION_MAX_LEN],
|
||||
}
|
||||
|
||||
#[gatt_service(uuid = "c0b70000-d4f4-4000-ada8-f99a02ee315c")]
|
||||
|
|
@ -111,6 +175,7 @@ pub async fn run(
|
|||
>,
|
||||
name: alloc::string::String,
|
||||
short_name: alloc::string::String,
|
||||
device_info: DeviceInfo,
|
||||
) {
|
||||
let mut resources: HostResources<DefaultPacketPool, CONNECTIONS_MAX, L2CAP_CHANNELS_MAX> =
|
||||
HostResources::new();
|
||||
|
|
@ -132,6 +197,21 @@ pub async fn run(
|
|||
}))
|
||||
.unwrap();
|
||||
|
||||
// set "dynamic" device info data
|
||||
let _ = server
|
||||
.device_info_service
|
||||
.serial_number
|
||||
.set(&server, &device_info.serial_number);
|
||||
let _ = server
|
||||
.device_info_service
|
||||
.fw_revision
|
||||
.set(&server, &device_info.fw_revision);
|
||||
let _ = server
|
||||
.device_info_service
|
||||
.sw_revision
|
||||
.set(&server, &device_info.sw_revision);
|
||||
|
||||
// advertise and run update logic
|
||||
let _ = embassy_futures::join::join(ble_task(runner), async {
|
||||
loop {
|
||||
match advertise(&mut peripheral, &server, &short_name).await {
|
||||
|
|
|
|||
13
src/main.rs
13
src/main.rs
|
|
@ -228,7 +228,18 @@ async fn main(spawner: Spawner) -> ! {
|
|||
serial[2]
|
||||
);
|
||||
let short_name = alloc::format!("V2X {:02x}{:02x}", serial[1], serial[2]); // max 8 chars!
|
||||
spawner.spawn(ble::run(controller, name, short_name).expect("Failed to spawn BLE task"));
|
||||
|
||||
let fw_revision = core::env!("GIT_REVISION");
|
||||
let sw_revision = util::get_feature_list().join(",");
|
||||
spawner.spawn(
|
||||
ble::run(
|
||||
controller,
|
||||
name,
|
||||
short_name,
|
||||
ble::DeviceInfo::new(&mac.to_string(), fw_revision, &sw_revision),
|
||||
)
|
||||
.expect("Failed to spawn BLE task"),
|
||||
);
|
||||
}
|
||||
|
||||
// Setup GNSS:
|
||||
|
|
|
|||
38
src/util.rs
38
src/util.rs
|
|
@ -31,3 +31,41 @@ pub(crate) fn get_tx_feature_list() -> Vec<&'static str> {
|
|||
|
||||
features
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub(crate) fn get_feature_list() -> Vec<&'static str> {
|
||||
let mut features = alloc::vec![];
|
||||
|
||||
if cfg!(feature = "gnss_ubx") {
|
||||
features.push("gnss_ubx");
|
||||
}
|
||||
if cfg!(feature = "gnss_l67k") {
|
||||
features.push("gnss_l67k");
|
||||
}
|
||||
if cfg!(feature = "cam_tx") {
|
||||
features.push("cam_tx");
|
||||
}
|
||||
if cfg!(feature = "cam") {
|
||||
features.push("cam");
|
||||
}
|
||||
if cfg!(feature = "denm") {
|
||||
features.push("denm");
|
||||
}
|
||||
if cfg!(feature = "spat") {
|
||||
features.push("spat");
|
||||
}
|
||||
if cfg!(feature = "spat_debug") {
|
||||
features.push("spat_debug");
|
||||
}
|
||||
if cfg!(feature = "screen") {
|
||||
features.push("screen");
|
||||
}
|
||||
if cfg!(feature = "uart") {
|
||||
features.push("uart");
|
||||
}
|
||||
if cfg!(feature = "ble") {
|
||||
features.push("ble");
|
||||
}
|
||||
|
||||
features
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue