Custom Client, looking for a good place to start

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

cross mob
Anonymous
Not applicable

Hello all,

   

I am hoping to get create a custom client that will be able to handle data that it receives from a server/peripheral device. The server is sending data via notifications. I have already written the server side and was really pleased with all the good example projects that were helpful in development. Now that I am writing the client code, I am finding it slightly more difficult.

   

At this point, I have opened up the PSoC_4_Central_IAS example project in order to get a starting point for develping the client program that I need. The first thing that I did was call a few API's that I added to bleApplications.c in order to discover attribute. I called CyBle_GattcDiscoverAllPrimaryServices(), CyBle_GattcDiscoverAllCharacteristics(),  and CyBle_GattcDiscoverAllCharacteristicDescriptors(). These all have returned with no error. Now that I have done that, I assume that my next step is to enable notifications to come from the server, and then log the data that the server gives me. 
The main questions I have here are, what API do I call to do this? I was thinking about using GattcWriteCharacteristicDescriptors() and writing a 0x01 to UUUID 2902 which is the CCCD handle. Does this seem to make sense?

   

Then I am wondering what else I need to do on the client side to start getting the data that the server sends assuming I have successfully enabled notifications. Do I need to add all the services, characteristics, and descriptors that the server has to be identicle in the client Macro BLE block? At this point, I just mirrored the attributes of the server including all the same UUUID's. Is this necessary?

   

The final thing I am wondering, which sort of relates to the other questions I have asked, is where all the data that the server sends can be found. Is there a function that I should call that returns the value of the data being sent? Or is there some variable or struct that exists which holds the notification data?  

   

I realize there are a lot of questions posed above and I am hoping that someone may have some insight or recommendations of places to go to get some more information, or perhaps an example project that would have some helpful examples. 

   

Thanks for the input, I can clarify any questions you have in response to the above. 

0 Likes
13 Replies
HeLi_263931
Level 8
Level 8
100 solutions authored 50 solutions authored 25 solutions authored

I think the "BLE Heart rate collector" example project might help you, IIRC its a client role. You need to look at the generated code for the HRSCX functions, e.g. HrscConfigHeartRateNtf().

   

You are right, you need to enable the notifications by setting the CCCD. For that you need to know the UUID and the handle of the characteristic you want to access. There is no need to clone the attribute characteristics of the other side - this list is onle neede for a GATT server (and you are a GATT client).

   

When y notification is send, the notification event parameter holds the data. I think you get a CYBLE_EVT_GATTC_HANDLE_VALUE_NTF event in that case. Probably the same example project might help you further.

0 Likes
Anonymous
Not applicable

Project #006 in the 100 Projects in 100 Days series for PSoC 4 BLE is an example of creating devices that assume the GAP Central (or GATT Client) role.

   

Learn more here: Project #006 - BLE Central with Immediate Alert Service

0 Likes
Anonymous
Not applicable

 Samsiek,

   

 

   

Rather than accessing a characteristic descriptor using UUID, I would rather advise to access them using attribute handle. This way, you can uniquely address the characteristic or their descriptors, even if there are multiple ones using same UUID (such as multiple CCCDs).

   

 

   

Use CyBle_GattcWriteCharacteristicDescriptors(connHandle, writeParam) API to access the Descriptor using attribute handle, The attribute handle for a descriptor is rerturned as part of the discovery procedure.

   

 

   

The data that is received from the server is received as part of the event 'CYBLE_EVT_GATTC_HANDLE_VALUE_NTF' in the generic event handler.

   

 

   

Some other events that may interest you as a client device are 'CYBLE_EVT_GATTC_EXEC_WRITE_RSP' for response from server device, 'CYBLE_EVT_GATTC_READ_RSP' for response from server side when you rread a characteristic using CyBle_GattcReadCharacteristicValue() API.

   

 

   

-Roit

0 Likes
Anonymous
Not applicable

Before I explain, some basic terms if you don't know them already: For the remainder of this post, when I mention the word Attribute, it can mean a Service, a Characteristic, or a Descriptor. All the latter 3 terms are basically an attribute. So I will just write Attribute wherever I am talking about all those 3 terms.

   

The first thing which you need to know is that a Handle is different from a UUID. A Handle is a number assigned to an attribute by the Server itself. It is just a local number by which the server identifies that particular attribute. A UUID on the other hand is a number defined by the BLE SIG (for Standard services / characteristics / descriptors) or by the user (for a Custom service / characteristic / descriptor). The UUID is the way by which you (as a user) understand what that attribute means. It doesn't really mean much to the Server device itself. The Server deals with handles. So there is a map in the Server device for "Handle vs UUID" for each Attribute.

   

So now, there are two parts to implementing a Client - 

   
        
  1. The Client needs to first understand the services provided by the Server - this basically means that the client needs to understand the map of "UUIDs vs Handles" of each attribute. The procedure to do this is called the discovery procedure. So the Client needs to Discover the Server first.
  2.     
  3. Once the discovery is complete, the Client knows which Handle belongs to which attribute. So the client can now call the BLE component APIs to write to / read from that handle directly (for example, you write 0x01 to the CCCD handle to enable notifications on the corresponding characteristic).
  4.    
   

