@@ -89,6 +89,9 @@ public class BluetoothLePlugin extends CordovaPlugin {
8989 //Quick Writes
9090 private LinkedList <byte []> queueQuick = new LinkedList <byte []>();
9191
92+ //Peripheral queue
93+ private LinkedList <Operation > peripheralQueue = new LinkedList <Operation >();
94+
9295 //Object keys
9396 private final String keyStatus = "status" ;
9497 private final String keyError = "error" ;
@@ -127,6 +130,7 @@ public class BluetoothLePlugin extends CordovaPlugin {
127130 private final String keyConnectionPriority = "connectionPriority" ;
128131 private final String keyMtu = "mtu" ;
129132 private final String keyPin = "pin" ;
133+ private final String keySent = "sent" ;
130134 private final String keyQueue = "queue" ;
131135
132136 //Write Types
@@ -155,6 +159,7 @@ public class BluetoothLePlugin extends CordovaPlugin {
155159 private final String statusRssi = "rssi" ;
156160 private final String statusConnectionPriorityRequested = "connectionPriorityRequested" ;
157161 private final String statusMtu = "mtu" ;
162+ private final String statusNotified = "notified" ;
158163
159164 //Properties
160165 private final String propertyBroadcast = "broadcast" ;
@@ -212,6 +217,7 @@ public class BluetoothLePlugin extends CordovaPlugin {
212217 private final String errorRequestConnectionPriority = "requestConnectPriority" ;
213218 private final String errorMtu = "mtu" ;
214219 private final String errorRetrievePeripheralsByAddress = "retrievePeripheralsByAddress" ;
220+ private final String errorNotify = "notify" ;
215221
216222 //Error Messages
217223 //Initialization
@@ -414,7 +420,9 @@ public boolean execute(String action, final JSONArray args, final CallbackContex
414420 } else if ("respond" .equals (action )) {
415421 respondAction (args , callbackContext );
416422 } else if ("notify" .equals (action )) {
417- notifyAction (args , callbackContext );
423+ Operation operation = new Operation ("notify" , args , callbackContext );
424+ peripheralQueue .add (operation );
425+ peripheralQueueStart ();
418426 } else if ("setPin" .equals (action )) {
419427 setPinAction (args , callbackContext );
420428 } else if ("retrievePeripheralsByAddress" .equals (action )) {
@@ -822,15 +830,18 @@ private void respondAction(JSONArray args, CallbackContext callbackContext) {
822830 }
823831 }
824832
825- private void notifyAction (JSONArray args , CallbackContext callbackContext ) {
833+ private boolean notifyAction (Operation operation ) {
834+ JSONArray args = operation .args ;
835+ CallbackContext callbackContext = operation .callbackContext ;
836+
826837 JSONObject obj = getArgsObject (args );
827838 if (isNotArgsObject (obj , callbackContext )) {
828- return ;
839+ return false ;
829840 }
830841
831842 String address = getAddress (obj );
832843 if (isNotAddress (address , callbackContext )) {
833- return ;
844+ return false ;
834845 }
835846 BluetoothDevice device = bluetoothAdapter .getRemoteDevice (address );
836847
@@ -841,6 +852,7 @@ private void notifyAction(JSONArray args, CallbackContext callbackContext) {
841852 addProperty (returnObj , "error" , "service" );
842853 addProperty (returnObj , "message" , "Service not found" );
843854 callbackContext .error (returnObj );
855+ return false ;
844856 }
845857
846858 UUID characteristicUuid = getUUID (obj .optString ("characteristic" , null ));
@@ -850,6 +862,7 @@ private void notifyAction(JSONArray args, CallbackContext callbackContext) {
850862 addProperty (returnObj , "error" , "characteristic" );
851863 addProperty (returnObj , "message" , "Characteristic not found" );
852864 callbackContext .error (returnObj );
865+ return false ;
853866 }
854867
855868 byte [] value = getPropertyBytes (obj , "value" );
@@ -859,6 +872,7 @@ private void notifyAction(JSONArray args, CallbackContext callbackContext) {
859872 addProperty (returnObj , "error" , "respond" );
860873 addProperty (returnObj , "message" , "Failed to set value" );
861874 callbackContext .error (returnObj );
875+ return false ;
862876 }
863877
864878 BluetoothGattDescriptor descriptor = characteristic .getDescriptor (clientConfigurationDescriptorUuid );
@@ -869,14 +883,16 @@ private void notifyAction(JSONArray args, CallbackContext callbackContext) {
869883 isIndicate = true ;
870884 }
871885
872- //Wait for onNotificationSent event
873886 boolean result = gattServer .notifyCharacteristicChanged (device , characteristic , isIndicate );
874887 if (!result ) {
875888 JSONObject returnObj = new JSONObject ();
876889 addProperty (returnObj , "error" , "notify" );
877890 addProperty (returnObj , "message" , "Failed to notify" );
878891 callbackContext .error (returnObj );
892+ return false ;
879893 }
894+
895+ return true ;
880896 }
881897
882898 public void hasPermissionAction (CallbackContext callbackContext ) {
@@ -3243,6 +3259,38 @@ private void queueRemove(HashMap<Object, Object> connection) {
32433259 queueNext (connection );
32443260 }
32453261
3262+ private void peripheralQueueStart () {
3263+ if (peripheralQueue .size () > 1 ) {
3264+ return ;
3265+ }
3266+
3267+ peripheralQueueNext ();
3268+ }
3269+
3270+ private void peripheralQueueNext () {
3271+ Operation operation = peripheralQueue .peek ();
3272+
3273+ boolean result = notifyAction (operation );
3274+
3275+ if (!result ) {
3276+ peripheralQueueRemove ();
3277+ }
3278+ }
3279+
3280+ private void peripheralQueueRemove () {
3281+ if (peripheralQueue .size () == 0 ) {
3282+ return ;
3283+ }
3284+
3285+ peripheralQueue .poll ();
3286+
3287+ if (peripheralQueue .size () == 0 ) {
3288+ return ;
3289+ }
3290+
3291+ peripheralQueueNext ();
3292+ }
3293+
32463294 private HashMap <Object , Object > EnsureCallback (UUID characteristicUuid , HashMap <Object , Object > connection ) {
32473295 HashMap <Object , Object > characteristicCallbacks = (HashMap <Object , Object >) connection .get (characteristicUuid );
32483296
@@ -4630,6 +4678,36 @@ public void onMtuChanged(BluetoothDevice device, int mtu) {
46304678 }
46314679
46324680 public void onNotificationSent (BluetoothDevice device , int status ) {
4681+ Operation operation = peripheralQueue .peek ();
4682+
4683+ JSONArray args = operation .args ;
4684+ CallbackContext callbackContext = operation .callbackContext ;
4685+
4686+ peripheralQueueRemove ();
4687+
4688+ //If no callback, just return
4689+ if (callbackContext == null ) {
4690+ return ;
4691+ }
4692+
4693+ JSONObject obj = getArgsObject (args );
4694+
4695+ JSONObject returnObj = new JSONObject ();
4696+
4697+ addDevice (returnObj , device );
4698+
4699+ //If successfully notified, return value
4700+ if (status == BluetoothGatt .GATT_SUCCESS ) {
4701+ addProperty (returnObj , keyStatus , statusNotified );
4702+ addProperty (returnObj , keySent , true );
4703+ callbackContext .success (returnObj );
4704+ } else {
4705+ //Else it failed
4706+ addProperty (returnObj , keyError , errorNotify );
4707+ callbackContext .error (returnObj );
4708+ }
4709+
4710+ //TODO: Remove code below (kept for backward compatibility)
46334711 if (initPeripheralCallback == null ) {
46344712 return ;
46354713 }
0 commit comments