1use std::rc::Rc;
6
7use bluetooth_traits::{BluetoothResponse, GATTType};
8use dom_struct::dom_struct;
9
10use crate::dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding::BluetoothRemoteGATTServerMethods;
11use crate::dom::bindings::codegen::Bindings::BluetoothRemoteGATTServiceBinding::BluetoothRemoteGATTServiceMethods;
12use crate::dom::bindings::error::Error;
13use crate::dom::bindings::reflector::reflect_dom_object;
14use crate::dom::bindings::root::{Dom, DomRoot};
15use crate::dom::bindings::str::DOMString;
16use crate::dom::bluetooth::{AsyncBluetoothListener, get_gatt_children};
17use crate::dom::bluetoothdevice::BluetoothDevice;
18use crate::dom::bluetoothuuid::{BluetoothCharacteristicUUID, BluetoothServiceUUID, BluetoothUUID};
19use crate::dom::eventtarget::EventTarget;
20use crate::dom::globalscope::GlobalScope;
21use crate::dom::promise::Promise;
22use crate::script_runtime::CanGc;
23
24#[dom_struct]
26pub(crate) struct BluetoothRemoteGATTService {
27 eventtarget: EventTarget,
28 device: Dom<BluetoothDevice>,
29 uuid: DOMString,
30 is_primary: bool,
31 instance_id: String,
32}
33
34impl BluetoothRemoteGATTService {
35 pub(crate) fn new_inherited(
36 device: &BluetoothDevice,
37 uuid: DOMString,
38 is_primary: bool,
39 instance_id: String,
40 ) -> BluetoothRemoteGATTService {
41 BluetoothRemoteGATTService {
42 eventtarget: EventTarget::new_inherited(),
43 device: Dom::from_ref(device),
44 uuid,
45 is_primary,
46 instance_id,
47 }
48 }
49
50 #[allow(non_snake_case)]
51 pub(crate) fn new(
52 global: &GlobalScope,
53 device: &BluetoothDevice,
54 uuid: DOMString,
55 isPrimary: bool,
56 instanceID: String,
57 can_gc: CanGc,
58 ) -> DomRoot<BluetoothRemoteGATTService> {
59 reflect_dom_object(
60 Box::new(BluetoothRemoteGATTService::new_inherited(
61 device, uuid, isPrimary, instanceID,
62 )),
63 global,
64 can_gc,
65 )
66 }
67
68 fn get_instance_id(&self) -> String {
69 self.instance_id.clone()
70 }
71}
72
73impl BluetoothRemoteGATTServiceMethods<crate::DomTypeHolder> for BluetoothRemoteGATTService {
74 fn Device(&self) -> DomRoot<BluetoothDevice> {
76 DomRoot::from_ref(&self.device)
77 }
78
79 fn IsPrimary(&self) -> bool {
81 self.is_primary
82 }
83
84 fn Uuid(&self) -> DOMString {
86 self.uuid.clone()
87 }
88
89 fn GetCharacteristic(
91 &self,
92 characteristic: BluetoothCharacteristicUUID,
93 can_gc: CanGc,
94 ) -> Rc<Promise> {
95 get_gatt_children(
96 self,
97 true,
98 BluetoothUUID::characteristic,
99 Some(characteristic),
100 self.get_instance_id(),
101 self.Device().get_gatt().Connected(),
102 GATTType::Characteristic,
103 can_gc,
104 )
105 }
106
107 fn GetCharacteristics(
109 &self,
110 characteristic: Option<BluetoothCharacteristicUUID>,
111 can_gc: CanGc,
112 ) -> Rc<Promise> {
113 get_gatt_children(
114 self,
115 false,
116 BluetoothUUID::characteristic,
117 characteristic,
118 self.get_instance_id(),
119 self.Device().get_gatt().Connected(),
120 GATTType::Characteristic,
121 can_gc,
122 )
123 }
124
125 fn GetIncludedService(&self, service: BluetoothServiceUUID, can_gc: CanGc) -> Rc<Promise> {
127 get_gatt_children(
128 self,
129 false,
130 BluetoothUUID::service,
131 Some(service),
132 self.get_instance_id(),
133 self.Device().get_gatt().Connected(),
134 GATTType::IncludedService,
135 can_gc,
136 )
137 }
138
139 fn GetIncludedServices(
141 &self,
142 service: Option<BluetoothServiceUUID>,
143 can_gc: CanGc,
144 ) -> Rc<Promise> {
145 get_gatt_children(
146 self,
147 false,
148 BluetoothUUID::service,
149 service,
150 self.get_instance_id(),
151 self.Device().get_gatt().Connected(),
152 GATTType::IncludedService,
153 can_gc,
154 )
155 }
156
157 event_handler!(serviceadded, GetOnserviceadded, SetOnserviceadded);
159
160 event_handler!(servicechanged, GetOnservicechanged, SetOnservicechanged);
162
163 event_handler!(serviceremoved, GetOnserviceremoved, SetOnserviceremoved);
165}
166
167impl AsyncBluetoothListener for BluetoothRemoteGATTService {
168 fn handle_response(&self, response: BluetoothResponse, promise: &Rc<Promise>, can_gc: CanGc) {
169 let device = self.Device();
170 match response {
171 BluetoothResponse::GetCharacteristics(characteristics_vec, single) => {
174 if single {
175 promise.resolve_native(
176 &device.get_or_create_characteristic(&characteristics_vec[0], self, can_gc),
177 can_gc,
178 );
179 return;
180 }
181 let mut characteristics = vec![];
182 for characteristic in characteristics_vec {
183 let bt_characteristic =
184 device.get_or_create_characteristic(&characteristic, self, can_gc);
185 characteristics.push(bt_characteristic);
186 }
187 promise.resolve_native(&characteristics, can_gc);
188 },
189 BluetoothResponse::GetIncludedServices(services_vec, single) => {
192 if single {
193 return promise.resolve_native(
194 &device.get_or_create_service(&services_vec[0], &device.get_gatt(), can_gc),
195 can_gc,
196 );
197 }
198 let mut services = vec![];
199 for service in services_vec {
200 let bt_service =
201 device.get_or_create_service(&service, &device.get_gatt(), can_gc);
202 services.push(bt_service);
203 }
204 promise.resolve_native(&services, can_gc);
205 },
206 _ => promise.reject_error(Error::Type("Something went wrong...".to_owned()), can_gc),
207 }
208 }
209}