Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BLE status = 133 problem #1

Closed
DoctorAllow opened this issue Jun 17, 2015 · 35 comments
Closed

BLE status = 133 problem #1

DoctorAllow opened this issue Jun 17, 2015 · 35 comments

Comments

@DoctorAllow
Copy link

I am facing the ble status = 133 in android BluetoothGatt .
the log follow:
D/BluetoothGatt(16840): connect() - device: F0:13:C3:80:AA:C6, auto: false
D/BluetoothGatt(16840): registerApp()
D/BluetoothGatt(16840): registerApp() - UUID=653ae82e-5199-4ff2-8897-27b6ae925f3c
I/BluetoothGatt(16840): Client registered, waiting for callback
D/BluetoothGatt(16840): onClientRegistered() - status=0 clientIf=5
D/BluetoothGatt(16840): onClientConnectionState() - status=133 clientIf=5 device=F0:13:C3:80:AA:C6
In the sourcode the 133 means GATT ERROR .
And in my code i have user the refresh() before the gatt.close();
And I have use close() after disconnect();
But there are not any AndroidPhone have this problem .the Samsung S4 had meet much time.
and the Moto X is very nice in BLE.
How about try to reconnect the device while we meet the status == 133 or 129?
For some AndroidPhone the Ble develpment is no good.
Maybe my english is no good , Hope you can help me ,Thank you very much .

@philips77
Copy link
Member

Hi,
It's true that errors 133 and 129 were common among different Android phones. The BLE is not very mature on Android but gets better and better each release. On Lollipop you don't get 129 any more (but you get some others). I don't know if there is anything you can do to avoid those errors. Try add some delays, e.g after getting connected and before calling discoverServices(). But eve this will not guarantee that it will work.

@dhesson
Copy link

dhesson commented Jul 5, 2015

I'm having this issue on a Nexus 5 running 5.1.1. We send an enter DFU command to the target, the target disconnects from my app (after ~3 seconds), I close the gatt, and then I fire up the DFU library intent service and it yields a 133 error after onClientRegistered(). Still trying to figure this out. I'm pretty sure its an app caching/le stack issue, because once the device is in DFU, I can launch the nRF Toolbox app and send it new firmware images without issue.

@philips77
Copy link
Member

Hi,
Did you try to start the DFU service when your device is still in the application mode? The service should trigger entering the bootloader mode automatically, unless you have implemented this feature in a different way. I think you could also try adding some delay after entering DFU, before you start the service. Error 133 be thrown if there was something unexpected on the air. Maybe the device needs more time to switch?
IMHO it may be hard to find out the reason. It may also behave differently on different Android devices and versions.

@philips77
Copy link
Member

We have also found some bugs in the new Android 5.1. The DFU was working much better on 5.0 and fails on 5.1.x. I still don't know if it's a bug out a feature, need some time to investigate.

@dhesson
Copy link

dhesson commented Jul 5, 2015

Yeah, we start the DFU service while in application mode. I receive a disconnect shortly after, and then I try starting the dfu intent service, which ends up failing during the connect phase. I've tried delaying 3, 5, and 10 seconds before connecting in DFU mode once its triggered. Also added retry code and changed the dfu lib to run on the UI thread, to no avail. I ordered a bluetooth sniffer so I can see what's going on at the transmission level, but I wont have it until mid week. I only work on the Android side, not the embedded app, so I'll just be sending the sniffing data to our firmware guys to see if they have any ideas. My suspicion is Android didn't cleanly disconnect form the peripheral, and has something unexpected or invalid in a cache causing the connect by the DFU lib to fail.

I'll try my app out on some other versions of Android & different phones and see if it works there.

@philips77
Copy link
Member

Hi again. The DFU service should automatically start itself after successful jump to the bootloader mode. No need to start it again.
Did you try flashing the update using nRF Toolbox when the device is in app mode? The DFU service, when started, connects to the device, reads the DFU Version characteristic (if present) and based on that decides whether the device is in the app or bootloader mode. If there is no DFU Version char. it starts as normal and may get a disconnect shortly after which means it was in the app mode. If in app mode it triggers switch and automatically starts itself again with same input parameters. The second connection should send the data.
I'm testing nRF Toolbox now with Nexus 5 with Android 5.1.1 and it works with our HRM DFU sample application from SDK 8.0. I managed to send only app and SD+BL+App all-in-one without any problems.
If you have our nRF51 DK you may try the sample and check state of LEDs. Based on them you may get the device state (app/Bootloader - connected/disconnected).

@dhesson
Copy link

dhesson commented Jul 7, 2015

