1use crate::types::*;
6
7use bt_common::{PeerId, Uuid};
8
9pub trait Client<T: crate::GattTypes> {
13 fn peer_id(&self) -> PeerId;
15
16 fn find_service(&self, uuid: Uuid) -> T::FindServicesFut;
21}
22
23pub trait PeerServiceHandle<T: crate::GattTypes> {
24 fn uuid(&self) -> Uuid;
25 fn is_primary(&self) -> bool;
26 fn connect(&self) -> T::ServiceConnectFut;
27}
28
29pub trait FromCharacteristic: Sized {
31 const UUID: Uuid;
32
33 fn from_chr(
35 characteristic: Characteristic,
36 value: &[u8],
37 ) -> ::core::result::Result<Self, bt_common::packet_encoding::Error>;
38
39 fn update(
42 &mut self,
43 new_value: &[u8],
44 ) -> ::core::result::Result<&mut Self, bt_common::packet_encoding::Error>;
45
46 fn try_read<T: crate::GattTypes>(
49 characteristic: Characteristic,
50 service: &T::PeerService,
51 ) -> impl futures::Future<Output = ::core::result::Result<Self, Error>> {
52 async move {
53 if characteristic.uuid != Self::UUID {
54 return Err(Error::ScanFailed("Wrong UUID".to_owned()));
55 }
56 let mut buf = [0; 128];
57 let (bytes, mut truncated) =
58 service.read_characteristic(&characteristic.handle, 0, &mut buf).await?;
59 let mut vec;
60 let buf_ptr = if truncated {
61 vec = Vec::with_capacity(bytes);
62 vec.copy_from_slice(&buf[..bytes]);
63 while truncated {
64 let (bytes, still_truncated) = service
65 .read_characteristic(&characteristic.handle, vec.len() as u16, &mut buf)
66 .await?;
67 vec.extend_from_slice(&buf[..bytes]);
68 truncated = still_truncated;
69 }
70 &vec[..]
71 } else {
72 &buf[..bytes]
73 };
74 Self::from_chr(characteristic, buf_ptr).map_err(Into::into)
75 }
76 }
77}
78
79#[derive(Debug, Clone)]
80pub struct CharacteristicNotification {
81 pub handle: Handle,
82 pub value: Vec<u8>,
83 pub maybe_truncated: bool,
84}
85
86pub trait PeerService<T: crate::GattTypes> {
89 fn discover_characteristics(&self, uuid: Option<Uuid>) -> T::CharacteristicDiscoveryFut;
95
96 fn read_characteristic<'a>(
102 &self,
103 handle: &Handle,
104 offset: u16,
105 buf: &'a mut [u8],
106 ) -> T::ReadFut<'a>;
107
108 fn write_characteristic<'a>(
109 &self,
110 handle: &Handle,
111 mode: WriteMode,
112 offset: u16,
113 buf: &'a [u8],
114 ) -> T::WriteFut<'a>;
115
116 fn read_descriptor<'a>(
117 &self,
118 handle: &Handle,
119 offset: u16,
120 buf: &'a mut [u8],
121 ) -> T::ReadFut<'a>;
122
123 fn write_descriptor<'a>(&self, handle: &Handle, offset: u16, buf: &'a [u8]) -> T::WriteFut<'a>;
124
125 fn subscribe(&self, handle: &Handle) -> T::NotificationStream;
134
135 }
137
138pub struct ServiceCharacteristic<'a, T: crate::GattTypes> {
140 service: &'a T::PeerService,
141 characteristic: Characteristic,
142 uuid: Uuid,
143}
144
145impl<'a, T: crate::GattTypes> ServiceCharacteristic<'a, T> {
146 pub async fn find(
147 service: &'a T::PeerService,
148 uuid: Uuid,
149 ) -> Result<Vec<ServiceCharacteristic<'a, T>>> {
150 let chrs = service.discover_characteristics(Some(uuid)).await?;
151 Ok(chrs.into_iter().map(|characteristic| Self { service, characteristic, uuid }).collect())
152 }
153
154 pub async fn read(&self, buf: &mut [u8]) -> Result<usize> {
155 self.service.read_characteristic(self.handle(), 0, buf).await.map(|(bytes, _)| bytes)
156 }
157
158 pub fn uuid(&self) -> Uuid {
159 self.uuid
160 }
161
162 pub fn handle(&self) -> &Handle {
163 &self.characteristic.handle
164 }
165
166 pub fn characteristic(&self) -> &Characteristic {
167 &self.characteristic
168 }
169}