Skip to content
This repository has been archived by the owner on Sep 6, 2023. It is now read-only.

Commit

Permalink
Merge branch 'hotfix/0.3.2'
Browse files Browse the repository at this point in the history
  • Loading branch information
persello committed Nov 10, 2022
2 parents f493c14 + 5928dd0 commit cacfaa0
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 37 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "bluedroid"
version = "0.3.1"
version = "0.3.2"
edition = "2021"
license = "MIT"
description = "A wrapper for the ESP32 Bluedroid Bluetooth stack."
Expand Down
19 changes: 18 additions & 1 deletion examples/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use lazy_static::lazy_static;
use log::info;

lazy_static! {
static ref VALUE: RwLock<Vec<u8>> = RwLock::new("Initial value".as_bytes().to_vec());
static ref VALUE: RwLock<Vec<u8>> = RwLock::new("Initial value.".as_bytes().to_vec());
}

fn main() {
Expand Down Expand Up @@ -42,6 +42,18 @@ fn main() {
.set_value("Initial value.".as_bytes().to_vec())
.build();

// A characteristic that notifies every second.
let indicating_characteristic = Characteristic::new(BleUuid::from_uuid128_string(
"c41d6f80-1a2c-11e9-ab14-d663bd873d93",
))
.name("Indicating Characteristic")
.permissions(AttributePermissions::new().read())
.properties(CharacteristicProperties::new().read().indicate())
.max_value_length(20)
.show_name()
.set_value("Initial value.".as_bytes().to_vec())
.build();

// A writable characteristic.
let writable_characteristic = Characteristic::new(BleUuid::from_uuid128_string(
"3c9a3f00-8ed3-4bdf-8a39-a01bebede295",
Expand All @@ -67,6 +79,7 @@ fn main() {
.primary()
.characteristic(&static_characteristic)
.characteristic(&notifying_characteristic)
.characteristic(&indicating_characteristic)
.characteristic(&writable_characteristic)
.build();

Expand All @@ -92,6 +105,10 @@ fn main() {
.write()
.unwrap()
.set_value(format!("Counter: {}", counter).as_bytes().to_vec());
indicating_characteristic
.write()
.unwrap()
.set_value(format!("Counter: {}", counter).as_bytes().to_vec());
std::thread::sleep(std::time::Duration::from_secs(1));
}
});
Expand Down
29 changes: 18 additions & 11 deletions src/gatt_server/characteristic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ pub struct Characteristic {
/// A buffer for keeping in memory the actual value of this characteristic.
pub(crate) internal_value: Vec<u8>,
/// The maximum length of the characteristic value.
max_value_length: u16,
max_value_length: Option<u16>,
/// A copy of the `control` property, in the `esp_attr_control_t` type, passed directly to the Bluetooth stack.
internal_control: esp_attr_control_t,
}
Expand All @@ -60,7 +60,7 @@ impl Characteristic {
properties: CharacteristicProperties::default(),
control: AttributeControl::AutomaticResponse(vec![0]),
internal_control: AttributeControl::AutomaticResponse(vec![0]).into(),
max_value_length: 8,
max_value_length: None,
}
}

Expand Down Expand Up @@ -92,7 +92,7 @@ impl Characteristic {

/// Sets the maximum length for the content of this characteristic. The default value is 8 bytes.
pub fn max_value_length(&mut self, length: u16) -> &mut Self {
self.max_value_length = length;
self.max_value_length = Some(length);
self
}

Expand Down Expand Up @@ -180,13 +180,20 @@ impl Characteristic {
pub fn set_value<T: Into<Vec<u8>>>(&mut self, value: T) -> &mut Self {
let value: Vec<u8> = value.into();

assert!(value.len() <= self.max_value_length as usize, "Value is too long for this characteristic and it can't be changed after starting the server.");

// If the characteristi hasn't been registered yet...
#[allow(clippy::cast_possible_truncation)]
if self.service_handle.is_none() {
// ...we can still change the value's maximum length.
self.max_value_length = value.len() as u16;
#[allow(clippy::manual_assert)]
if let Some(max_value_length) = self.max_value_length {
if value.len() > max_value_length as usize {
panic!(
"Value is too long for characteristic {}. The explicitly set maximum length is {} bytes.",
self, max_value_length
);
}
} else if self.attribute_handle.is_some() && value.len() > self.internal_value.len() {
panic!(
"Value is too long for characteristic {}. The implicitly set maximum length is {} bytes.",
self,
self.internal_value.len()
);
}

self.internal_value = value;
Expand Down Expand Up @@ -249,7 +256,7 @@ impl Characteristic {
self.permissions.into(),
self.properties.into(),
leaky_box_raw!(esp_attr_value_t {
attr_max_len: self.max_value_length,
attr_max_len: self.max_value_length.unwrap_or(self.internal_value.len() as u16),
attr_len: self.internal_value.len() as u16,
attr_value: self.internal_value.as_mut_slice().as_mut_ptr(),
}),
Expand Down
34 changes: 29 additions & 5 deletions src/gatt_server/gatts_event_handler.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#![allow(clippy::too_many_lines, clippy::if_not_else)]

use crate::{
gatt_server::{GattServer, Profile},
leaky_box_raw,
Expand Down Expand Up @@ -278,7 +280,7 @@ impl GattServer {
profile
.write()
.unwrap()
.gatts_event_handler(event, gatts_if, param)
.gatts_event_handler(event, gatts_if, param);
}
});
}
Expand Down Expand Up @@ -380,11 +382,16 @@ impl Profile {
esp_gatts_cb_event_t_ESP_GATTS_ADD_CHAR_DESCR_EVT => {
let param = unsafe { (*param).add_char_descr };

// ATTENTION: Descriptors might have duplicate UUIDs!
// We need to set them in order of creation.

if let Some(service) = self.get_service(param.service_handle) {
if let Some(descriptor) = service
.read()
.unwrap()
.get_descriptor_by_id(param.descr_uuid)
.get_descriptors_by_id(param.descr_uuid)
.iter()
.find(|d| d.read().unwrap().attribute_handle.is_none())
{
if param.status != esp_gatt_status_t_ESP_GATT_OK {
warn!("GATT descriptor registration failed.");
Expand All @@ -406,7 +413,7 @@ impl Profile {
esp_gatts_cb_event_t_ESP_GATTS_WRITE_EVT => {
let param = unsafe { (*param).write };

for service in self.services.iter() {
for service in &self.services {
service.read().unwrap().characteristics.iter().for_each(|characteristic| {
if characteristic.read().unwrap().attribute_handle == Some(param.handle) {
debug!(
Expand Down Expand Up @@ -537,13 +544,24 @@ impl Profile {
esp_gatts_cb_event_t_ESP_GATTS_READ_EVT => {
let param = unsafe { (*param).read };

for service in self.services.iter() {
debug!(
"MCC: Received read event for handle 0x{:04x}.",
param.handle
);

for service in &self.services {
service
.read()
.unwrap()
.characteristics
.iter()
.for_each(|characteristic| {
debug!(
"MCC: Checking characteristic {} ({:?}).",
characteristic.read().unwrap(),
characteristic.read().unwrap().attribute_handle
);

if characteristic.read().unwrap().attribute_handle == Some(param.handle)
{
debug!(
Expand Down Expand Up @@ -583,6 +601,12 @@ impl Profile {
} else {
characteristic.read().unwrap().descriptors.iter().for_each(
|descriptor| {
debug!(
"MCC: Checking descriptor {} ({:?}).",
descriptor.read().unwrap(),
descriptor.read().unwrap().attribute_handle
);

if descriptor.read().unwrap().attribute_handle
== Some(param.handle)
{
Expand Down Expand Up @@ -615,7 +639,7 @@ impl Profile {
value: response,
},
})
))
));
}
}
}
Expand Down
27 changes: 13 additions & 14 deletions src/gatt_server/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,20 +83,19 @@ impl Service {
.cloned()
}

pub(crate) fn get_descriptor_by_id(
&self,
id: esp_bt_uuid_t,
) -> Option<Arc<RwLock<Descriptor>>> {
for characteristic in &self.characteristics {
#[allow(clippy::significant_drop_in_scrutinee)]
for descriptor in characteristic.read().unwrap().clone().descriptors {
if descriptor.read().unwrap().uuid == id.into() {
return Some(descriptor);
}
}
}

None
pub(crate) fn get_descriptors_by_id(&self, id: esp_bt_uuid_t) -> Vec<Arc<RwLock<Descriptor>>> {
self.characteristics
.iter()
.filter_map(|characteristic| {
characteristic
.read()
.unwrap()
.clone()
.descriptors
.into_iter()
.find(|descriptor| descriptor.read().unwrap().uuid == id.into())
})
.collect()
}

pub(crate) fn register_self(&mut self, interface: u8) {
Expand Down
10 changes: 5 additions & 5 deletions src/utilities/ble_uuid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,30 +149,30 @@ impl From<esp_gatt_id_t> for BleUuid {
impl std::fmt::Display for BleUuid {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Uuid16(uuid) => write!(f, "0x{:04x}", uuid),
Self::Uuid32(uuid) => write!(f, "0x{:08x}", uuid),
Self::Uuid16(uuid) => write!(f, "0x{uuid:04x}"),
Self::Uuid32(uuid) => write!(f, "0x{uuid:08x}"),
Self::Uuid128(uuid) => {
let mut uuid = *uuid;
uuid.reverse();

let mut uuid_str = String::new();

for byte in &uuid {
uuid_str.push_str(&format!("{:02x}", byte));
uuid_str.push_str(&format!("{byte:02x}"));
}
uuid_str.insert(8, '-');
uuid_str.insert(13, '-');
uuid_str.insert(18, '-');
uuid_str.insert(23, '-');

write!(f, "{}", uuid_str)
write!(f, "{uuid_str}")
}
}
}
}

impl std::fmt::Debug for BleUuid {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self)
write!(f, "{self}")
}
}

0 comments on commit cacfaa0

Please sign in to comment.