Tried nRF Toolbox with our device and it toasted 'DFU service not found', so we've implemented the feature in a way that doesn't work out of the box when in application mode. Just thought maybe my issue was related to this ticket due to my logs being an exact match, but maybe it's something we're doing after application mode switches to DFU with our custom implementation. Thanks for the assistance

@dhesson
Copy link

dhesson commented Jul 9, 2015

Didn't realize the address changed when the device entered DFU mode. Problem solved :(

@philips77
Copy link
Member

Nice to hear that.
Yes, the address changes when switched to DFU mode unless the buttonless switch was used (at least our implementation). The address also changes when the new SD is flashed (than the app is removed). As the new bootloader can't send the Service Changed indication, or the previous application might not have one, changing the address is the only way to force service rediscovery, at least on iOS. On Android this refresh() hack may be used, but it's bad and I was trying to avoid it whenever possible.

@DoctorAllow
Copy link
Author

Hi:
Why the refresh() is bad for android and you were trying to avoid it whenever possible?
I have try the refresh after the disconnect() and before the close(), it is good for some phone to the 133 , My app has reconncect function,for some phone ,if the 133 happen,there maybe we can't connect again forever,but if we add the refresh() after disconnnect , it will be better for this issuer.
But I also meet some terrible status,i have recept the disconnect callback , but the device also show connect to the phone,the disconnect callback is the phone tell the app the gatt is disconnect.So i need to try to remove the refresh() and try again.But i also don't know why the refresh is bad for bluetooth.

@philips77
Copy link
Member

The refresh() method is not in the public api. Reflections must be used to call it. It also may be removed one day without notice.
By removing the cashed services it also shorten the lifetime of a Bluetooth Smart device. Each time the phone connects to it it does the full service discovery. The Service Changed characteristic was designed to avoid necessity of doing service discovery multiple times. Android should work properly without the need of any hacks...

@DoctorAllow
Copy link
Author

Sorry; I also have one question:

  1. it also may be removed one day without notice , the mean if I refresh the cash , the phone will hard to scan the device?or which notice you say ?

@philips77
Copy link
Member

