Open jonas-schievink opened 5 years ago
A hard-coded primary service is now enumerated correctly. Next steps:
Removing milestone since service enumeration with one hard-coded service now works.
I've been using NimBLE for a few days, and think implementing a similar pattern for notifications would be a good idea, I'm going to start work on this over the next couple days and see where I get.
As promised may moons ago, here is an example layout that I think will work (hopefully this job is still relevant). I am not 100% certain of the actual parameters required, nor how they fit into the existing code. Hopefully you can make adjustments as required.
It also doesn't take into account Server vs Client, but I think Client is a subset of the traits and probably not much different.
struct Profile {}
trait GATTProfile {
fn get_uuid() -> UUID;
fn set_uuid(uuid: UUID);
fn get_profile_type() -> ProfileType;
fn get_profile_type(profie_type: ProfileType);
fn add_services(attr: GATTService);
fn get_services(uuid: UUID) -> & GATTService;
fn get_services(service_type: Option<ServiceType>) -> Vec<& GATTService>;
}
#[GATTService("UUID","ServiceType")]
struct Service {}
trait GATTService {
fn get_uuid() -> UUID;
fn set_uuid(uuid: UUID);
fn get_service_type() -> ServiceType;
fn get_service_type(profie_type: ServiceType);
fn add_characteristic(attr: GATTCharacteristic);
fn get_characteristic(uuid: UUID) -> & GATTCharacteristic;
fn get_characteristic() -> Vec<& GATTCharacteristic>;
}
#[GATTCharacteristic("UUID","Descriptor")]
struct Characteristic {
value: [u8]
}
trait GATTCharacteristic {
fn get_uuid() -> UUID;
fn set_uuid(uuid: UUID);
fn get_descriptor() -> String;
fn set_descriptor(descriptor: String);
fn get_value() -> [u8];
fn set_value(value: [u8]);
fn notify(func: Option<FnOnce(value: [u8])>);
fn indicate(func: Option<FnOnce(value: [u8])>);
}```
I can't say that I can help with the implementation, but I am happy to review any decisions.
@tl8roy Sorry, I'm not entirely sure what to make of that – we can't allocate memory, for example, and if the attributes are supposed to auto-implement the traits then they would need quite a bit more info to do so. For example the service needs to know all characteristics that are present at compile time to avoid allocations, but macros cannot access implemented traits or any values really.
The reason why I arrived at the approach described in https://github.com/jonas-schievink/rubble/issues/72 is that I don't think it will be very easy (if at all possible) to make procedural macros do the job in all cases here.
Your completely correct. I should have reread everything before posting. Let me have a think and see if I can abuse macros/types some more.
GATT is not it's own protocol, but means Generic Attribute Profile (even though the spec sometimes calls it Generic Attribute Protocol - I'm not making this shit up!). We have to implement whatever parts of ATT are needed by GATT.