@@ -2278,19 +2278,8 @@ export class Bluetooth extends BluetoothCommon {
22782278 const cUUID = uuidToString ( characteristic . getUuid ( ) ) ;
22792279 const sUUID = uuidToString ( characteristic . getService ( ) . getUuid ( ) ) ;
22802280
2281- const stateObject = this . connections [ pUUID ] ;
2282- stateObject . onNotifyCallbacks = stateObject . onNotifyCallbacks || { } ;
22832281 const key = sUUID + '/' + cUUID ;
22842282 const onNotify = args . onNotify ;
2285- stateObject . onNotifyCallbacks [ key ] = function ( result ) {
2286- // CLog(
2287- // CLogTypes.warning,
2288- // `onNotifyCallback ---- UUID: ${UUID}, pUUID: ${pUUID}, cUUID: ${cUUID}, args.characteristicUUID: ${
2289- // args.characteristicUUID
2290- // }, sUUID: ${sUUID}, args.serviceUUID: ${args.serviceUUID}, result: ${result}`
2291- // );
2292- onNotify ( result ) ;
2293- } ;
22942283
22952284 this . attachSubDelegate (
22962285 { methodName, args, resolve, reject} ,
@@ -2305,11 +2294,16 @@ export class Bluetooth extends BluetoothCommon {
23052294 }
23062295
23072296 if ( UUID === pUUID && cUUID === args . characteristicUUID && sUUID === args . serviceUUID ) {
2308- if ( status === GATT_SUCCESS ) {
2297+ if ( status === GATT_SUCCESS && descriptor . getValue ( ) !== android . bluetooth . BluetoothGattDescriptor . DISABLE_NOTIFICATION_VALUE ) {
2298+ // only assign notify callback when receiving a successful response
2299+ const stateObject = this . connections [ pUUID ] ;
2300+ stateObject . onNotifyCallbacks = stateObject . onNotifyCallbacks || { } ;
2301+ stateObject . onNotifyCallbacks [ key ] = function ( result ) {
2302+ onNotify ( result ) ;
2303+ } ;
23092304 resolve ( ) ;
23102305 clearListeners ( ) ;
23112306 } else {
2312- delete stateObject . onNotifyCallbacks [ key ] ;
23132307 onError (
23142308 new BluetoothError ( BluetoothCommon . msg_error_function_call , {
23152309 arguments : args ,
@@ -2318,8 +2312,6 @@ export class Bluetooth extends BluetoothCommon {
23182312 } )
23192313 ) ;
23202314 }
2321- } else {
2322- delete stateObject . onNotifyCallbacks [ key ] ;
23232315 }
23242316 } ,
23252317 } ) ,
@@ -2347,74 +2339,110 @@ export class Bluetooth extends BluetoothCommon {
23472339 return this . addToQueue (
23482340 args ,
23492341 ( wrapper ) =>
2350- new Promise < void > ( ( resolve , reject ) => {
2351- const gatt = wrapper . gatt ;
2352- const gattService = wrapper . bluetoothGattService ;
2353- const characteristicUUID = stringToUuid ( args . characteristicUUID ) ;
2354-
2355- const characteristic = this . _findNotifyCharacteristic ( gattService , characteristicUUID ) ;
2356- if ( Trace . isEnabled ( ) ) {
2357- CLog ( CLogTypes . info , `${ methodName } ---- peripheralUUID:${ args . peripheralUUID } serviceUUID:${ args . serviceUUID } characteristicUUID:${ args . characteristicUUID } ` ) ;
2358- }
2359-
2360- if ( ! characteristic ) {
2361- return reject (
2362- new BluetoothError ( BluetoothCommon . msg_no_characteristic , {
2363- method : methodName ,
2364- arguments : args ,
2365- } )
2366- ) ;
2367- }
2368-
2369- const stateObject = this . connections [ args . peripheralUUID ] ;
2370- if ( stateObject && stateObject . onNotifyCallbacks ) {
2371- const key = args . serviceUUID + '/' + args . characteristicUUID ;
2372- delete stateObject . onNotifyCallbacks [ key ] ;
2373- }
2374- const clearListeners = ( ) => {
2375- this . removeDisconnectListener ( onDisconnect ) ;
2376- } ;
2377- const onError = ( err ) => {
2378- reject ( err ) ;
2379- clearListeners ( ) ;
2380- } ;
2381- const onDisconnect = ( address ) => {
2382- if ( address === args . peripheralUUID ) {
2383- onError (
2384- new BluetoothError ( BluetoothCommon . msg_peripheral_disconnected , {
2385- method : methodName ,
2386- arguments : args ,
2387- } )
2388- ) ;
2389- }
2390- } ;
2391- this . addDisconnectListener ( onDisconnect ) ;
2392- try {
2393- if ( gatt . setCharacteristicNotification ( characteristic , false ) ) {
2394- resolve ( ) ;
2395- clearListeners ( ) ;
2396- } else {
2397- onError (
2398- new BluetoothError ( BluetoothCommon . msg_error_function_call , {
2399- method : 'setCharacteristicNotification' ,
2400- arguments : args ,
2401- } )
2402- ) ;
2403- }
2404- } catch ( ex ) {
2405- if ( Trace . isEnabled ( ) ) {
2406- CLog ( CLogTypes . error , methodName , ex ) ;
2407- }
2408- onError (
2409- new BluetoothError ( ex . message , {
2410- stack : ex . stackTrace || ex . stack ,
2411- nativeException : ex . nativeException ,
2412- arguments : args ,
2413- method : methodName ,
2414- } )
2415- ) ;
2416- }
2417- } )
2342+ new Promise < void > ( ( resolve , reject ) => {
2343+ const gatt = wrapper . gatt ;
2344+ const bluetoothGattService = wrapper . bluetoothGattService ;
2345+ const characteristicUUID = stringToUuid ( args . characteristicUUID ) ;
2346+
2347+ const characteristic = this . _findNotifyCharacteristic ( bluetoothGattService , characteristicUUID ) ;
2348+ if ( Trace . isEnabled ( ) ) {
2349+ CLog ( CLogTypes . info , `${ methodName } ---- peripheralUUID:${ args . peripheralUUID } serviceUUID:${ args . serviceUUID } characteristicUUID:${ args . characteristicUUID } ` ) ;
2350+ }
2351+ if ( ! characteristic ) {
2352+ return reject (
2353+ new BluetoothError ( BluetoothCommon . msg_no_characteristic , {
2354+ method : methodName ,
2355+ arguments : args ,
2356+ } )
2357+ ) ;
2358+ }
2359+
2360+ if ( ! gatt . setCharacteristicNotification ( characteristic , false ) ) {
2361+ return reject (
2362+ new BluetoothError ( BluetoothCommon . msg_error_function_call , {
2363+ method : 'setCharacteristicNotification' ,
2364+ arguments : args ,
2365+ } )
2366+ ) ;
2367+ }
2368+
2369+ const clientCharacteristicConfigId = stringToUuid ( '2902' ) ;
2370+ let bluetoothGattDescriptor = characteristic . getDescriptor ( clientCharacteristicConfigId ) as android . bluetooth . BluetoothGattDescriptor ;
2371+ if ( ! bluetoothGattDescriptor ) {
2372+ bluetoothGattDescriptor = new android . bluetooth . BluetoothGattDescriptor ( clientCharacteristicConfigId , android . bluetooth . BluetoothGattDescriptor . PERMISSION_WRITE ) ;
2373+ bluetoothGattDescriptor . setValue ( android . bluetooth . BluetoothGattDescriptor . DISABLE_NOTIFICATION_VALUE ) ;
2374+ characteristic . addDescriptor ( bluetoothGattDescriptor ) ;
2375+ if ( Trace . isEnabled ( ) ) {
2376+ CLog ( CLogTypes . info , methodName , '---- descriptor:' , bluetoothGattDescriptor ) ;
2377+ }
2378+ // Any creation error will trigger the global catch. Ok.
2379+ }
2380+
2381+ // prefer notify over indicate
2382+ if ( ( characteristic . getProperties ( ) & android . bluetooth . BluetoothGattCharacteristic . PROPERTY_NOTIFY ) !== 0 ) {
2383+ bluetoothGattDescriptor . setValue ( android . bluetooth . BluetoothGattDescriptor . DISABLE_NOTIFICATION_VALUE ) ;
2384+ } else if ( ( characteristic . getProperties ( ) & android . bluetooth . BluetoothGattCharacteristic . PROPERTY_INDICATE ) !== 0 ) {
2385+ bluetoothGattDescriptor . setValue ( android . bluetooth . BluetoothGattDescriptor . DISABLE_NOTIFICATION_VALUE ) ;
2386+ } else {
2387+ return reject (
2388+ new BluetoothError ( BluetoothCommon . msg_characteristic_cant_notify , {
2389+ method : methodName ,
2390+ arguments : args ,
2391+ } )
2392+ ) ;
2393+ }
2394+
2395+ const pUUID = args . peripheralUUID ;
2396+ const cUUID = uuidToString ( characteristic . getUuid ( ) ) ;
2397+ const sUUID = uuidToString ( characteristic . getService ( ) . getUuid ( ) ) ;
2398+
2399+ const key = sUUID + '/' + cUUID ;
2400+ this . attachSubDelegate (
2401+ { methodName, args, resolve, reject} ,
2402+ ( clearListeners , onError ) => ( {
2403+ onDescriptorWrite : ( gatt : android . bluetooth . BluetoothGatt , descriptor : android . bluetooth . BluetoothGattDescriptor , status : number ) => {
2404+ const device = gatt . getDevice ( ) ;
2405+ let UUID : string = null ;
2406+ if ( device == null ) {
2407+ // happens some time, why ... ?
2408+ } else {
2409+ UUID = device . getAddress ( ) ;
2410+ }
2411+
2412+ if ( UUID === pUUID && cUUID === args . characteristicUUID && sUUID === args . serviceUUID ) {
2413+ if ( status === GATT_SUCCESS && descriptor . getValue ( ) === android . bluetooth . BluetoothGattDescriptor . DISABLE_NOTIFICATION_VALUE ) {
2414+ // Only delete callback on successful disable
2415+ const stateObject = this . connections [ args . peripheralUUID ] ;
2416+ if ( stateObject && stateObject . onNotifyCallbacks ) {
2417+ const key = args . serviceUUID + '/' + args . characteristicUUID ;
2418+ delete stateObject . onNotifyCallbacks [ key ] ;
2419+ }
2420+ resolve ( ) ;
2421+ clearListeners ( ) ;
2422+ } else {
2423+ onError (
2424+ new BluetoothError ( BluetoothCommon . msg_error_function_call , {
2425+ arguments : args ,
2426+ method : 'writeDescriptor' ,
2427+ status,
2428+ } )
2429+ ) ;
2430+ }
2431+ }
2432+ } ,
2433+ } ) ,
2434+ ( onError ) => {
2435+ if ( ! gatt . writeDescriptor ( bluetoothGattDescriptor ) ) {
2436+ onError (
2437+ new BluetoothError ( BluetoothCommon . msg_error_function_call , {
2438+ method : 'writeDescriptor' ,
2439+ arguments : args ,
2440+ } )
2441+ ) ;
2442+ }
2443+ } ,
2444+ ) ;
2445+ } )
24182446 ) ;
24192447 }
24202448
0 commit comments