don / cordova-plugin-ble-central

Bluetooth Low Energy (BLE) Central plugin for Apache Cordova (aka PhoneGap)
Apache License 2.0
942 stars 603 forks source link

iOS notifications / kinda sorta works (issue #99 continuation) #101

Closed blistick closed 8 years ago

blistick commented 8 years ago

Hi Don,

This is a continuation of my issue #99. (Sorry, I couldn't figure out how to reopen it.)

I've made progress by using ble.startNotification instead of ble.read.

The reason I didn't use the notification approach before is that I get an error when I use it, BUT I've found that if I show the error with an alert(), AND if I don't dismiss the alert on my phone, I get the notifications and the correct data from my device.

Weird, I know.

Once I dismiss the alert, I stop getting the data, but I do still see "didUpdateValueForCharacteristic" when my device sends data. (I'm guessing that the alert() is pausing execution, which prevents your code from marking the notification as failed??)

If I omit the failure callback from ble.startNotification, or if I do a console.log() within the callback instead of an alert(), the data is not returned by the notification.

See below for my console log. You'll see where I logged bytes that were received, which was happening while the alert was still on my phone.

Is there a way to prevent the error I'm getting, or to tell the plugin to disregard it?

Best,

Barton

2015-09-23 13:32:57.365 Bluno[190:3255] registering for notification 2015-09-23 13:32:57.365 Bluno[190:3255] getData 2015-09-23 13:32:57.366 Bluno[190:3255] Looking for DFB1 2015-09-23 13:32:57.614 Bluno[190:3255] Error Domain=CBATTErrorDomain Code=10 "The attribute could not be found." UserInfo=0x17407ebc0 {NSLocalizedDescription=The attribute could not be found.} 2015-09-23 13:33:00.883 Bluno[190:3255] didUpdateValueForCharacteristic 2015-09-23 13:33:00.890 Bluno[190:3255] Data received from BLE: 2015-09-23 13:33:00.891 Bluno[190:3255] 72 2015-09-23 13:33:00.891 Bluno[190:3255] 69 2015-09-23 13:33:00.892 Bluno[190:3255] 76 2015-09-23 13:33:00.892 Bluno[190:3255] 76 2015-09-23 13:33:00.893 Bluno[190:3255] 79 2015-09-23 13:33:05.294 Bluno[190:3255] didUpdateValueForCharacteristic 2015-09-23 13:33:05.298 Bluno[190:3255] Data received from BLE: 2015-09-23 13:33:05.299 Bluno[190:3255] 72 2015-09-23 13:33:05.299 Bluno[190:3255] 69 2015-09-23 13:33:05.300 Bluno[190:3255] 76 2015-09-23 13:33:05.300 Bluno[190:3255] 76 2015-09-23 13:33:05.300 Bluno[190:3255] 79 2015-09-23 13:33:10.394 Bluno[190:3255] didUpdateValueForCharacteristic 2015-09-23 13:33:15.494 Bluno[190:3255] didUpdateValueForCharacteristic 2015-09-23 13:33:20.324 Bluno[190:3255] didUpdateValueForCharacteristic

don commented 8 years ago

Based on the bluno sample notification is the way to go.

What error are you getting when you startNotification?

blistick commented 8 years ago

The error I get is:

Error Domain=CBATTErrorDomain Code=10 "The attribute could not be found." UserInfo=0x17407ebc0 {NSLocalizedDescription=The attribute could not be found.}

You'll see this in the log snippet I included at the end of my prior post.

Oddly, the bytes are still delivered by the plugin, so long as the alert() is not dismissed.

don commented 8 years ago

That's a really odd error. Maybe "dfb1" or the 128 bit version 0000DFB1-0000-1000-8000-00805F9B34FB would work better?

It's possible the server dynamically adds the characteristic and it's not there when you first request it?

You get a peripheral object in the success callback for the connect method. Can you print that out and post the results here?

console.log(JSON.stringify(peripheral, null, 2));
blistick commented 8 years ago

I've tried the 128 bit version before, and it hasn't worked (I think it works for Android but not iOS), but I'll try it again tomorrow, as well as "dfb1".

I'll also post the contents of the peripheral object.

I'll do all this in about 12 hours, when I get back into my office.

Thanks!

blistick commented 8 years ago

When I tried "dfb1" I got the same result as for "DFB1". When I tried the 128 bit version, I got, "Could not find characteristic with UUID".

Here's the contents of the peripheral object:

{ "characteristics": [ { "properties": [ "Read" ], "isNotifying": false, "characteristic": "2A23", "service": "180A" }, { "properties": [ "Read" ], "isNotifying": false, "characteristic": "2A24", "service": "180A" }, { "properties": [ "Read" ], "isNotifying": false, "characteristic": "2A25", "service": "180A" }, { "properties": [ "Read" ], "isNotifying": false, "characteristic": "2A26", "service": "180A" }, { "properties": [ "Read" ], "isNotifying": false, "characteristic": "2A27", "service": "180A" }, { "properties": [ "Read" ], "isNotifying": false, "characteristic": "2A28", "service": "180A" }, { "properties": [ "Read" ], "isNotifying": false, "characteristic": "2A29", "service": "180A" }, { "properties": [ "Read" ], "isNotifying": false, "characteristic": "2A2A", "service": "180A" }, { "properties": [ "Read" ], "isNotifying": false, "characteristic": "2A50", "service": "180A" }, { "properties": [ "Read", "WriteWithoutResponse", "Write", "Notify" ], "isNotifying": false, "characteristic": "DFB1", "service": "DFB0" }, { "properties": [ "Read", "WriteWithoutResponse", "Write", "Notify" ], "isNotifying": false, "characteristic": "DFB2", "service": "DFB0" } ], "id": "2709C4B8-5BC6-C2C3-6307-804B2070B925", "rssi": 127, "advertising": { "kCBAdvDataLocalName": "Bluno", "kCBAdvDataServiceUUIDs": [ "DFB0", "1812" ], "kCBAdvDataTxPowerLevel": 0, "kCBAdvDataIsConnectable": true }, "name": "Bluno", "services": [ "180A", "DFB0" ] }

blistick commented 8 years ago

Hey Don. Not to be too much of a pest, but any thoughts based on the contents of the peripheral object?

If I could somehow tell the plugin to ignore the notification error, I would be able to get the data (since I see the data coming in, until my alert in the error handler is dismissed.)

Thanks!

blistick commented 8 years ago

I developed a workaround for my issue.

I found that if I commented out a couple of lines in the didUpdateNotificationStateForCharacteristic function in source file BLECentralPlugin.m, my app would successfully get subsequent notifications and characteristic data.

Here's a snippet of code showing the two lines I commented out:

    } else if (notificationCallbackId && error) {
        NSLog(@"%@", error);
//        pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:[error localizedDescription]];
//        [self.commandDelegate sendPluginResult:pluginResult callbackId:notificationCallbackId];
    }

Obviously this is not a very clean solution, but at least it lets me move forward.

don commented 8 years ago

@blistick glad you found a work around. I'm not sure why you're getting errors with the characteristics. Without the @dfrobot hardware I can't really debug this. If you find a more generic solution, let me know.

uKL commented 7 years ago

That may be because dfrobot hardware is not so BLE compliant and it doesn't contain client configuration descriptor in the characteristic...

don commented 7 years ago

@uKL yes, this is because DFRobot hides the descriptor for the characteristic so BLE client's can't subscribe. They didn't seem interested in fixing the problem. You can work around it by modifying the plugin. See https://github.com/don/cordova-plugin-ble-central/issues/251#issuecomment-226369279 for more info.

uKL commented 7 years ago

This is actually a coincidence I came here :) I'm implementing the same thing on native iOS.