refresh() method clears the device's list of services cached on the phone. It means that the next time the phone will connect to the device it will have to do the service discovery procedure. Without calling refresh(), when you call gatt.discoverService() and the phone had already discovered them before, it will just return you back the cached list without doing any operations over the air. It will be about 5 seconds faster and will save some battery on the peripheral.
When you call refresh() every time you disconnect the cache is cleared and the phone will retrieve services from the peripheral next time it connects.
Full service discovery should be done only when the services might have changed, it means:

  • after receiving Service Change indication from a bonded device (SC indications must be enabled prior to that) - this works on Android
  • each time you connect to a device that previously had Service Change characteristic in its database, in case of non-bonded device - this does not work on Android up to 5.1.1 (Android always caches services, despite there was or wasn't SC characteristic).

@hrldcpr
Copy link
Contributor

hrldcpr commented Nov 13, 2015

Hey @philips77, sorry to revive this thread, but perhaps you have some insight on how to get around some similar 129 and 133 issues I'm having when trying to DFU?

We're using the maven release of the library, no.nordicsemi.android:dfu:0.6.

Things work fine on our newer bootloaders, where DFU runs on a different MAC address than the normal application. But we still have some old hardware in the wild that we'd like to be able to update, which reuses the same MAC address for the application and the DFU service. Even then it works fine on certain phones, such as Moto E, but it only works about 10% of the time on other phones, such as Galaxy S5. On such phones, the other 90% of the time, the DFU library hits the following errors:

…
E/DfuBaseService: Service discovery error: 129
E/DfuBaseService: An error occurred while connecting to the device:16513
D/BluetoothGatt: cancelOpen() - device: FA:B0:BE:04:6C:7E
D/BluetoothGatt: onClientConnectionState() - status=133 clientIf=7 device=FA:B0:BE:04:6C:7E
E/DfuBaseService: Connection state change error: 133 newState: 0
…

The full log output is attached here.

In that log you'll also see a few random things we try before starting DFU, with 1 second delays between each step:

  • "old DFU step 1" is refreshing the service cache, using the hidden "refresh" method on the BluetoothGatt object
  • "old DFU step 2" is calling discoverServices() on the BluetoothGatt
  • "old DFU step 3" is refreshing the service cache again
  • "old DFU step 4" is closing the BluetoothGatt
  • "old DFU step 5" is finally starting your DFU library

So anyway, if you happen to have any thoughts on what might be going wrong or how we might be able to fix it, that would be excellent!

@philips77
Copy link
Member

Hi, what I'd do is just clear the cache after you get onStateChangedCallback with state disconnected, before calling close() (before you start DFU service). The second service discovery before that may not be a good choice. Also keep in mind, that calling refresh() performs the service discovery if you are connected. It's asynchronous. The service discovery may take few seconds. You may also give some time after close using wait(600) (I see you give 1s).
The 129 bug does not appear since Lollipop. The 133 is also getting less common, I'd say.

So, in summary:

  1. You are connected, wants to perform DFU
  2. gatt.disconnect()
  3. In the disconnect callback: refresh() and close() (you may give 600ms before close() )
  4. Wait some time with wait(600)
  5. Start DFU service

You may also check the log in nRF Master Control Panel. I log there all ble related method on Debug level.

Hope it helped

@hrldcpr
Copy link
Contributor

hrldcpr commented Nov 15, 2015

Thanks for the tips Aleksander! I'll try them soon.

@hrldcpr
Copy link
Contributor

hrldcpr commented Nov 17, 2015

@philips77 that helped to fix my issues on Samsung phones, thanks very much!

Now I'm getting a different issue on certain newer phones (Nexus 5X and OnePlus 2). The DFU progress gets to 1% and then I receive this error:

DfuBaseService: Device returned error after sending file (error 6)

Any guesses what could cause this error? The exact same device and zip archive work fine together on other phones.

(Sorry to continue on this thread, just figured you might know what can lead to that error. Thanks!)

@philips77
Copy link
Member

Try to change the number of packets (before a receipt notification is sent) in the settings. Start from 1 and increase it slowly. You may also try to increase the connection interval in the DFU bootloader. The issue may be related to the speed of saving incoming packets on flash. The new phones may support more packets per connection interval which may be too fast for DFU. Also nrf52 needs a little more time to save, as it has more flash memory, and in the flash tech a page needs to be cleared before saved.

@philips77
Copy link
Member

FYI, I published a newer version of the DFU library on jcenter (0.6.1). Not related to your problem, but to this: https://devzone.nordicsemi.com/question/57250/android-6-master-control-panel-bonded-dfu-android-6-gets-stuck-in-a-loop/?answer=57307#post-id-57307

@hrldcpr
Copy link
Contributor

hrldcpr commented Nov 20, 2015

thanks @philips77

is there any way to change that setting other than changing mPacketsBeforeNotification in the DFU code and re-compiling? and is there a way to change the setting in nRF Toolbox? we get the same error in nRF Toolbox. the default value of 10 seems pretty conservative already though, i'd have thought?

the strange thing is that these phones work fine on devices that have our newer bootloader. so with the exact same hardware on both ends (phone and device), just changing the bootloader introduces the issue.

anyway i'll let you know if i find anything! also, good to know about that nordic devcenter, maybe i'll bug you there next time ;)

@philips77
Copy link
Member

Hi, in toolbox's DFU profile you have the settings icon in the right top corner. There you can find Number of Packets, which sets the mPacketsBeforeNotification value.

@hrldcpr
Copy link
Contributor

hrldcpr commented Nov 23, 2015

Thanks yet again @philips77 that was totally the issue! The highest I could get it to was 4, to work on both the OnePlus 2 and the Nexus 5X.

In case anyone else comes upon this thread, here is the code I used:

PreferenceManager.getDefaultSharedPreferences(getActivity()).edit()
        .putString(DfuSettingsConstants.SETTINGS_NUMBER_OF_PACKETS, "4")
        .commit();

@Timmmm
Copy link

Timmmm commented Jul 5, 2016

I finally found where the error codes are defined:

https://android.googlesource.com/platform/external/bluetooth/bluedroid/+/master/stack/include/gatt_api.h

Unfortunately 0x85 (133) is just GATT_ERROR, which isn't very helpful. 0x89 (137) is GATT_AUTH_FAIL which is a little more helpful...

@philips77
Copy link
Member

From my experience the error 133 is thrown in case of timing issue. This is when a command was expected but wasn't received. For example when device is not reachable after calling device.connectGatt(...), or when such issue occurs during the connection. It is not normal BLE behavior so the connection cannot be continued. Other errors are normal ones, so they occur in some situations, but according to BLE spec.

@xujing19870829
Copy link

