Attempting to add another custom characteristic to BLE101 project, need a little help.

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
MaSa_2723681
Level 2
Level 2
5 replies posted Welcome! First question asked

Hello,

I started with the BLE101 (CapSenseLed) example project and that worked fine (using CY8CKIT-042-KIT  aka BLE Pioneer Kit). I wanted to track the time since reset so I put a timer component on the schematic and added an ISR to the TC (Terminal Count) of the timer. The Timer_ISR, which occurs every 5 seconds, toggles the green led and increments a variable "OnTime". And that all works fine.

Then I tried to add a custom characteristic to track the time since reset. I think I did everything right in the BLE component in PSoC Creator 4.1. I used the CySmart1.2 to verify operation and it looks good. (capsenseled Project archive attached).

Then I modified the BLE101 Android Studio project to accomidate the additional "OnTime" data. I did it just like the "capsense" data I think.

However, when click the notify switch for my "OnTime" I get a null pointer exception at the line number 310 in PSoCCapSenseLedService.java. The offending instruction is mOnTimeCccd.setValue(byteVal);

The Android Monitor shows:

Shutting down VM

09-06 13:54:40.786 5263-5263/com.cypress.academy.ble101 E/AndroidRuntime: FATAL EXCEPTION: main

                                                                          Process: com.cypress.academy.ble101, PID: 5263

                                                                          java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.bluetooth.BluetoothGattDescriptor.setValue(byte[])' on a null object reference

                                                                              at com.cypress.academy.ble101.PSoCCapSenseLedService.writeOnTimeNotification(PSoCCapSenseLedService.java:310)

                                                                              at com.cypress.academy.ble101.MainActivity$5.onCheckedChanged(MainActivity.java:186)

                                                                              at android.widget.CompoundButton.setChecked(CompoundButton.java:165)

                                                                              at android.widget.Switch.setChecked(Switch.java:1138)

                                                                              at android.widget.Switch.toggle(Switch.java:1133)

                                                                              at android.widget.CompoundButton.performClick(CompoundButton.java:123)

                                                                              at android.view.View$PerformClick.run(View.java:22570)

                                                                              at android.os.Handler.handleCallback(Handler.java:739)

                                                                              at android.os.Handler.dispatchMessage(Handler.java:95)

                                                                              at android.os.Looper.loop(Looper.java:158)

                                                                              at android.app.ActivityThread.main(ActivityThread.java:7231)

                                                                              at java.lang.reflect.Method.invoke(Native Method)

                                                                              at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)

                                                                              at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)

I have no idea why that is a null pointer. Since this is only a slight variation from the example code I was wondering if someone could try out my code and see what I am doing wrong. Any help would be greatly appricated!

Thank you,

Mark

0 Likes
1 Solution

Never mind. Got it working. Evidently all CCCD UUIDs are 00002902-0000-1000-8000-00805f9b34fb despite what you put in the BLE component GUI. I also moved my updateOnTime() routine from main() to the Timer_ISR().

Thanks,

Mark

View solution in original post

0 Likes
6 Replies
Anonymous
Not applicable

The byteval is fine; you create and declare it in the function itself, so that is not the part failing. My guess is that the error is referring to the mOnTimeCccd object being null; This would be caused by your service discovery not having found the handle/service before you are trying to write a notification (using the writeOnTimeNotification function). Can you verify that you are receiving the service discovered event for the capsenseLedService? Maybe put a breakpoint in that function to see what values are being returned or stepping through it to make sure it is getting a service. Otherwise, the safe fix would be to add a check to make sure you received the UUID handles before trying to send the notification.

(Not that I work with Java much at all )

Epratt

0 Likes

Hello Epratt, Thank you for the suggestions! I agree that the problem must be mOnTimeCccd object being null. I'm new at this so still trying to get my head around everything. So as I understand it, onServicesDiscovered(BluetoothGatt gatt, int status) is called when a service discovery has completed. And gatt is the gatt data base, right? So I should be able to set a break point inside of onServicesDiscovered

and view the gatt data base. I do that and look at it but not sure how to interpret it all. I expected one service with three characteristics. I don't see anything about characteristics.

Still struggling...

Thanks,

Mark

0 Likes
Anonymous
Not applicable

Hello Mark,

I'm not sure how the GATT data is stored, but for access and usage it uses temporary index offset values as "handles"; this means that when you get a handle to a specific service or characteristic it should just return a simple number between 0 and n (n is roughly the number of attributes/declarations in your BLE profile). The phone is most likely holding an "empty" GATT database object with nothing in it when it first connects; Next, it will proceed to "service discovery" this is where it requests all of the services and their offset index (handle) from the device. The device will then return each service as a "service discovered" event/data. Based on this being the method of operation for discovering services, my guess would be that the onServicesDiscovered() event is being called after the example code discovers the handle for the capsense service, but not necessarily after the onTime service handle has been discovered. Or, it could be that the onServicesDiscovered() function is being called upon each service response from the device, in which case you might need to break after the 2nd or 3rd hits rather than the first hit.

This thread should have some useful information: GATT services discovery

0 Likes

I'm making a little progress, after two months. The problem seems to be an issue with the UUID of my OnTimeCccd descriptor. I put in:

00002902-0000-1000-8000-00805F9B34FC in the  GUI and for some reason, after discovery of the GATT data base, it is discovered as

00002902-0000-1000-8000-00805F9B34FB.

The above UUID value that ends in FB is the UUID of the capsenseccd descriptor. So now I have TWO descriptors with the same UUID!

If I change the Android studio app to have the same UUIDs for both, like this:

private final static String CccdUUID =                   "00002902-0000-1000-8000-00805f9b34fb";
private final static String OnTimeCccdUUID =             "00002902-0000-1000-8000-00805f9b34fb";

The app will run. I no longer get the null pointer error but the app only runs for 30 seconds then I get a supervisor time out. I guess that is because the connection was lost for over 30 seconds but I can see the OnTime being updated on the phone every 5 seconds. Strange.

Two questions.

  1.       Why does the UUID that I put in the PSoC Studio GUI not show up upon GATT discovery?
  2.       After “fixing” the UUID of OnTimeCccd, why do I get a supervisor time out and the app dies?

I am re-posting the latest version of my project in case somebody wants to give it a try. Also adding a few screen shots in a word document.

Thanks in advance.

Mark

0 Likes
Anonymous
Not applicable

1. When you discover the UUIDs of services on a BLE device, it will iterate through them in a "random" order, eventually returning all requested values. So, it could be that you are receiving both UUIDs, but one is appearing before the other (I don't think their order is guaranteed).

2. The supervisor timeout means that the devices' communication keep-alive packets are no longer reaching the app; I would take that to mean that your BLE device's radio somehow disconnected, or shut down when the app connected. (There is a supervisor timeout setting on the BLE component in the PSoC studio. You could check the supervisor timeout on the app-side too)

I won't have time to play with your project on hardware, but I'll take a look at the code/settings and see if I notice anything

0 Likes

Never mind. Got it working. Evidently all CCCD UUIDs are 00002902-0000-1000-8000-00805f9b34fb despite what you put in the BLE component GUI. I also moved my updateOnTime() routine from main() to the Timer_ISR().

Thanks,

Mark

0 Likes