use std::sync::{Arc, RwLock};
use crate::gatt_server::service::Service;
use esp_idf_sys::*;
use log::debug;
#[derive(Debug, Clone)]
pub struct Profile {
name: Option<String>,
pub(crate) services: Vec<Arc<RwLock<Service>>>,
pub(crate) identifier: u16,
pub(crate) interface: Option<u8>,
}
impl Profile {
#[must_use]
pub const fn new(identifier: u16) -> Self {
Self {
name: None,
services: Vec::new(),
identifier,
interface: None,
}
}
pub fn name<S: Into<String>>(&mut self, name: S) -> &mut Self {
self.name = Some(name.into());
self
}
#[must_use]
pub fn service(&mut self, service: &Arc<RwLock<Service>>) -> &mut Self {
self.services.push(service.clone());
self
}
#[must_use]
pub fn build(&self) -> Arc<RwLock<Self>> {
Arc::new(RwLock::new(self.clone()))
}
pub(crate) fn get_service(&self, handle: u16) -> Option<Arc<RwLock<Service>>> {
for service in &self.services {
if service.read().unwrap().handle == Some(handle) {
return Some(service.clone());
}
}
None
}
pub(crate) fn get_service_by_id(&self, id: esp_gatt_id_t) -> Option<Arc<RwLock<Service>>> {
for service in &self.services {
if service.read().unwrap().uuid == id.into() {
return Some(service.clone());
}
}
None
}
pub(crate) fn register_self(&self) {
debug!("Registering {}.", self);
unsafe { esp_nofail!(esp_ble_gatts_app_register(self.identifier)) };
}
pub(crate) fn register_services(&mut self) {
debug!("Registering {}'s services.", &self);
self.services.iter_mut().for_each(|service| {
service
.write()
.unwrap()
.register_self(self.interface.unwrap());
});
}
}
impl std::fmt::Display for Profile {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{} (0x{:04x})",
self.name
.clone()
.unwrap_or_else(|| "Unnamed profile".to_string()),
self.identifier,
)
}
}