ustincameron commented 6 years ago

@blistick can you post the code you ended up using? I've commented out the line but not getting any data in the buffer var. It's insane how popular yet difficult the Bluno is.

don commented 6 years ago

@blistick's code is another valid approach https://github.com/don/cordova-plugin-ble-central/issues/101#issuecomment-143908282 it ignores the error when the descriptor can't be set. Instead of commenting those lines out, return resultWithStatus:CDVCommandStatus_OK so the Cordova success callback fires.

In your JavaScript code, ensure startNotification is called before writing any data to DFB1. Your notification callback will be called when data arrives. You never want to call stopNotification.

blistick commented 6 years ago

@socca1157, the only change I made was to comment out the two lines that I indicated above. Not sure why you're not getting data. Good luck!

ustincameron commented 6 years ago

@don Thank you! #101 mixed with your twitter suggestion to check if my changes to the plugin were making it across Ionic build solved my issue! Literally spent weeks trying to read the serial data from the Bluno. Much appreciated!!

stoneWeb commented 2 years ago

I use xcode to run it on my phone, I can get notifications for a while, and when I restart the app I get "The attribute could not be found." v1.4.4 How to resolve?

peitschie commented 2 years ago

@stoneWeb are you using the DFRobot hardware that this issue was originally reported against?

stoneWeb commented 2 years ago

@peitschie yes, this one: bluno-nano Xcode works fine when running on the phone, but if you restart the app, you can't receive the data sent by nano, Communication is one-way only, and sending data from the phone to the Nano works fine.

peitschie commented 2 years ago

@stoneWeb would you mind opening a new issue for this?

Would be great to get the debug logs out of Xcode before and after the app restart as well, to help pinpoint what's going on there.