Android 5.0+ dfu is Ok
Android 6.0 I found a problem
10-19 11:33:38.503 17771-30222/no.nordicsemi.android.nrftoolbox I/DfuBaseService: Connecting to the device...
10-19 11:33:38.505 17771-30222/no.nordicsemi.android.nrftoolbox D/BluetoothGatt: connect() - device: D9:61:D9:94:FB:A6, auto: false
10-19 11:33:38.505 17771-30222/no.nordicsemi.android.nrftoolbox D/BluetoothGatt: registerApp()
10-19 11:33:38.505 17771-30222/no.nordicsemi.android.nrftoolbox D/BluetoothGatt: registerApp() - UUID=61853f54-21e9-45f7-b17a-a60b3f4723ee
10-19 11:33:38.509 17771-17783/no.nordicsemi.android.nrftoolbox D/BluetoothGatt: onClientRegistered() - status=0 clientIf=5
10-19 11:33:38.629 17771-17784/no.nordicsemi.android.nrftoolbox D/BluetoothGatt: onClientConnectionState() - status=0 clientIf=5 device=D9:61:D9:94:FB:A6
10-19 11:33:38.630 17771-17784/no.nordicsemi.android.nrftoolbox I/DfuBaseService: Connected to GATT server
10-19 11:33:38.634 17771-17784/no.nordicsemi.android.nrftoolbox D/BluetoothGatt: discoverServices() - device: D9:61:D9:94:FB:A6
10-19 11:33:38.639 17771-17784/no.nordicsemi.android.nrftoolbox I/DfuBaseService: Attempting to start service discovery... succeed
10-19 11:34:00.350 17771-17783/no.nordicsemi.android.nrftoolbox D/BluetoothGatt: onSearchComplete() = Device=D9:61:D9:94:FB:A6 Status=129
10-19 11:34:00.350 17771-17783/no.nordicsemi.android.nrftoolbox E/DfuBaseService: Service discovery error: 129
10-19 11:34:00.351 17771-30222/no.nordicsemi.android.nrftoolbox E/DfuBaseService: An error occurred during discovering services:129
10-19 11:34:00.354 17771-17784/no.nordicsemi.android.nrftoolbox D/BluetoothGatt: onClientConnectionState() - status=133 clientIf=5 device=D9:61:D9:94:FB:A6
10-19 11:34:00.356 17771-17784/no.nordicsemi.android.nrftoolbox E/DfuBaseService: Connection state change error: 133 newState: 0
10-19 11:34:00.386 17771-30222/no.nordicsemi.android.nrftoolbox I/HwCust: Constructor found for class android.app.HwCustNotificationImpl
10-19 11:34:00.387 17771-30222/no.nordicsemi.android.nrftoolbox D/HwCust: Create obj success use class android.app.HwCustNotificationImpl
10-19 11:34:00.392 17771-17771/no.nordicsemi.android.nrftoolbox I/DfuBaseService: Action received: android.bluetooth.device.action.ACL_DISCONNECTED
10-19 11:34:00.409 17771-30222/no.nordicsemi.android.nrftoolbox I/DfuBaseService: Disconnecting from the device...
10-19 11:34:00.410 17771-30222/no.nordicsemi.android.nrftoolbox D/BluetoothGatt: cancelOpen() - device: D9:61:D9:94:FB:A6
10-19 11:34:00.413 17771-30222/no.nordicsemi.android.nrftoolbox D/BluetoothGatt: refresh() - device: D9:61:D9:94:FB:A6
10-19 11:34:00.415 17771-30222/no.nordicsemi.android.nrftoolbox I/DfuBaseService: Refreshing result: true
10-19 11:34:00.416 17771-30222/no.nordicsemi.android.nrftoolbox I/DfuBaseService: Cleaning up...
10-19 11:34:00.416 17771-30222/no.nordicsemi.android.nrftoolbox D/BluetoothGatt: close()
10-19 11:34:00.416 17771-30222/no.nordicsemi.android.nrftoolbox D/BluetoothGatt: unregisterApp() - mClientIf=5
10-19 11:34:00.420 17771-30222/no.nordicsemi.android.nrftoolbox I/DfuBaseService: Restarting the service
10-19 11:34:02.445 17771-30222/no.nordicsemi.android.nrftoolbox D/HwCust: Create obj success use class android.app.HwCustNotificationImpl
10-19 11:34:02.471 17771-30222/no.nordicsemi.android.nrftoolbox I/DfuBaseService: Connecting to the device...
10-19 11:34:02.473 17771-30222/no.nordicsemi.android.nrftoolbox D/BluetoothGatt: connect() - device: D9:61:D9:94:FB:A6, auto: false
10-19 11:34:02.473 17771-30222/no.nordicsemi.android.nrftoolbox D/BluetoothGatt: registerApp()
10-19 11:34:02.473 17771-30222/no.nordicsemi.android.nrftoolbox D/BluetoothGatt: registerApp() - UUID=fb0d28ce-e6e5-4bcd-9147-dc101a80b246
10-19 11:34:02.477 17771-17783/no.nordicsemi.android.nrftoolbox D/BluetoothGatt: onClientRegistered() - status=0 clientIf=5
10-19 11:34:32.496 17771-17824/no.nordicsemi.android.nrftoolbox D/BluetoothGatt: onClientConnectionState() - status=133 clientIf=5 device=D9:61:D9:94:FB:A6
10-19 11:34:32.496 17771-17824/no.nordicsemi.android.nrftoolbox E/DfuBaseService: Connection state change error: 133 newState: 0
10-19 11:34:32.497 17771-30222/no.nordicsemi.android.nrftoolbox E/DfuBaseService: Device got disconnected before service discovery finished
10-19 11:34:32.500 17771-30222/no.nordicsemi.android.nrftoolbox D/BluetoothGatt: refresh() - device: D9:61:D9:94:FB:A6
10-19 11:34:32.504 17771-30222/no.nordicsemi.android.nrftoolbox I/DfuBaseService: Refreshing result: true
10-19 11:34:32.504 17771-30222/no.nordicsemi.android.nrftoolbox I/DfuBaseService: Cleaning up...
10-19 11:34:32.504 17771-30222/no.nordicsemi.android.nrftoolbox D/BluetoothGatt: close()
10-19 11:34:32.504 17771-30222/no.nordicsemi.android.nrftoolbox D/BluetoothGatt: unregisterApp() - mClientIf=5
10-19 11:34:33.108 17771-30222/no.nordicsemi.android.nrftoolbox D/HwCust: Create obj success use class android.app.HwCustNotificationImpl
10-19 11:34:33.192 17771-17810/no.nordicsemi.android.nrftoolbox D/mali_winsys: new_window_surface returns 0x3000

