xref: /btstack/port/arduino/examples/LECentral/LECentral.ino (revision 8caefee39d444df6d8908a96a844825f10fbdaa4)
1*8caefee3SMatthias Ringwald#include <BTstack.h>
2*8caefee3SMatthias Ringwald#include <SPI.h>
3*8caefee3SMatthias Ringwald
4*8caefee3SMatthias Ringwald/*
5*8caefee3SMatthias Ringwald * EXAMPLE_START(LECentral): LE Central
6*8caefee3SMatthias Ringwald *
7*8caefee3SMatthias Ringwald * @text Compared with the other examples, the LE Central is
8*8caefee3SMatthias Ringwald * a bit more complex. This is because it performs multiple
9*8caefee3SMatthias Ringwald * steps in sequence as it is common with GATT Client APIs.
10*8caefee3SMatthias Ringwald *
11*8caefee3SMatthias Ringwald * It shows how to first scan for other
12*8caefee3SMatthias Ringwald * devices and then connect to one. When connected, a series of
13*8caefee3SMatthias Ringwald * GATT Client operations are performed: first the list of
14*8caefee3SMatthias Ringwald * GATT Services is queried. If a particular service is found,
15*8caefee3SMatthias Ringwald * the list of its GATT Characteristics is retrieved and a set
16*8caefee3SMatthias Ringwald * of known Characteristics are cached for later access.
17*8caefee3SMatthias Ringwald */
18*8caefee3SMatthias Ringwald
19*8caefee3SMatthias Ringwald/*
20*8caefee3SMatthias Ringwald * @section Characteristic Summary
21*8caefee3SMatthias Ringwald * @text As multiple Characteristics need to be found, a custom
22*8caefee3SMatthias Ringwald * struct is used to collect all information about it. This allows
23*8caefee3SMatthias Ringwald * to defined the list of neccessary characteristics in the
24*8caefee3SMatthias Ringwald * characteristics[] array
25*8caefee3SMatthias Ringwald */
26*8caefee3SMatthias Ringwald/* LISTING_START(LECentralSummary): Characteristic Summary */
27*8caefee3SMatthias Ringwald
28*8caefee3SMatthias Ringwald// BLE Shield Service V2 incl. used Characteristics
29*8caefee3SMatthias RingwaldUUID bleShieldServiceV2UUID("B8E06067-62AD-41BA-9231-206AE80AB550");
30*8caefee3SMatthias Ringwald
31*8caefee3SMatthias Ringwaldtypedef struct characteristic_summary {
32*8caefee3SMatthias Ringwald    UUID         uuid;
33*8caefee3SMatthias Ringwald    const char * name;
34*8caefee3SMatthias Ringwald    bool         found;
35*8caefee3SMatthias Ringwald    BLECharacteristic characteristic;
36*8caefee3SMatthias Ringwald} characteristic_summary_t;
37*8caefee3SMatthias Ringwald
38*8caefee3SMatthias Ringwaldtypedef enum characteristicIDs {
39*8caefee3SMatthias Ringwald    charRX = 0,
40*8caefee3SMatthias Ringwald    charTX,
41*8caefee3SMatthias Ringwald    charBaud,
42*8caefee3SMatthias Ringwald    charBdAddr,
43*8caefee3SMatthias Ringwald    numCharacteristics  /* last one */
44*8caefee3SMatthias Ringwald} characteristicIDs_t;
45*8caefee3SMatthias Ringwald
46*8caefee3SMatthias Ringwaldcharacteristic_summary characteristics[] = {
47*8caefee3SMatthias Ringwald    { UUID("f897177b-aee8-4767-8ecc-cc694fd5fcee"), "RX"       },
48*8caefee3SMatthias Ringwald    { UUID("bf45e40a-de2a-4bc8-bba0-e5d6065f1b4b"), "TX"       },
49*8caefee3SMatthias Ringwald    { UUID("2fbc0f31-726a-4014-b9fe-c8be0652e982"), "Baudrate" },
50*8caefee3SMatthias Ringwald    { UUID("65c228da-bad1-4f41-b55f-3d177f4e2196"), "BD ADDR"  }
51*8caefee3SMatthias Ringwald};
52*8caefee3SMatthias Ringwald
53*8caefee3SMatthias Ringwald/* LISTING_END(LECentralSummary): Characteristic Summary */
54*8caefee3SMatthias Ringwald
55*8caefee3SMatthias Ringwald// Application state
56*8caefee3SMatthias RingwaldBLEDevice  myBLEDevice;
57*8caefee3SMatthias RingwaldBLEService myBLEService;
58*8caefee3SMatthias Ringwaldbool serviceFound;
59*8caefee3SMatthias Ringwaldbool sendCounter = false;
60*8caefee3SMatthias Ringwald
61*8caefee3SMatthias Ringwaldint counter = 0;
62*8caefee3SMatthias Ringwaldchar counterString[20];
63*8caefee3SMatthias Ringwald
64*8caefee3SMatthias Ringwaldstatic timer_source_t heartbeat;
65*8caefee3SMatthias Ringwald
66*8caefee3SMatthias Ringwald/*
67*8caefee3SMatthias Ringwald * @section Setup
68*8caefee3SMatthias Ringwald * @text In the setup, various callbacks are registered. After that
69*8caefee3SMatthias Ringwald * we start scanning for other devices
70*8caefee3SMatthias Ringwald */
71*8caefee3SMatthias Ringwald/* LISTING_START(LECentralSetup): LE Central Setup */
72*8caefee3SMatthias Ringwald void setup(void){
73*8caefee3SMatthias Ringwald    Serial.begin(9600);
74*8caefee3SMatthias Ringwald    BTstack.setBLEAdvertisementCallback(advertisementCallback);
75*8caefee3SMatthias Ringwald    BTstack.setBLEDeviceConnectedCallback(deviceConnectedCallback);
76*8caefee3SMatthias Ringwald    BTstack.setBLEDeviceDisconnectedCallback(deviceDisconnectedCallback);
77*8caefee3SMatthias Ringwald    BTstack.setGATTServiceDiscoveredCallback(gattServiceDiscovered);
78*8caefee3SMatthias Ringwald    BTstack.setGATTCharacteristicDiscoveredCallback(gattCharacteristicDiscovered);
79*8caefee3SMatthias Ringwald    BTstack.setGATTCharacteristicNotificationCallback(gattCharacteristicNotification);
80*8caefee3SMatthias Ringwald    BTstack.setGATTCharacteristicReadCallback(gattReadCallback);
81*8caefee3SMatthias Ringwald    BTstack.setGATTCharacteristicWrittenCallback(gattWrittenCallback);
82*8caefee3SMatthias Ringwald    BTstack.setGATTCharacteristicSubscribedCallback(gattSubscribedCallback);
83*8caefee3SMatthias Ringwald    BTstack.setup();
84*8caefee3SMatthias Ringwald    BTstack.bleStartScanning();
85*8caefee3SMatthias Ringwald}
86*8caefee3SMatthias Ringwald/* LISTING_END(LECentralSetup): LE Central Setup */
87*8caefee3SMatthias Ringwald
88*8caefee3SMatthias Ringwald/*
89*8caefee3SMatthias Ringwald * @section Loop
90*8caefee3SMatthias Ringwald *
91*8caefee3SMatthias Ringwald * @text In the standard Arduino loop() function, BTstack's loop() is called first
92*8caefee3SMatthias Ringwald * If we're connected, we send the string "BTstack" plus a counter as fast as possible.
93*8caefee3SMatthias Ringwald * As the Bluetooth module might be busy, it's important to check the result of the
94*8caefee3SMatthias Ringwald * writeCharacteristicWithoutResponse() call. If it's not ok, we just try again in the
95*8caefee3SMatthias Ringwald * next loop iteration.
96*8caefee3SMatthias Ringwald */
97*8caefee3SMatthias Ringwald/* LISTING_START(LECentralLoop): Loop */
98*8caefee3SMatthias Ringwaldvoid loop(void){
99*8caefee3SMatthias Ringwald    BTstack.loop();
100*8caefee3SMatthias Ringwald
101*8caefee3SMatthias Ringwald    // send counter as fast as possible
102*8caefee3SMatthias Ringwald    if (sendCounter){
103*8caefee3SMatthias Ringwald        sprintf(counterString, "BTstack %u\n", counter);
104*8caefee3SMatthias Ringwald        int result = myBLEDevice.writeCharacteristicWithoutResponse(&characteristics[charTX].characteristic, (uint8_t*) counterString, strlen(counterString) );
105*8caefee3SMatthias Ringwald        if (result == BLE_PERIPHERAL_OK){
106*8caefee3SMatthias Ringwald            Serial.print("Wrote without response: ");
107*8caefee3SMatthias Ringwald            Serial.println(counterString);
108*8caefee3SMatthias Ringwald            counter++;
109*8caefee3SMatthias Ringwald        }
110*8caefee3SMatthias Ringwald    }
111*8caefee3SMatthias Ringwald}
112*8caefee3SMatthias Ringwald/* LISTING_END(LECentralLoop): Loop */
113*8caefee3SMatthias Ringwald
114*8caefee3SMatthias Ringwald/*
115*8caefee3SMatthias Ringwald * @section Advertisement Callback
116*8caefee3SMatthias Ringwald *
117*8caefee3SMatthias Ringwald * @text When an Advertisement is received, we check if it contains
118*8caefee3SMatthias Ringwald * the UUID of the service we're interested in. Only a single service
119*8caefee3SMatthias Ringwald * with a 128-bit UUID can be contained in and Advertisement and not
120*8caefee3SMatthias Ringwald * all BLE devices provides this. Other options are to match on the
121*8caefee3SMatthias Ringwald * reported device name or the BD ADDR prefix.
122*8caefee3SMatthias Ringwald *
123*8caefee3SMatthias Ringwald * If we found an interesting device, we try to connect to it.
124*8caefee3SMatthias Ringwald */
125*8caefee3SMatthias Ringwald/* LISTING_START(LECentralAdvertisementCallback): Advertisement Callback */
126*8caefee3SMatthias Ringwaldvoid advertisementCallback(BLEAdvertisement *bleAdvertisement) {
127*8caefee3SMatthias Ringwald    Serial.print("Device discovered: ");
128*8caefee3SMatthias Ringwald    Serial.print(bleAdvertisement->getBdAddr()->getAddressString());
129*8caefee3SMatthias Ringwald    Serial.print(", RSSI: ");
130*8caefee3SMatthias Ringwald    Serial.println(bleAdvertisement->getRssi());
131*8caefee3SMatthias Ringwald    if (bleAdvertisement->containsService(&bleShieldServiceV2UUID)) {
132*8caefee3SMatthias Ringwald        Serial.println("\nBLE ShieldService V2 found!\n");
133*8caefee3SMatthias Ringwald        BTstack.bleStopScanning();
134*8caefee3SMatthias Ringwald        BTstack.bleConnect(bleAdvertisement, 10000);  // 10 s
135*8caefee3SMatthias Ringwald    }
136*8caefee3SMatthias Ringwald}
137*8caefee3SMatthias Ringwald/* LISTING_END(LECentralAdvertisementCallback): Advertisement Callback */
138*8caefee3SMatthias Ringwald
139*8caefee3SMatthias Ringwald/*
140*8caefee3SMatthias Ringwald * @section Device Connected Callback
141*8caefee3SMatthias Ringwald *
142*8caefee3SMatthias Ringwald * @text At the end of bleConnect(), the device connected callback is callec.
143*8caefee3SMatthias Ringwald * The status argument tells if the connection timed out, or if the connection
144*8caefee3SMatthias Ringwald * was established successfully.
145*8caefee3SMatthias Ringwald *
146*8caefee3SMatthias Ringwald * On a successful connection, a GATT Service Discovery is started.
147*8caefee3SMatthias Ringwald */
148*8caefee3SMatthias Ringwald/* LISTING_START(LECentralDeviceConnectedCallback): Device Connected Callback */
149*8caefee3SMatthias Ringwaldvoid deviceConnectedCallback(BLEStatus status, BLEDevice *device) {
150*8caefee3SMatthias Ringwald    switch (status){
151*8caefee3SMatthias Ringwald        case BLE_STATUS_OK:
152*8caefee3SMatthias Ringwald            Serial.println("Device connected!");
153*8caefee3SMatthias Ringwald            myBLEDevice = *device;
154*8caefee3SMatthias Ringwald            counter = 0;
155*8caefee3SMatthias Ringwald            myBLEDevice.discoverGATTServices();
156*8caefee3SMatthias Ringwald            break;
157*8caefee3SMatthias Ringwald        case BLE_STATUS_CONNECTION_TIMEOUT:
158*8caefee3SMatthias Ringwald            Serial.println("Error while Connecting the Peripheral");
159*8caefee3SMatthias Ringwald            BTstack.bleStartScanning();
160*8caefee3SMatthias Ringwald            break;
161*8caefee3SMatthias Ringwald        default:
162*8caefee3SMatthias Ringwald            break;
163*8caefee3SMatthias Ringwald    }
164*8caefee3SMatthias Ringwald}
165*8caefee3SMatthias Ringwald/* LISTING_END(LECentralDeviceConnectedCallback): Device Connected Callback */
166*8caefee3SMatthias Ringwald
167*8caefee3SMatthias Ringwald/*
168*8caefee3SMatthias Ringwald * @section Device Disconnected Callback
169*8caefee3SMatthias Ringwald *
170*8caefee3SMatthias Ringwald * @text If the connection to a device breaks, the device disconnected callback
171*8caefee3SMatthias Ringwald * is called. Here, we start scanning for new devices again.
172*8caefee3SMatthias Ringwald */
173*8caefee3SMatthias Ringwald/* LISTING_START(LECentralDeviceDisconnectedCallback): Device Disconnected Callback */
174*8caefee3SMatthias Ringwaldvoid deviceDisconnectedCallback(BLEDevice * device){
175*8caefee3SMatthias Ringwald    Serial.println("Disconnected, starting over..");
176*8caefee3SMatthias Ringwald    sendCounter = false;
177*8caefee3SMatthias Ringwald    BTstack.bleStartScanning();
178*8caefee3SMatthias Ringwald}
179*8caefee3SMatthias Ringwald/* LISTING_END(LECentralDeviceDisconnectedCallback): Device Disconnected Callback */
180*8caefee3SMatthias Ringwald
181*8caefee3SMatthias Ringwald/*
182*8caefee3SMatthias Ringwald * @section Service Discovered Callback
183*8caefee3SMatthias Ringwald *
184*8caefee3SMatthias Ringwald * @text The service discovered callback is called for each service and after the
185*8caefee3SMatthias Ringwald * service discovery is complete. The status argument is provided for this.
186*8caefee3SMatthias Ringwald *
187*8caefee3SMatthias Ringwald * The main information about a discovered Service is its UUID.
188*8caefee3SMatthias Ringwald * If we find our service, we store the reference to this service.
189*8caefee3SMatthias Ringwald * This allows to discover the Characteristics for our service after
190*8caefee3SMatthias Ringwald * the service discovery is complete.
191*8caefee3SMatthias Ringwald */
192*8caefee3SMatthias Ringwald/* LISTING_START(LECentralServiceDiscoveredCallback): Service Discovered Callback */
193*8caefee3SMatthias Ringwaldvoid gattServiceDiscovered(BLEStatus status, BLEDevice *device, BLEService *bleService) {
194*8caefee3SMatthias Ringwald    switch(status){
195*8caefee3SMatthias Ringwald        case BLE_STATUS_OK:
196*8caefee3SMatthias Ringwald            Serial.print("Service Discovered: :");
197*8caefee3SMatthias Ringwald            Serial.println(bleService->getUUID()->getUuidString());
198*8caefee3SMatthias Ringwald            if (bleService->matches(&bleShieldServiceV2UUID)) {
199*8caefee3SMatthias Ringwald                serviceFound = true;
200*8caefee3SMatthias Ringwald                Serial.println("Our service located!");
201*8caefee3SMatthias Ringwald                myBLEService = *bleService;
202*8caefee3SMatthias Ringwald            }
203*8caefee3SMatthias Ringwald            break;
204*8caefee3SMatthias Ringwald        case BLE_STATUS_DONE:
205*8caefee3SMatthias Ringwald            Serial.println("Service discovery finished");
206*8caefee3SMatthias Ringwald            if (serviceFound) {
207*8caefee3SMatthias Ringwald                device->discoverCharacteristicsForService(&myBLEService);
208*8caefee3SMatthias Ringwald            }
209*8caefee3SMatthias Ringwald            break;
210*8caefee3SMatthias Ringwald        default:
211*8caefee3SMatthias Ringwald            Serial.println("Service discovery error");
212*8caefee3SMatthias Ringwald            break;
213*8caefee3SMatthias Ringwald    }
214*8caefee3SMatthias Ringwald}
215*8caefee3SMatthias Ringwald/* LISTING_END(LECentralServiceDiscoveredCallback): Service Discovered Callback */
216*8caefee3SMatthias Ringwald
217*8caefee3SMatthias Ringwald/*
218*8caefee3SMatthias Ringwald * @section Characteristic Discovered Callback
219*8caefee3SMatthias Ringwald *
220*8caefee3SMatthias Ringwald * @text Similar to the Service Discovered callback, the Characteristic Discovered
221*8caefee3SMatthias Ringwald * callback is called for each Characteristic found and after the discovery is complete.
222*8caefee3SMatthias Ringwald *
223*8caefee3SMatthias Ringwald * The main information is again its UUID. If we find a Characteristic that we're
224*8caefee3SMatthias Ringwald * interested in, it's name is printed and a reference stored for later.
225*8caefee3SMatthias Ringwald *
226*8caefee3SMatthias Ringwald * On discovery complete, we subscribe to a particular Characteristic to receive
227*8caefee3SMatthias Ringwald * Characteristic Value updates in the Notificaation Callback.
228*8caefee3SMatthias Ringwald */
229*8caefee3SMatthias Ringwald/* LISTING_START(LECentralCharacteristicDiscoveredCallback): Characteristic Discovered Callback */
230*8caefee3SMatthias Ringwaldvoid gattCharacteristicDiscovered(BLEStatus status, BLEDevice *device, BLECharacteristic *characteristic) {
231*8caefee3SMatthias Ringwald    switch(status){
232*8caefee3SMatthias Ringwald        case BLE_STATUS_OK:
233*8caefee3SMatthias Ringwald            Serial.print("Characteristic Discovered: ");
234*8caefee3SMatthias Ringwald            Serial.print(characteristic->getUUID()->getUuidString());
235*8caefee3SMatthias Ringwald            Serial.print(", handle 0x");
236*8caefee3SMatthias Ringwald            Serial.println(characteristic->getCharacteristic()->value_handle, HEX);
237*8caefee3SMatthias Ringwald            int i;
238*8caefee3SMatthias Ringwald            for (i=0;i<numCharacteristics;i++){
239*8caefee3SMatthias Ringwald                if (characteristic->matches(&characteristics[i].uuid)){
240*8caefee3SMatthias Ringwald                    Serial.print("Characteristic found: ");
241*8caefee3SMatthias Ringwald                    Serial.println(characteristics[i].name);
242*8caefee3SMatthias Ringwald                    characteristics[i].found = 1;
243*8caefee3SMatthias Ringwald                    characteristics[i].characteristic = *characteristic;
244*8caefee3SMatthias Ringwald                    break;
245*8caefee3SMatthias Ringwald                }
246*8caefee3SMatthias Ringwald            }
247*8caefee3SMatthias Ringwald            break;
248*8caefee3SMatthias Ringwald        case BLE_STATUS_DONE:
249*8caefee3SMatthias Ringwald            Serial.print("Characteristic discovery finished, status ");
250*8caefee3SMatthias Ringwald            Serial.println(status, HEX);
251*8caefee3SMatthias Ringwald            if (characteristics[charRX].found) {
252*8caefee3SMatthias Ringwald                device->subscribeForNotifications(&characteristics[charRX].characteristic);
253*8caefee3SMatthias Ringwald            }
254*8caefee3SMatthias Ringwald            break;
255*8caefee3SMatthias Ringwald        default:
256*8caefee3SMatthias Ringwald            Serial.println("Characteristics discovery error");
257*8caefee3SMatthias Ringwald            break;
258*8caefee3SMatthias Ringwald    }
259*8caefee3SMatthias Ringwald}
260*8caefee3SMatthias Ringwald/* LISTING_END(LECentralCharacteristicDiscoveredCallback): Characteristic Discovered Callback */
261*8caefee3SMatthias Ringwald
262*8caefee3SMatthias Ringwald/*
263*8caefee3SMatthias Ringwald * @section Subscribed Callback
264*8caefee3SMatthias Ringwald *
265*8caefee3SMatthias Ringwald * @text After the subcribe operation is complete, we get notified if it was
266*8caefee3SMatthias Ringwald * successful. In this example, we read the Characteristic that contains the
267*8caefee3SMatthias Ringwald * BD ADDR of the other device. This isn't strictly neccessary as we already
268*8caefee3SMatthias Ringwald * know the device address from the Advertisement, but it's a common pattern
269*8caefee3SMatthias Ringwald * with iOS as the device address is hidden from applications.
270*8caefee3SMatthias Ringwald */
271*8caefee3SMatthias Ringwald/* LISTING_START(LECentralSubscribedCallback): Subscribed Callback */
272*8caefee3SMatthias Ringwaldvoid gattSubscribedCallback(BLEStatus status, BLEDevice * device){
273*8caefee3SMatthias Ringwald    device->readCharacteristic(&characteristics[charBdAddr].characteristic);
274*8caefee3SMatthias Ringwald}
275*8caefee3SMatthias Ringwald/* LISTING_END(LECentralSubscribedCallback): Subscribed Callback */
276*8caefee3SMatthias Ringwald
277*8caefee3SMatthias Ringwald/*
278*8caefee3SMatthias Ringwald * @section Read Callback
279*8caefee3SMatthias Ringwald *
280*8caefee3SMatthias Ringwald * @text The Read callback is called with the result from a read operation.
281*8caefee3SMatthias Ringwald * Here, we write to the TX Characteristic next.
282*8caefee3SMatthias Ringwald */
283*8caefee3SMatthias Ringwald/* LISTING_START(LECentralReadCallback): Read Callback */
284*8caefee3SMatthias Ringwaldvoid gattReadCallback(BLEStatus status, BLEDevice *device, uint8_t *value, uint16_t length) {
285*8caefee3SMatthias Ringwald    Serial.print("Read callback: ");
286*8caefee3SMatthias Ringwald    Serial.println((const char *)value);
287*8caefee3SMatthias Ringwald    device->writeCharacteristic(&characteristics[charTX].characteristic, (uint8_t*) "Hello!", 6);
288*8caefee3SMatthias Ringwald}
289*8caefee3SMatthias Ringwald/* LISTING_END(LECentralReadCallback): Read Callback */
290*8caefee3SMatthias Ringwald
291*8caefee3SMatthias Ringwald/*
292*8caefee3SMatthias Ringwald * @section Written Callback
293*8caefee3SMatthias Ringwald *
294*8caefee3SMatthias Ringwald * @text After the write operation is complete, the Written Callback is callbed with
295*8caefee3SMatthias Ringwald * the result in the status argument. As we're done with the initial setup of the remote
296*8caefee3SMatthias Ringwald * device, we set the flag to write the test string as fast as possible.
297*8caefee3SMatthias Ringwald */
298*8caefee3SMatthias Ringwald/* LISTING_START(LECentralWrittenCallback): Written Callback */
299*8caefee3SMatthias Ringwaldvoid gattWrittenCallback(BLEStatus status, BLEDevice *device){
300*8caefee3SMatthias Ringwald    sendCounter = true;
301*8caefee3SMatthias Ringwald}
302*8caefee3SMatthias Ringwald/* LISTING_END(LECentralWrittenCallback): Written Callback */
303*8caefee3SMatthias Ringwald
304*8caefee3SMatthias Ringwald/*
305*8caefee3SMatthias Ringwald * @section Notification Callback
306*8caefee3SMatthias Ringwald *
307*8caefee3SMatthias Ringwald * @text Notifictions for Characteristic Value Updates are delivered via the
308*8caefee3SMatthias Ringwald * Notification Callback. When more than one Characteristic is subscribed,
309*8caefee3SMatthias Ringwald * the value handle can be used to distinguish between them. The
310*8caefee3SMatthias Ringwald * BLECharacteristic.isValueHandle(int handle) allows to test if a value handle
311*8caefee3SMatthias Ringwald * belongs to a particular Characteristic.
312*8caefee3SMatthias Ringwald */
313*8caefee3SMatthias Ringwald/* LISTING_START(LECentralNotificationCallback): Notification Callback */
314*8caefee3SMatthias Ringwaldvoid gattCharacteristicNotification(BLEDevice *device, uint16_t value_handle, uint8_t *value, uint16_t length) {
315*8caefee3SMatthias Ringwald    Serial.print("Notification: ");
316*8caefee3SMatthias Ringwald    Serial.println((const char *)value);
317*8caefee3SMatthias Ringwald}
318*8caefee3SMatthias Ringwald/* LISTING_END(LECentralNotificationCallback): Notification Callback */
319*8caefee3SMatthias Ringwald
320