https://github.com/Polidea/react-native-ble-plx/issues/229
https://github.com/Polidea/react-native-ble-plx/issues/264
https://github.com/Polidea/RxAndroidBle/issues/202
subscribe to service's characteristic via characteristic.monitor() method and receive values broadcasted by the peripheral device when callback function is executed
subscribe to service's characteristic via characteristic.monitor() method and receive the following error when callback function is executed
BleError: Characteristic d8b2c95b-b317-47ca-ac02-ccfd3d85a666 notify change failed for device 80293EA3-F380-A86F-B84F-DFC1A5B23502 and service ef66ccad-f4a8-4c51-b025-bc2a2c9fdaa6
device.connect()
.then((device) => {
this.setInfo("Discovering services and characteristics")
return device.discoverAllServicesAndCharacteristics()
})
.then((device) => {
this.setInfo("Setting notifications")
return this.setupNotifications(device)
})
.then(() => {
this.setInfo("Listening...")
}, (error) => {
this.setError(error.message)
})
let voltageCharacteristic = null
snifferService = services.filter(service => service.uuid === SERVICE_SNIFFER_UUID)[0]
snifferService.characteristics()
.then(characteristics => {
voltageCharacteristic = characteristics.filter(c => c.uuid === SNIFFER_VOLTAGE_UUID)[0]
voltageCharacteristic.read().then(res => {
voltageCharacteristic.monitor((error, c) => {
// getting the error here (voltageCharacteristic has notifiable attribute set to true)
})
})
})
.catch(error => console.log(error))
BLE Peripheral Device: ESP32 DEVKIT v1
[RxBLEKit|DEBG|14:09:35.624]: CentralManager(10861909952) cancelPeripheralConnection(peripheral: Peripheral(uuid: 80293EA3-F380-A86F-B84F-DFC1A5B23502, name: Optional("XFit")))
[RxBLEKit|DEBG|14:09:35.632]: CentralManager(10861909952) cancelPeripheralConnection(peripheral: Peripheral(uuid: 80293EA3-F380-A86F-B84F-DFC1A5B23502, name: Optional("XFit")))
[RxBLEKit|DEBG|14:09:35.632]: CentralManager(10861909952) didDisconnect(from: Peripheral(uuid: 80293EA3-F380-A86F-B84F-DFC1A5B23502, name: Optional("XFit")), error: nil)
2019-05-22 16:09:35.642708+0200 crossfitApp[3330:989980] [CoreBluetooth] XPC connection invalid
2019-05-22 16:09:36.933669+0200 crossfitApp[3330:989975] [CoreBluetooth] API MISUSE: <CBCentralManager: 0x28766e540> has no restore identifier but the delegate implements the centralManager:willRestoreState: method. Restoring will not be supported
[RxBLEKit|DEBG|14:09:36.947]: CentralManager(10861602112) didUpdateState(state: poweredOn)
[RxBLEKit|DEBG|14:09:36.957]: CentralManager(10861602112) scanForPeripherals(withServices: nil, options: Optional([:]))
[RxBLEKit|VERB|14:09:36.971]: CentralManager(10861602112) didDiscover(peripheral: Peripheral(uuid: C020115B-51E7-2C81-51CB-DF1BC55A697F, name: nil), rssi: -70)
[RxBLEKit|VERB|14:09:36.973]: CentralManager(10861602112) didDiscover(peripheral: Peripheral(uuid: 34673AF0-4EA0-8710-4214-988B5CDBF059, name: nil), rssi: -93)
[RxBLEKit|VERB|14:09:36.978]: CentralManager(10861602112) didDiscover(peripheral: Peripheral(uuid: B403A3C1-C3BC-526B-0B29-7B84DA12898A, name: nil), rssi: -79)
[RxBLEKit|VERB|14:09:36.984]: CentralManager(10861602112) didDiscover(peripheral: Peripheral(uuid: 0F6DBCFA-4C35-A4ED-665F-35420F685B35, name: nil), rssi: -99)
[RxBLEKit|VERB|14:09:36.985]: CentralManager(10861602112) didDiscover(peripheral: Peripheral(uuid: 2506CBEC-6659-1F85-103F-D51372463A4F, name: nil), rssi: -67)
[RxBLEKit|VERB|14:09:36.999]: CentralManager(10861602112) didDiscover(peripheral: Peripheral(uuid: FABCBC8B-B340-96AA-BB1A-2A61E868B20F, name: nil), rssi: -78)
[RxBLEKit|VERB|14:09:36.999]: CentralManager(10861602112) didDiscover(peripheral: Peripheral(uuid: 0F5E6A85-8F12-B3CE-3E20-429CB6ABB9FA, name: nil), rssi: 127)
[RxBLEKit|VERB|14:09:37.000]: CentralManager(10861602112) didDiscover(peripheral: Peripheral(uuid: 716D9F46-139A-D8D9-39A7-D430CC044FBE, name: nil), rssi: -73)
[RxBLEKit|VERB|14:09:37.002]: CentralManager(10861602112) didDiscover(peripheral: Peripheral(uuid: EFA0E1FB-E4C7-E927-F0D0-D1CDF87745CA, name: nil), rssi: -89)
[RxBLEKit|VERB|14:09:37.004]: CentralManager(10861602112) didDiscover(peripheral: Peripheral(uuid: 8D27405F-DF76-EF35-75F6-00AED3E73C0C, name: nil), rssi: -83)
[RxBLEKit|VERB|14:09:37.015]: CentralManager(10861602112) didDiscover(peripheral: Peripheral(uuid: E2D11F25-979C-F401-5E15-02FC79BDF5DF, name: nil), rssi: 127)
[RxBLEKit|VERB|14:09:37.019]: CentralManager(10861602112) didDiscover(peripheral: Peripheral(uuid: 1E37C315-3529-B921-AFA5-8089BFD1745C, name: nil), rssi: -81)
[RxBLEKit|VERB|14:09:37.028]: CentralManager(10861602112) didDiscover(peripheral: Peripheral(uuid: 0A5DAD63-78FA-4CD9-C13A-A73A49BFA322, name: nil), rssi: -88)
[RxBLEKit|VERB|14:09:37.032]: CentralManager(10861602112) didDiscover(peripheral: Peripheral(uuid: 6D504379-83E6-73AC-4F82-6CA641FA340A, name: nil), rssi: -95)
[RxBLEKit|VERB|14:09:37.035]: CentralManager(10861602112) didDiscover(peripheral: Peripheral(uuid: DAAD03EF-BBCC-EE38-3FE5-8E0AF65D9C3B, name: nil), rssi: -71)
[RxBLEKit|VERB|14:09:37.038]: CentralManager(10861602112) didDiscover(peripheral: Peripheral(uuid: 635CC333-023C-82F4-685B-2CEFC60B6A90, name: nil), rssi: -89)
[RxBLEKit|VERB|14:09:37.041]: CentralManager(10861602112) didDiscover(peripheral: Peripheral(uuid: 5894D3E2-0111-F865-D699-715B1DC5A83C, name: nil), rssi: -92)
[RxBLEKit|VERB|14:09:37.048]: CentralManager(10861602112) didDiscover(peripheral: Peripheral(uuid: C353879B-6DA4-8730-CBDA-828E1B82B9CD, name: nil), rssi: -79)
[RxBLEKit|VERB|14:09:37.064]: CentralManager(10861602112) didDiscover(peripheral: Peripheral(uuid: E357C250-08A8-7093-331A-9AA655CF3D57, name: nil), rssi: -85)
[RxBLEKit|VERB|14:09:37.066]: CentralManager(10861602112) didDiscover(peripheral: Peripheral(uuid: 6A30D0D0-0115-A264-903D-0BFECDE6F03D, name: nil), rssi: -82)
[RxBLEKit|VERB|14:09:37.068]: CentralManager(10861602112) didDiscover(peripheral: Peripheral(uuid: 7916FE15-9719-5F82-6B60-E0CF7EE78F85, name: nil), rssi: -81)
[RxBLEKit|VERB|14:09:37.070]: CentralManager(10861602112) didDiscover(peripheral: Peripheral(uuid: 5371ABF5-25AC-EF11-4251-57F928BA76E3, name: nil), rssi: -94)
[RxBLEKit|VERB|14:09:37.073]: CentralManager(10861602112) didDiscover(peripheral: Peripheral(uuid: 0DF38A38-12B8-1EDD-FF46-60BF9FDB906A, name: nil), rssi: -61)
[RxBLEKit|VERB|14:09:37.076]: CentralManager(10861602112) didDiscover(peripheral: Peripheral(uuid: FF294989-156C-CAF4-540F-3CAF459E3559, name: nil), rssi: -65)
[RxBLEKit|VERB|14:09:37.078]: CentralManager(10861602112) didDiscover(peripheral: Peripheral(uuid: 7410F5EA-CDA5-7805-F63F-D255F83CE5DF, name: nil), rssi: -78)
[RxBLEKit|VERB|14:09:37.082]: CentralManager(10861602112) didDiscover(peripheral: Peripheral(uuid: 45D92E51-0493-CBB1-1EAD-C0FEC42A38F0, name: nil), rssi: -83)
[RxBLEKit|VERB|14:09:37.085]: CentralManager(10861602112) didDiscover(peripheral: Peripheral(uuid: 68E8E2B9-A2F0-5EBF-DD87-B0A30275E0EA, name: nil), rssi: -85)
[RxBLEKit|VERB|14:09:37.085]: CentralManager(10861602112) didDiscover(peripheral: Peripheral(uuid: 1C1F2531-F8C6-A490-B508-79408B956499, name: nil), rssi: -72)
[RxBLEKit|VERB|14:09:37.094]: CentralManager(10861602112) didDiscover(peripheral: Peripheral(uuid: F128AAB5-E8B4-D9BC-E137-A7304DE79FDA, name: nil), rssi: -85)
[RxBLEKit|VERB|14:09:37.095]: CentralManager(10861602112) didDiscover(peripheral: Peripheral(uuid: D0E5CAC3-1F6C-CD1F-E3BD-04D3502AE716, name: nil), rssi: -85)
[RxBLEKit|VERB|14:09:37.101]: CentralManager(10861602112) didDiscover(peripheral: Peripheral(uuid: 5DEDA521-58E0-8FCF-AEB8-C6C638E6F763, name: nil), rssi: -90)
[RxBLEKit|VERB|14:09:37.104]: CentralManager(10861602112) didDiscover(peripheral: Peripheral(uuid: 59853C3F-7A57-37AF-30D7-5086321DA860, name: nil), rssi: -77)
[RxBLEKit|VERB|14:09:37.106]: CentralManager(10861602112) didDiscover(peripheral: Peripheral(uuid: 59066EAE-E91B-57C9-64B8-5046359F02EE, name: nil), rssi: -96)
[RxBLEKit|VERB|14:09:37.108]: CentralManager(10861602112) didDiscover(peripheral: Peripheral(uuid: 620C7A60-5B38-365F-882C-207C6CF9D44D, name: nil), rssi: -79)
[RxBLEKit|VERB|14:09:37.118]: CentralManager(10861602112) didDiscover(peripheral: Peripheral(uuid: 566EF8CD-4476-6CAF-A3B5-D21455026E2B, name: nil), rssi: -74)
[RxBLEKit|VERB|14:09:37.120]: CentralManager(10861602112) didDiscover(peripheral: Peripheral(uuid: D03B86FD-F74A-FA6B-8015-C564B8D2F2FC, name: nil), rssi: -63)
[RxBLEKit|VERB|14:09:37.123]: CentralManager(10861602112) didDiscover(peripheral: Peripheral(uuid: CD451EAC-2E08-EF75-E007-3F24B58F0C59, name: nil), rssi: -71)
[RxBLEKit|VERB|14:09:37.131]: CentralManager(10861602112) didDiscover(peripheral: Peripheral(uuid: EE3740E2-7F0B-FACD-A0CC-699B207DA695, name: nil), rssi: -80)
[RxBLEKit|VERB|14:09:37.135]: CentralManager(10861602112) didDiscover(peripheral: Peripheral(uuid: 645995AE-821F-8868-D91F-6F7CBE4BDAED, name: nil), rssi: -87)
[RxBLEKit|VERB|14:09:37.137]: CentralManager(10861602112) didDiscover(peripheral: Peripheral(uuid: 8BB3F02C-ABF1-1099-1F78-CC6408EABC84, name: nil), rssi: 127)
[RxBLEKit|VERB|14:09:37.143]: CentralManager(10861602112) didDiscover(peripheral: Peripheral(uuid: 80293EA3-F380-A86F-B84F-DFC1A5B23502, name: Optional("XFit")), rssi: -62)
[RxBLEKit|VERB|14:09:37.147]: CentralManager(10861602112) didDiscover(peripheral: Peripheral(uuid: 5AAB65A4-5283-AEEB-EDDA-8F3AD450DE71, name: nil), rssi: -66)
[RxBLEKit|DEBG|14:09:37.154]: CentralManager(10861602112) stopScan()
[RxBLEKit|DEBG|14:09:37.154]: CentralManager(10861602112) retrievePeripherals(withIdentifiers: [80293EA3-F380-A86F-B84F-DFC1A5B23502])
[RxBLEKit|DEBG|14:09:37.157]: CentralManager(10861602112) connect(peripheral: Peripheral(uuid: 80293EA3-F380-A86F-B84F-DFC1A5B23502, name: Optional("XFit")), options: nil)
[RxBLEKit|DEBG|14:09:37.391]: Peripheral(uuid: 80293EA3-F380-A86F-B84F-DFC1A5B23502, name: Optional("XFit")) discoverServices(serviceUUIDs: nil)
[RxBLEKit|DEBG|14:09:37.843]: Peripheral(uuid: 80293EA3-F380-A86F-B84F-DFC1A5B23502, name: Optional("XFit")) didDiscoverServices(services: Optional("[Service(uuid: Device Information, id: 10861745600), Service(uuid: 9A8CA9EF-E43F-4157-9FEE-C37A3D7DC12D, id: 10861742784), Service(uuid: EF66CCAD-F4A8-4C51-B025-BC2A2C9FDAA6, id: 10861740928)]"), error: nil)
[RxBLEKit|DEBG|14:09:37.843]: Peripheral(uuid: 80293EA3-F380-A86F-B84F-DFC1A5B23502, name: Optional("XFit")) discoverCharacteristics(characteristicUUIDs: nil, for: Service(uuid: Device Information, id: 10861745600))
[RxBLEKit|DEBG|14:09:37.844]: Peripheral(uuid: 80293EA3-F380-A86F-B84F-DFC1A5B23502, name: Optional("XFit")) discoverCharacteristics(characteristicUUIDs: nil, for: Service(uuid: 9A8CA9EF-E43F-4157-9FEE-C37A3D7DC12D, id: 10861742784))
[RxBLEKit|DEBG|14:09:37.844]: Peripheral(uuid: 80293EA3-F380-A86F-B84F-DFC1A5B23502, name: Optional("XFit")) discoverCharacteristics(characteristicUUIDs: nil, for: Service(uuid: EF66CCAD-F4A8-4C51-B025-BC2A2C9FDAA6, id: 10861740928))
[RxBLEKit|DEBG|14:09:37.963]: Peripheral(uuid: 80293EA3-F380-A86F-B84F-DFC1A5B23502, name: Optional("XFit")) didDiscoverCharacteristicsFor(for: Service(uuid: Device Information, id: 10861745600), characteristics: Optional("[Characteristic(uuid: Manufacturer Name String, id: 11081318496), Characteristic(uuid: Model Number String, id: 11081319168), Characteristic(uuid: Serial Number String, id: 11081329536)]"), error: nil)
[RxBLEKit|DEBG|14:09:38.083]: Peripheral(uuid: 80293EA3-F380-A86F-B84F-DFC1A5B23502, name: Optional("XFit")) didDiscoverCharacteristicsFor(for: Service(uuid: 9A8CA9EF-E43F-4157-9FEE-C37A3D7DC12D, id: 10861742784), characteristics: Optional("[Characteristic(uuid: E94F85C8-7F57-4DBD-B8D3-2B56E107ED60, id: 11081092000), Characteristic(uuid: A8985FDA-51AA-4F19-A777-71CF52ABBA1E, id: 11081092096)]"), error: nil)
[RxBLEKit|DEBG|14:09:38.205]: Peripheral(uuid: 80293EA3-F380-A86F-B84F-DFC1A5B23502, name: Optional("XFit")) didDiscoverCharacteristicsFor(for: Service(uuid: EF66CCAD-F4A8-4C51-B025-BC2A2C9FDAA6, id: 10861740928), characteristics: Optional("[Characteristic(uuid: 5B7DD565-6E90-4DF8-B806-F4AC85DF74CA, id: 11081326656), Characteristic(uuid: C8FB3A51-D44C-4D9F-A8EC-A7598C1BF2EA, id: 11081329440), Characteristic(uuid: D8B2C95B-B317-47CA-AC02-CCFD3D85A666, id: 11081319456), Characteristic(uuid: 7127A1B2-ED4D-433A-9780-5A9E38F6A040, id: 11081330016)]"), error: nil)
[RxBLEKit|DEBG|14:09:38.283]: Peripheral(uuid: 80293EA3-F380-A86F-B84F-DFC1A5B23502, name: Optional("XFit")) setNotifyValue(enabled: true, for: Characteristic(uuid: D8B2C95B-B317-47CA-AC02-CCFD3D85A666, id: 11081319456))
[RxBLEKit|DEBG|14:09:38.284]: Peripheral(uuid: 80293EA3-F380-A86F-B84F-DFC1A5B23502, name: Optional("XFit")) didUpdateNotificationStateFor(for:Characteristic(uuid: D8B2C95B-B317-47CA-AC02-CCFD3D85A666, id: 11081319456), isNotifying: false, error: Optional(Error Domain=CBATTErrorDomain Code=10 "The attribute could not be found." UserInfo={NSLocalizedDescription=The attribute could not be found.}))
[RxBLEKit|DEBG|14:09:38.286]: Peripheral(uuid: 80293EA3-F380-A86F-B84F-DFC1A5B23502, name: Optional("XFit")) setNotifyValue(enabled: false, for: Characteristic(uuid: D8B2C95B-B317-47CA-AC02-CCFD3D85A666, id: 11081319456))
[RxBLEKit|DEBG|14:09:38.287]: Peripheral(uuid: 80293EA3-F380-A86F-B84F-DFC1A5B23502, name: Optional("XFit")) didUpdateNotificationStateFor(for:Characteristic(uuid: D8B2C95B-B317-47CA-AC02-CCFD3D85A666, id: 11081319456), isNotifying: false, error: Optional(Error Domain=CBATTErrorDomain Code=10 "The attribute could not be found." UserInfo={NSLocalizedDescription=The attribute could not be found.}))
2019-05-22 16:09:40.107097+0200 crossfitApp[3330:989903] [] nw_socket_handle_socket_event [C131254.1:1] Socket SO_ERROR [61: Connection refused]
Characteristic properties extracted from Chrome devtools
voltageCharacteristic: Characteristic
deviceID: "80293EA3-F380-A86F-B84F-DFC1A5B23502"
id: 10794864096
isIndicatable: false
isNotifiable: true
isNotifying: false
isReadable: false
isWritableWithResponse: false
isWritableWithoutResponse: false
serviceID: 10746901760
serviceUUID: "ef66ccad-f4a8-4c51-b025-bc2a2c9fdaa6"
uuid: "d8b2c95b-b317-47ca-ac02-ccfd3d85a666"
value: null
Error stack trace
"BleError: Characteristic d8b2c95b-b317-47ca-ac02-ccfd3d85a666 notify change failed for device 80293EA3-F380-A86F-B84F-DFC1A5B23502 and service ef66ccad-f4a8-4c51-b025-bc2a2c9fdaa6
at parseBleError (blob:http://10.80.148.183:8081/e724eaee-ffd5-4243-9d1e-3c4c983e62ea:112674:18)
at monitorListener (blob:http://10.80.148.183:8081/e724eaee-ffd5-4243-9d1e-3c4c983e62ea:113739:50)
at RCTDeviceEventEmitter.emit (blob:http://10.80.148.183:8081/e724eaee-ffd5-4243-9d1e-3c4c983e62ea:6131:37)
at MessageQueue.__callFunction (blob:http://10.80.148.183:8081/e724eaee-ffd5-4243-9d1e-3c4c983e62ea:2587:44)
at blob:http://10.80.148.183:8081/e724eaee-ffd5-4243-9d1e-3c4c983e62ea:2344:17
at MessageQueue.__guard (blob:http://10.80.148.183:8081/e724eaee-ffd5-4243-9d1e-3c4c983e62ea:2541:13)
at MessageQueue.callFunctionReturnFlushedQueue (blob:http://10.80.148.183:8081/e724eaee-ffd5-4243-9d1e-3c4c983e62ea:2343:14)
at http://10.80.148.183:8081/debugger-ui/debuggerWorker.js:80:58"
package.json file:{
"name": "voltageApp",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node node_modules/react-native/local-cli/cli.js start",
"test": "jest",
"android": "react-native run-android",
"ios": "react-native run-ios"
},
"dependencies": {
"react": "16.8.3",
"react-native": "0.59.8",
"react-native-ble-plx": "^1.0.3",
"react-native-gesture-handler": "^1.2.1",
"react-navigation": "^3.9.1"
},
"devDependencies": {
"@babel/core": "^7.4.4",
"@babel/runtime": "^7.4.4",
"babel-jest": "^24.8.0",
"jest": "^24.8.0",
"metro-react-native-babel-preset": "^0.54.0",
"react-test-renderer": "16.8.3"
},
"jest": {
"preset": "react-native"
}
}
const SERVICE_SNIFFER_UUID = 'ef66ccad-f4a8-4c51-b025-bc2a2c9fdaa6'
const SNIFFER_STATUS_UUID = '5b7dd565-6e90-4df8-b806-f4ac85df74ca'
const SNIFFER_SPEED_UUID = 'c8fb3a51-d44c-4d9f-a8ec-a7598c1bf2ea'
const SNIFFER_VOLTAGE_UUID = 'd8b2c95b-b317-47ca-ac02-ccfd3d85a666'
scanAndConnect () {
this.manager.startDeviceScan(null, null, (error, device) => {
if (error) {
// Handle error (scanning will be stopped automatically)
this.setError(error)
return false
}
// Check if it is a device you are looking for based on advertisement data or other criteria.
if (device.name === 'XXX' || device.localName === 'Sniffer') {
this.device = device
this.manager.stopDeviceScan()
device.connect()
.then((device) => {
return device.discoverAllServicesAndCharacteristics()
})
.then((device) => {
return this.setupNotifications(device)
})
.then(() => {
this.setInfo("Listening...")
}, (error) => {
this.setError(error.message)
})
}
})
}
async setupNotifications(device) {
let snifferService = null
device.services().then(services => {
let voltageCharacteristic = null
snifferService = services.filter(service => service.uuid === SERVICE_SNIFFER_UUID)[0]
snifferService.characteristics()
.then(characteristics => {
// voltageCharacteristic is retrieved correctly and data is also seems correct
voltageCharacteristic = characteristics.filter(c => c.uuid === SNIFFER_VOLTAGE_UUID)[0]
voltageCharacteristic.monitor((error, c) => {
// RECEIVED THE ERROR HERE (voltageCharacteristic.notifiable === true)
})
})
.catch(error => console.log(error))
})
}
Tried with version 1.0.2 and same error occurs.
Reading the Characteristic before invoking monitor method doesn't work either.
await characteristic.read();
Hello, have you considered adding native logs?
@dariuszseweryn Added a version of the native logs in the original question.
Tried to read and write on that and other characteristics and works fine, so it seems it's not a problem of service/characteristic definition.
Why do you think so?
Because characteristic is published, seems to have the correct values for notification, and other programs can subscribe to the characteristic notification normally
Yet you can see here that iOS API rejects setting the notification:
[RxBLEKit|DEBG|14:09:38.284]: Peripheral(uuid: 80293EA3-F380-A86F-B84F-DFC1A5B23502, name: Optional("XFit")) didUpdateNotificationStateFor(for:Characteristic(uuid: D8B2C95B-B317-47CA-AC02-CCFD3D85A666, id: 11081319456), isNotifying: false, error: Optional(Error Domain=CBATTErrorDomain Code=10 "The attribute could not be found." UserInfo={NSLocalizedDescription=The attribute could not be found.}))
What other programs have you tried?
LightBlue, I turn on the notifications for that characteristic and fetch the correct values sent by the peripheral
If I disable in the iOS project the line that throws the error it works properly (notification handler executes whenever the peripheral broadcasts a value, and the characteristic has that value).
Peripheral.swift (line 334)
public func setNotifyValue(_ enabled: Bool,
for characteristic: Characteristic) -> Observable<Characteristic> {
let observable = peripheral
.rx_didUpdateNotificationStateForCharacteristic
.filter { $0.0 == characteristic.characteristic }
.take(1)
.map { (_, error) -> Characteristic in
if let error = error {
/// throw BluetoothError.characteristicNotifyChangeFailed(characteristic, error)
}
return characteristic
}
return ensureValidPeripheralStateAndCallIfSucceeded(
for: observable,
postSubscriptionCall: { [weak self] in
self?.peripheral.setNotifyValue(enabled, for: characteristic.characteristic)
}
)
}
I'll investigate the characteristic definition on the peripheral side. The current characteristic definition on the Android device is:
pCharSnifferVoltage = pService->createCharacteristic(
SNIFFER_VOLTAGE_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_NOTIFY |
BLECharacteristic::PROPERTY_WRITE
);
So _maybe_ there is some error in the implementation of ESP32 you are using after all?
Could be, I'll post on Espressif forums in case someone has encountered the same problem. I'll post my findings into this thread.
In order to not keep maintaining my own react-native-ble-plx fork, is there a way (config or something) to make the library not to stop on native(iOS) exceptions?
Just to be sure. Is Client Characteristic Configuration Descriptor present for your characteristic? You can check it with nRF Connect app for example.
@Cierpliwy I had a similar issue (https://github.com/Polidea/react-native-ble-plx/issues/229) and I simply did what you wrote above
/// throw BluetoothError.characteristicNotifyChangeFailed(characteristic, error)
I am using a custom bluetooth peripheral, so it might not follow the requirements of the bluetooth communication protocols for now, and I'll have to keep it that way for now, but I don't think that this is an issue of this library. If you wonder what's this for @packetstracer, you should look at this post https://devzone.nordicsemi.com/f/nordic-q-a/8427/why-do-we-need-cccd
Just to be sure. Is Client Characteristic Configuration Descriptor present for your characteristic? You can check it with nRF Connect app for example.
@Cierpliwy I've investigated about the Client Characteristic Configuration descriptor for the characteristic that was notifying, and It wasn't set. So I've created the descriptor and added to the characteristic and now everything works fine.
Thanks a lot!!
For the sake of future information for people having the same issue, I attach some info about Client Characteristic Configuration descriptor:
What is this descriptor:
Associated with the idea of indications/notifications, is the architected BLE Descriptor called "Client Characteristic Configuration" which has UUID 0x2902. This contains (among other things) two distinct bit fields that can be on or off. One bit field governs Notifications while the other governs Indications. If the corresponding bit is on, then the server can/may send the corresponding push. For example if the Notifications bit is on, then the server can/may send notifications. The primary purpose of the descriptor is to allow a partner (a client) to request that the server actually send notifications or indications. Here is an example.
Imagine that we have a BLE Server that can publish notifications when data changes. Now imagine that a BLE Client connects but is actually not interested in receiving these. If the BLE Server executes a notification push and sends the data, that will be wasted effort/energy as the client doesn't want or can't use the information. What we really want is that the client should inform the server that if it wants to push new data then it either should or shouldn't. And that is where this descriptor comes into play.
If the descriptor is present on a characteristic then then client can remotely change the bit flag to enable or disable notifications and indications. Since the descriptor flag is stored locally within the server, the server is at liberty to examine the flag before performing a radio transmission. What this means is that the client/peer can toggle on or off its desire to receive notifications and the server should honor those requests.
Extracted from https://github.com/nkolban/esp32-snippets/blob/master/Documentation/BLE%20C%2B%2B%20Guide.pdf
How I created this descriptor in Arduino for the characteristic that notifies de values:
BLEService *pService = pServer->createService(SERVICE_SNIFFER_UUID);
BLECharacteristic *pCharSnifferVoltage = pService->createCharacteristic(
SNIFFER_VOLTAGE_UUID,
BLECharacteristic::PROPERTY_NOTIFY
);
// create CCC descriptor and add it to the characteristic
BLEDescriptor *pClientCharacteristicConfigDescriptor = new BLEDescriptor((uint16_t)0x2902);
pCharSnifferVoltage->addDescriptor(pClientCharacteristicConfigDescriptor);
pService->start();
If I disable in the iOS project the line that throws the error it works properly (notification handler executes whenever the peripheral broadcasts a value, and the characteristic has that value).
Peripheral.swift (line 334)
public func setNotifyValue(_ enabled: Bool, for characteristic: Characteristic) -> Observable<Characteristic> { let observable = peripheral .rx_didUpdateNotificationStateForCharacteristic .filter { $0.0 == characteristic.characteristic } .take(1) .map { (_, error) -> Characteristic in if let error = error { /// throw BluetoothError.characteristicNotifyChangeFailed(characteristic, error) } return characteristic } return ensureValidPeripheralStateAndCallIfSucceeded( for: observable, postSubscriptionCall: { [weak self] in self?.peripheral.setNotifyValue(enabled, for: characteristic.characteristic) } ) }
This works well to resolve the issue. For 1.x version of react-native-ble-plx i created a patch-package patch file and would apply the patch 'postinstall'.
However, in react-native-ble-plx 2.x they seem to use 'MultiplatformBleAdapter' as a pod dependency and i am unable to create a patch. I do not have access to the ble firmware so I can only deal with the issue on app. Is there a library which could help me generate and apply patch file to a swift file within pods folder rather than editing the file manually ?
I was running into this same problem and added the CCCD to the notify characteristic as recommended above. Now, instead of getting the the attribute is not found native error, I am getting a the handle is invalid error. I would prefer to not change the native code as a workaround. Any ideas what would be wrong with my descriptor that would cause be to get a "the handle is invalid" error?
You hav probably misconfigured your peripheral. Consult Bluetooth Core Specification and/or documentation of the framework you use for peripheral implementation.
Thanks.
@dariuszseweryn Hi, i am facing the same issue. It working on android, but failed on IOS.
I tested write and listen for notifications successful by using LightBlue.
Any solution to solve this?
{"message":"Characteristic 000036f6-0000-1000-8000-00805f9b34fb notify change failed for device A and service 0000fee7-0000-1000-8000-00805f9b34fb","errorCode":403,"attErrorCode":10,"iosErrorCode":null,"androidErrorCode":null,"reason":"The attribute could not be found.","name":"BleError"}
If I disable in the iOS project the line that throws the error it works properly (notification handler executes whenever the peripheral broadcasts a value, and the characteristic has that value).
Peripheral.swift (line 334)
public func setNotifyValue(_ enabled: Bool, for characteristic: Characteristic) -> Observable<Characteristic> { let observable = peripheral .rx_didUpdateNotificationStateForCharacteristic .filter { $0.0 == characteristic.characteristic } .take(1) .map { (_, error) -> Characteristic in if let error = error { /// throw BluetoothError.characteristicNotifyChangeFailed(characteristic, error) } return characteristic } return ensureValidPeripheralStateAndCallIfSucceeded( for: observable, postSubscriptionCall: { [weak self] in self?.peripheral.setNotifyValue(enabled, for: characteristic.characteristic) } ) }
Any workaround for v2 ?
If I disable in the iOS project the line that throws the error it works properly (notification handler executes whenever the peripheral broadcasts a value, and the characteristic has that value).
Peripheral.swift (line 334)public func setNotifyValue(_ enabled: Bool, for characteristic: Characteristic) -> Observable<Characteristic> { let observable = peripheral .rx_didUpdateNotificationStateForCharacteristic .filter { $0.0 == characteristic.characteristic } .take(1) .map { (_, error) -> Characteristic in if let error = error { /// throw BluetoothError.characteristicNotifyChangeFailed(characteristic, error) } return characteristic } return ensureValidPeripheralStateAndCallIfSucceeded( for: observable, postSubscriptionCall: { [weak self] in self?.peripheral.setNotifyValue(enabled, for: characteristic.characteristic) } ) }Any workaround for v2 ?
You can:
Awful solution I know, but works for a workaround until we can have a better way
Most helpful comment
@Cierpliwy I've investigated about the Client Characteristic Configuration descriptor for the characteristic that was notifying, and It wasn't set. So I've created the descriptor and added to the characteristic and now everything works fine.
Thanks a lot!!
For the sake of future information for people having the same issue, I attach some info about Client Characteristic Configuration descriptor:
What is this descriptor:
Extracted from https://github.com/nkolban/esp32-snippets/blob/master/Documentation/BLE%20C%2B%2B%20Guide.pdf
How I created this descriptor in Arduino for the characteristic that notifies de values: