esp32_nimble/server/
ble_advertisement_data.rs1use crate::{BLEDevice, enums::PowerType, utilities::BleUuid};
2use alloc::{string::String, vec::Vec};
3use esp_idf_svc::sys as esp_idf_sys;
4
5pub struct BLEAdvertisementData {
6 pub(crate) flags: u8,
8 service_uuids_16: Vec<esp_idf_sys::ble_uuid16_t>,
10 uuids16_is_complete: bool,
11 service_uuids_32: Vec<esp_idf_sys::ble_uuid32_t>,
13 uuids32_is_complete: bool,
14 service_uuids_128: Vec<esp_idf_sys::ble_uuid128_t>,
16 uuids128_is_complete: bool,
17 name: String,
19 name_is_complete: bool,
20 tx_pwr_lvl_is_present: bool,
22 svc_data_uuid16: Vec<u8>,
26 appearance: Option<u16>,
30 svc_data_uuid32: Vec<u8>,
34 svc_data_uuid128: Vec<u8>,
36 mfg_data: Vec<u8>,
39}
40
41impl BLEAdvertisementData {
42 pub fn new() -> Self {
43 Self {
44 flags: (esp_idf_sys::BLE_HS_ADV_F_DISC_GEN | esp_idf_sys::BLE_HS_ADV_F_BREDR_UNSUP)
45 as _,
46 service_uuids_16: Vec::new(),
47 uuids16_is_complete: true,
48 service_uuids_32: Vec::new(),
49 uuids32_is_complete: true,
50 service_uuids_128: Vec::new(),
51 uuids128_is_complete: true,
52 name: String::new(),
53 name_is_complete: true,
54 tx_pwr_lvl_is_present: false,
55 svc_data_uuid16: Vec::new(),
56 appearance: None,
57 svc_data_uuid32: Vec::new(),
58 svc_data_uuid128: Vec::new(),
59 mfg_data: Vec::new(),
60 }
61 }
62
63 pub fn name(&mut self, name: &str) -> &mut Self {
65 self.name.clear();
66 self.name.push_str(name);
67
68 self
69 }
70
71 pub fn add_service_uuid(&mut self, uuid: BleUuid) -> &mut Self {
72 let x = esp_idf_sys::ble_uuid_any_t::from(uuid);
73 match uuid {
74 BleUuid::Uuid16(_) => {
75 self.service_uuids_16.push(unsafe { x.u16_ });
76 }
77 BleUuid::Uuid32(_) => {
78 self.service_uuids_32.push(unsafe { x.u32_ });
79 }
80 BleUuid::Uuid128(_) => {
81 self.service_uuids_128.push(unsafe { x.u128_ });
82 }
83 }
84
85 self
86 }
87
88 pub fn service_data(&mut self, uuid: BleUuid, data: &[u8]) {
89 match uuid {
90 BleUuid::Uuid16(uuid) => {
91 self.svc_data_uuid16.clear();
92 self.svc_data_uuid16.extend_from_slice(&uuid.to_ne_bytes());
93 self.svc_data_uuid16.extend_from_slice(data);
94 }
95 BleUuid::Uuid32(uuid) => {
96 self.svc_data_uuid32.clear();
97 self.svc_data_uuid32.extend_from_slice(&uuid.to_ne_bytes());
98 self.svc_data_uuid32.extend_from_slice(data);
99 }
100 BleUuid::Uuid128(uuid) => {
101 self.svc_data_uuid128.clear();
102 self.svc_data_uuid128.extend_from_slice(&uuid);
103 self.svc_data_uuid128.extend_from_slice(data);
104 }
105 }
106 }
107
108 pub fn appearance(&mut self, appearance: u16) -> &mut Self {
110 self.appearance = Some(appearance);
111
112 self
113 }
114
115 pub fn add_tx_power(&mut self) -> &mut Self {
117 self.tx_pwr_lvl_is_present = true;
118
119 self
120 }
121
122 pub fn manufacturer_data(&mut self, data: &[u8]) -> &mut Self {
123 self.mfg_data.clear();
124 self.mfg_data.extend_from_slice(data);
125
126 self
127 }
128
129 pub(crate) fn payload_len(&self) -> usize {
130 let mut payload_len: usize = if self.flags > 0 { 2 + 1 } else { 0 };
131
132 if !self.service_uuids_16.is_empty() {
133 payload_len += 2 + 2 * self.service_uuids_16.len();
134 }
135 if !self.service_uuids_32.is_empty() {
136 payload_len += 2 + 4 * self.service_uuids_32.len();
137 }
138 if !self.service_uuids_128.is_empty() {
139 payload_len += 2 + 16 * self.service_uuids_128.len();
140 }
141
142 if !self.name.is_empty() {
143 payload_len += 2 + self.name.len();
144 }
145
146 if self.tx_pwr_lvl_is_present {
147 payload_len += 2 + (esp_idf_sys::BLE_HS_ADV_TX_PWR_LVL_LEN as usize);
148 }
149
150 if !self.svc_data_uuid16.is_empty() {
151 payload_len += 2 + self.svc_data_uuid16.len();
152 }
153
154 if !self.svc_data_uuid32.is_empty() {
155 payload_len += 2 + self.svc_data_uuid32.len();
156 }
157
158 if !self.svc_data_uuid128.is_empty() {
159 payload_len += 2 + self.svc_data_uuid128.len();
160 }
161
162 if self.appearance.is_some() {
163 payload_len += 2 + (esp_idf_sys::BLE_HS_ADV_APPEARANCE_LEN as usize);
164 }
165
166 if !self.mfg_data.is_empty() {
167 payload_len += 2 + self.mfg_data.len();
168 }
169
170 payload_len
179 }
180
181 pub(crate) fn as_ble_hs_adv_fields(&self) -> esp_idf_sys::ble_hs_adv_fields {
182 let mut ret = esp_idf_sys::ble_hs_adv_fields {
183 flags: self.flags,
184 ..Default::default()
185 };
186
187 if !self.service_uuids_16.is_empty() {
188 ret.set_uuids16_is_complete(self.uuids16_is_complete as _);
189 ret.uuids16 = self.service_uuids_16.as_ptr();
190 ret.num_uuids16 = self.service_uuids_16.len() as _;
191 }
192 if !self.service_uuids_32.is_empty() {
193 ret.set_uuids32_is_complete(self.uuids32_is_complete as _);
194 ret.uuids32 = self.service_uuids_32.as_ptr();
195 ret.num_uuids32 = self.service_uuids_32.len() as _;
196 }
197 if !self.service_uuids_128.is_empty() {
198 ret.set_uuids128_is_complete(self.uuids128_is_complete as _);
199 ret.uuids128 = self.service_uuids_128.as_ptr();
200 ret.num_uuids128 = self.service_uuids_128.len() as _;
201 }
202
203 if !self.name.is_empty() {
204 ret.name = self.name.as_ptr().cast();
205 ret.name_len = self.name.len() as _;
206 ret.set_name_is_complete(self.name_is_complete as _);
207 }
208
209 if self.tx_pwr_lvl_is_present {
210 ret.set_tx_pwr_lvl_is_present(1);
211 let ble_device = BLEDevice::take();
212 ret.tx_pwr_lvl = ble_device.get_power(PowerType::Advertising).to_dbm();
213 }
214
215 if !self.svc_data_uuid16.is_empty() {
216 ret.svc_data_uuid16 = self.svc_data_uuid16.as_ptr();
217 ret.svc_data_uuid16_len = self.svc_data_uuid16.len() as _;
218 }
219
220 if !self.svc_data_uuid32.is_empty() {
221 ret.svc_data_uuid32 = self.svc_data_uuid32.as_ptr();
222 ret.svc_data_uuid32_len = self.svc_data_uuid32.len() as _;
223 }
224
225 if !self.svc_data_uuid128.is_empty() {
226 ret.svc_data_uuid128 = self.svc_data_uuid128.as_ptr();
227 ret.svc_data_uuid128_len = self.svc_data_uuid128.len() as _;
228 }
229
230 if let Some(appearance) = self.appearance {
231 ret.set_appearance_is_present(1);
232 ret.appearance = appearance;
233 }
234
235 if !self.mfg_data.is_empty() {
236 ret.mfg_data = self.mfg_data.as_ptr();
237 ret.mfg_data_len = self.mfg_data.len() as _;
238 }
239
240 ret
241 }
242}