Now in order to discover the Server, we need to know whether you are implementing a standard service or a custom service on the Server side. I ask this because the client implementation is a little different for these two. For a standard service (the list of standard services is on the BLE Developer Portal), the BLE component in PSoC Creator does the discovery procedure automatically, once you call the CyBle_GattcStartDiscovery() API. So you won't need to call CyBle_GattcDiscoverAllPrimaryServices(), CyBle_GattcDiscoverAllCharacteristics(), or CyBle_GattcDiscoverAllCharacteristicDescriptors(). For standard services, you have example projects (like the Heart Rate Collector as mentioned in another post, also Project # 006 as mentioned). 

   

If you are implementing a custom service on the server side, then the BLE component on the client side does not discover this custom service automatically (so that you would have to call all those APIs mentioned above). This is a bit tricky and I suggest that you wait for sometime for this to come up. I am creating a project which does precisely this - discover and subscribe to a characteristic as part of a custom service - and this is a part of the 100 Projects in 100 Days series which Gagan mentioned above. The project would basically work with Apple Notification Center Services spec released by Apple. 

   

If you really want to go ahead with Custom client and cannot wait, please write back, and I will be happy to send you something.

   

Happy coding!

   

Uday

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

This is exactly the place where I got stuck right now. I would be very glad about any help you could give me.

   

Can you send some info to me, Cypress knows my email address

   

 

   

Bob

0 Likes
Anonymous
Not applicable

 Udgy,

   

Thanks for the response. To answer one of your questions, I do intend to use a custom server and client. What I have implemented so far is mostly in the GATT settings in BLEapplications.c file. I have started by calling three API's. Those are int discoverAllServices(), in which I call CyBle_GattcDiscoverAllPrimaryServices(connHandle); 

   

Then I have a function called int discoverCharacteristics(), in which I declare 

   

CYBLE_GATT_ATTR_HANDLE_RANGE_T  characteristicRange;

   

    characteristicRange.startHandle = 0x2A00;

   

    characteristicRange.endHandle = 0xAAA7;

   

and call CyBle_GattcDiscoverAllCharacteristics(connHandle, characteristicRange);. 

   

Next I have int discoverDespriptors()

   

{    CYBLE_GATTC_FIND_INFO_REQ_T findInfo;

   

    findInfo.startHandle = 0x2902; //These are the ranges of UUID's I have declared in my custom server.

   

    findInfo.endHandle = 0xAA77; 

   

 CyBle_GattcDiscoverAllCharacteristicDescriptors(connHandle, &findInfo);

   

}

   

The final thing I have is this:

   

void enableNotifications()

   

{

   

    CYBLE_GATTC_WRITE_REQ_T *writeReqParameter;

   

    

   

    uint8 notify = 0x01;

   

    writeReqParameter->attrHandle = 0x2902;

   

    writeReqParameter->value.len = CYBLE_CCCD_LEN;

   

    writeReqParameter->value.val = &notify;

   

    

   

    //This is the actual function call

   

    CyBle_GattcWriteCharacteristicDescriptors(connHandle, writeReqParameter);

   

    

   

 

   

}

   

 

   

This is as far as I have gotten and I don't know if this last function is correct or will execute. Does this look like a good way to start the client code or am I totally missing something importatn? Additionally, I am still a bit confused about what to do if I successfully enable notificaitons. I know that I need to look into the following things:

   

CYBLE_EVT_GATTC_HANDLE_VALUE_NTF', CYBLE_EVT_GATTC_EXEC_WRITE_RSP, and CYBLE_EVT_GATTC_READ_RSP as was mentioned above by Roit. 

   

Thanks for the feedback.

   

Sam

0 Likes
Anonymous
Not applicable

Did you ever get it to work?  We're having a similar issue on our end.  We're trying to read data from a custom server.

0 Likes
HeLi_263931
Level 8
Level 8
100 solutions authored 50 solutions authored 25 solutions authored
        You cannot use the UUIDs as handles. In your GATT server project, there is a generated file 'CYBLE_custom.h'. Look there for the handles.   
0 Likes
Anonymous
Not applicable

 "AN91162 - Creating a BLE Custom Profile" application note is out:

   

http://www.cypress.com/?rID=109900

0 Likes
HeLi_263931
Level 8
Level 8
100 solutions authored 50 solutions authored 25 solutions authored

Oh cool, that will come in handy for so many people...

0 Likes
Anonymous
Not applicable

Yes it will!

0 Likes
Anonymous
Not applicable

Hello, I am new in BLE, can anyone provide some custom client example with custom service, just with one service and one characteristic,I am looking into 100-projects, but there are too many code, which only confuse me. I am try to do it by myself, but there are no result of my trying. 

   

Thanks. Rostyk

0 Likes
Anonymous
Not applicable

Any status update on the current state of the example Custom Client project mentioned in Uday's post?

   

Trying to dig through the examples from other's projectst online is yielding progress pretty slowly; I'm mostly stuck on the actual discovery initiation-handling-finishing process.

   

(Sorry for necro, but looked like a relevant place to post an update request)

0 Likes