@philips77
Copy link
Member

Could you open another issue? This one is regarding error 129, as I can see.

@xujing19870829
Copy link

Find the problem, the embedded engineers changed the dfu state device name, so can not connect service,thank you, your project has given us great help

@philips77
Copy link
Member

Great to hear that!

@dazza5000
Copy link

I still get this every so often. Any ideas on how to fix this?

@Maragues
Copy link

Maragues commented Dec 8, 2017

What seems to have improved the situation for me in a custom BLE connection implementation

This, among all other recommendations of running all commands from a single thread, not blocking BluetoothCallbacks, keeping a single BluetoothGatt, etc.

BLE on Android is complex... Maybe tomorrow I'm facing the same issue on a different device :(

@btmcmahan
Copy link

I had the Error #133 problem. After months of research and pulling my hair out, I have found a solution that is not normally talked about.

Your normal connect request looks something like this:

cGatt.connectGatt(this, false, gattCallback);

There is another version of the connectGatt command, with a 4th parameter. This parameter specifies what type of bluetooth device you are connecting to. I added a "2" to specify that I am connecting via Bluetooth LE. (it's called "transport", forgive me if my explanation is incorrect, but it solved all my problems)

Try this:

cGatt.connectGatt(this, false, gattCallback, 2);

And BAM, now my #133 nightmare is over (I pray)!

@chitrang200889
Copy link

Hi btmcmahan, I am also getting same error but not able to solve my problem with your work around. Please spare some time and have a look at this question https://stackoverflow.com/questions/48507782/how-to-write-byte-array-with-bluetoothgattcharacteristic-in-ble. Thanks.

@btmcmahan
Copy link

btmcmahan commented Feb 2, 2018 via email

@BytesZero
Copy link

  • Android OS < 6.0:
mBluetoothDevice.connectGatt(context, false, callback);
  • Android OS >= 6.0:
mBluetoothDevice.connectGatt(context, false, callback, BluetoothDevice.TRANSPORT_LE);

Ultimately, hardware equipment is needed to completely solve this problem.

@anilOVYO
Copy link

anilOVYO commented Aug 8, 2019

  • On some devices, it got fixed with
    mBluetoothDevice.connectGatt(context, false, callback, BluetoothDevice.TRANSPORT_LE);
  • on some devices like Samsung S7, A8, it was a problem with the ScanSettings.Builder().setReportDelay(400) // or 500ms. it should not be 0 or more like 1000ms.
    ScanSettings settings = new ScanSettings.Builder()
    .setScanMode(ScanSettings.SCAN_MODE_BALANCED)
    .setReportDelay(400)
    .build();`

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests