Cannot transmit temperature values via BLE

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

cross mob
HeDi_4635501
Level 3
Level 3
First solution authored 10 questions asked 25 sign-ins

Hi,

I have a CY8CKIT-062-WIFI-BT board and would like to read temperature values from another controller (ESP32 conroller+BME280Sensor), for example.

I use the standard UUIDs (Environmental Sensing Service 0x181a and then the characteristic properties temperature 0x2a6e, humidity 0x2a6F and pressure 0x2a6d). To learn, I use the examples from the ModusToolbox™ Software Training Level 3 - Bluetooth® (e.g. key_ch06_ex04_connect_notify). I don't want to control an LED, just read values.

The GATT database is on.

HeDi_4635501_0-1649604371892.png

 

******************** Application Start ********************
******************** Read BLE Devices ********************
*******************************************************************

Bluetooth Stack Initialization Successful
Bluetooth Management Event: 0x16 BTM_LOCAL_IDENTITY_KEYS_REQUEST_EVT
Bluetooth Management Event: 0x0 BTM_ENABLED_EVT
Bluetooth Enabled
Local Bluetooth Device Address: 00:A0:50:1D:95:63
Commands:
? Help (this message)
s Start scanning and connect
S Stop scanning
d Disconnect
n Turn on Button Count notifications
N Turn off Button Count notifications
0...7 Control LED
r Read LED value

Bluetooth Management Event: 0x17 BTM_BLE_SCAN_STATE_CHANGED_EVT
High duty scanning.
scan_callback function
Device = 30:24:A9:1C:30:6B
scan_callback function
Device = 14:CB:19:E3:C5:BE
scan_callback function
Device = 24:62:AB:F1:F8:2A
scan_callback function
Found Device "ESP32S_BME280" with BD Address: 24:62:AB:F1:F8:2A
RAW Data:
Len = 31 02 01 06 0E 09 45 53 50 33 32 53 5F 42 4D 45 32 38 30 02 0A 03 03 03 1A 18 05 12 12 00 40 00 BB
scan_callback function
Bluetooth Management Event: 0x17 BTM_BLE_SCAN_STATE_CHANGED_EVT
Scanning stopped.
Bluetooth Management Event: 0x14 BTM_PAIRED_DEVICE_LINK_KEYS_REQUEST_EVT
Bluetooth GATT Callback Event: 0x0
GATT_CONNECTION_STATUS_EVT
GATT_CONNECTION_STATUS_EVT: Connect BDA 24:62:AB:F1:F8:2A
Connection ID 32768
Bluetooth Management Event: 0xb BTM_PAIRING_IO_CAPABILITIES_BLE_REQUEST_EVT
Bluetooth Management Event: 0x14 BTM_PAIRED_DEVICE_LINK_KEYS_REQUEST_EVT
Bluetooth Management Event: 0x20 BTM_BLE_CONNECTION_PARAM_UPDATE
Bluetooth Management Event: 0xd BTM_ENCRYPTION_STATUS_EVT
Encrypt status: 0
Bluetooth Management Event: 0x14 BTM_PAIRED_DEVICE_LINK_KEYS_REQUEST_EVT
Bluetooth Management Event: 0x13 BTM_PAIRED_DEVICE_LINK_KEYS_UPDATE_EVT
Bluetooth Management Event: 0xc BTM_PAIRING_COMPLETE_EVT
Pairing complete: 0
Bluetooth Management Event: 0x20 BTM_BLE_CONNECTION_PARAM_UPDATE

I understand the process so far.  Now the services should be read in and I can't get any further.

When I press r for read LED value, a ledHandler = 0x09u is used, where does this value come from (or cccdHandle = 0x0Cu;)?

If I use 0x181a (Environmental Sensing UUID) there is an error.

When I press n or r the following comes up

Bluetooth GATT Callback Event: 0x7

GATT_APP_BUFFER_TRANSMITTED_EVT

Bluetooth GATT Callback Event: 0x1

GATT_OPERATION_CPLT_EVT

p_event_data->operation_complete.status: 0x1

GATT operation failed with status: 1

I don't know how to contact the services to read the value. it works on the smarphone.

HeDi_4635501_1-1649605411446.png

 

0 Likes
1 Solution

Hi @HeDi_4635501 ,

You have to use the Bluetooth host stack library only. To get the events in the desired sequence you have to create a Bluetooth task and block/unblock it using a queue.

For example:

Bluetooth_task():

{

Do the app init;

Establish connection->add data (a number that indicates case for your task immediately after connecting) in your queue that will be used to block/unblock the task;

Switch (queue_data):

                  Case ‘1’ :

                  //do the service discovery, add next data to the queue

                  Case ‘2’:

                  // send read request after given time interval

                  //start the timer, once it expires, send the request

                  .

                  .

                  .

                  .

                  And so on.

}

Please refer to this example : https://github.com/Infineon/training-modustoolbox-level2-psoc/tree/master/Projects/key_ch03_ex03_que... to see how led task is unblocked whenever there is some data in the queue (or how the task remains blocked whenever the queue is empty)

You can map the data in the queue to the case number of the next objective as per your sequence (scanning->connection->discovery->read request)

Thanks and regards.

Advait Kulkarni

View solution in original post

0 Likes
15 Replies
BragadeeshV
Moderator
Moderator
Moderator
First question asked 1000 replies posted 750 replies posted

Hi @HeDi_4635501,

Can you please let us know which Api you used to read the temperature characteristic? If you want to read the characteristic by UUID, you need to use wiced_bt_gatt_client_send_read_by_type(). If you want to read by handle, then first you need to discover all the services, characteristics and note their attribute handle. Also please share the modified project to us for our review.

Regards,
Bragadeesh
0 Likes

Hi,

I work with ModusToolbox 2.4 and Bluetooth Configurator 2.5.

I got the examples from here: ModusToolbox™ Software Training Level3 Bluetooth® (https://github.com/infineon/training-modustoolbox-level3-bluetooth , key_ch06_ex04_connect_notify ).

The function wiced_bt_gatt_client_send_read_handle which is defined in the program code or under mtb_share/btstack/release-v3.3.0 in wiced_bt_gat.h.

I can't find any examples of a central GAP that reads and displays standard UUIDs such as the temperature UUID 0x2a6e. I try to understand the examples mentioned and to adapt what is not linked to me.

I programmed this on a Raspberry Pi and it works. It's very complicated on this board.

0 Likes

Hi @HeDi_4635501 ,

You need to use the 'wiced_bt_client_send_read_by_type' API, https://infineon.github.io/btstack/ble/api_reference_manual/html/group__gatt__client__api__functions... (please refer to this link for various APIs and the parameters they take). You have to initialize parameters for the uuid and length of the data received, by referring to the UUID type structure definition in the wiced_bt_types.h file. For example:

int16_t temperature_val;
wiced_bt_uuid_t uuid;
uint16_t len = 0;
uuid.len = LEN_UUID_16;
uuid.uu.uuid16 = 0x2A6E;
wiced_bt_gatt_client_send_read_by_type(connection_id, 0x1, 0xFFFF, &uuid, (uint8_t *)&temperature_val, sizeof(temperature_val), GATT_AUTH_REQ_NONE);

In the GATT operation complete event in main.c, acquire the data received from the server if the completion status is successful.

Regards,

Advait Kulkarni

0 Likes

Sorry for the late info.

The information was very helpful. I've only now understood the difference between uuid and hadler. The sample program "key_ch06_ex05_discover" can only be understood if you understand the whole handling of BLE. I have tried to understand and adapt the program. Point 1 scan and connect (via the controller name) is understandable.

Reading in the temperature after the last solution does not work.

Started temperature read service. Status: 0x0
Bluetooth GATT Callback Event: 0x1 GATT_OPERATION_CPLT_EVT
GATTC_OPTYPE_READ_HANDLE
temperatue value is: 0.00 ° C

If I first read in the temperature via a handler, then the last solution also works.

Bluetooth GATT Callback Event: 0x1 GATT_OPERATION_CPLT_EVT
GATTC_OPTYPE_READ_HANDLE
temperatue value is: 24.79 ° C
Started temperature read service. Status: 0x0
Bluetooth GATT Callback Event: 0x1 GATT_OPERATION_CPLT_EVT
GATTC_OPTYPE_READ_HANDLE
temperatue value is: 24.79 ° C

I need to call this function first

wiced_bt_gatt_client_send_read_handle(connection_id, tempHandle, 0, (uint8_t *)&tempValue, sizeof(tempValue), GATT_AUTH_REQ_NONE);

and then I can also use this funtion

wiced_bt_gatt_client_send_read_by_type(connection_id, 0x1, 0xFFFF, &uuid, (uint8_t *)&tempValue, sizeof(tempValue), GATT_AUTH_REQ_NONE);

read the value.

The cause is that the 2nd function in GATT_OPERATION_CPLT_EVT always goes into the first if statement.

Started temperature read service. Status: 0x0
Bluetooth GATT Callback Event: 0x1 GATT_OPERATION_CPLT_EVT
p_event_data->operation_complete.op 0x2
GATTC_OPTYPE_READ_HANDLE
temperatue value is: 0.00 ° C

why

Result is notified using GATT_OPERATION_CPLT_EVT of wiced_bt_gatt_cback_t, with wiced_bt_gatt_operation_complete_t::op set to GATTC_OPTYPE_READ_BY_TYPE

and the function doesn't do that


I have a second question.

I would like to display the content of the characteristic user descriptor 0x2901. All, temperature, humidity pressure have a descriptor. How do you do that the Zut temperature is displayed. All this is not a problem on the smartphone, but it is when programming. thank you for your help

 

0 Likes

Hi @HeDi_4635501 ,

1st query: The stack is developed in a way that the data is received in read handle event only even when you send a read by type request.


2nd query: The following is the code to read the characteristic user descriptor:
wiced_bt_uuid_t uuid;
char *f;
uuid.uu.uuid16 = 0x2901;
wiced_bt_gatt_client_send_read_by_type(connection_id, 0x1, 0xFFFF, &uuid, (uint8_t *)&f, sizeof(f), GATT_AUTH_REQ_NONE);

Regards,

Advait Kulkarni

0 Likes

Thank you again and again, because I would not be able to get this with the descriptions alone.

This means that the description in the Bluetooth Host Stack Library is wrong

Result is notified using GATT_OPERATION_CPLT_EVT of wiced_bt_gatt_cback_t, with wiced_bt_gatt_operation_complete_t::op set to GATTC_OPTYPE_READ_BY_TYPE.

How can I differentiate now?

case GATT_OPERATION_CPLT_EVT:

...

if (p_event_data->operation_complete.op == GATTC_OPTYPE_READ_HANDLE)
{
printf("GATTC_OPTYPE_READ_HANDLE\n");
   if (p_event_data->operation_complete.response_data.handle == tempHandle)
   {
     printf("temperatue value is: %4.2f \xb0 C\n",tempValue/100.0);
   }
   else if (p_event_data->operation_complete.response_data.handle == humiHandle)
   {
     printf("humitity value is: %5.2f %%\n",humiValue/100.0);
   }
   else if (p_event_data->operation_complete.response_data.handle == pressHandle)
  {
     printf("pressure value is: %.2f hPa\n",pressValue/1000.0);
   }
}
else if (p_event_data->operation_complete.op == GATTC_OPTYPE_READ_BY_TYPE)
{
   printf("GATTC_OPTYPE_READ_BY_TYPE\n");
  printf("temperatue value is: %4.2f \xb0 C\n",tempValue/100.0);
}

...

Even with your second answer I get into the GATTC_OPTYPE_READ_HANDLE. How do I say what I want to show now?

 

 

0 Likes

Hi @HeDi_4635501 ,

We will update the description in the Bluetooth host stack library regarding the data being received in read handle event irrespective of the request being read handle or read by type.

If you have done service discovery, then you will know which handle corresponds to which data. However, if you have not done service discovery and sending a request using a UUID, the data with that particular UUID only will be received, hence, it is expected that you know which data you are requesting for, while using read by type.
You can refer to the bluetooth spec core v_5.3>Host>ATT>Protocol requirement>Attribute protocol PDUs>Reading attributes
for more clarity on read by type and read handle.

Once you have requested for some data (say temperature), you have to wait till you receive some response before sending another request (say humidity). Thus, you can know what value you have received.

Regards,

Advait Kulkarni

0 Likes

if i use the function wiced_bt_gatt_client_send_read_by_type the temperature 0  is displayed.

case GATT_OPERATION_CPLT_EVT:

...

if (p_event_data->operation_complete.op == GATTC_OPTYPE_READ_HANDLE)
{
printf("GATTC_OPTYPE_READ_HANDLE\n");
   if (p_event_data->operation_complete.response_data.handle == tempHandle)
   {
     printf("temperatue value is: %4.2f \xb0 C\n",tempValue/100.0);
   }

output:

Started temperature read service. Status: 0x0

Bluetooth GATT Callback Event: 0x1 GATT_OPERATION_CPLT_EVT

Gatt Event Complete Conn=32768 Op=2 status=0x0 Handle=0x2A len=2 Data=A8 08

GATTC_OPTYPE_READ_HANDLE

Temperatue value is: 0.00 °C

what is wrong or who writes a value in the variable tempValue

0 Likes

Hi @HeDi_4635501 ,

The tempvalue is used only for values that are greater than the maximum transmission unit's (MTU) size limit (refer to the parameters under the wiced_bt_gatt_client_send_read_by_type() API on this link: https://infineon.github.io/btstack/ble/api_reference_manual/html/group__gatt__client__api__functions...).

Here, you have to use the attribute data, for example,
data = p_event_data->operation_complete.response_data.att_value.p_data;
printf("%f\n",data);

Also, since you are using UUID (read by type API), you do not need to check the response_data.handle. Without service discovery, the client will not know which handle corresponds to which data.

Thank you and regards,

Advait Kulkarni

0 Likes

Hi,

the BLE programming on the Cy8Ckit-62-WiFi-BT with mode toolbox is very complicated. The key_ch06_ex05_discover example is very specific and cannot be generalized.

I have 3 sensors (temperature, humidity and air pressure). The values are to be transmitted via Bluetooth. The board is the GAP Central or GATT Client.

Finding and connecting a BLE client works well.

Reading data from multiple UUIDs does not work. I don't think libraries can do that.

I will now show the services or characteristics.

. startServiceDiscovery();

. startCharacteristicDiscovery();

Now I know the corresponding handles.

*******************************************************************
******************** Application Start ********************
********************** Read BLE Data ***********************
*******************************************************************

Bluetooth Stack Initialization Successful
Bluetooth Enabled
Local Bluetooth Device Address: 00:A0:50:1D:95:63
High duty scanning.
[4090] wiced_post_stack_init_cback(): BT sleep mode is NOT enabled
scan_callback function
Device = 24:62:AB:F1:F8:2A
scan_callback function
Found Device "ESP32S_BME280" with BD Address: 24:62:AB:F1:F8:2A
scan_callback function
Scanning stopped.
GATT_CONNECTION_STATUS_EVT: Connect BDA 24:62:AB:F1:F8:2A
Connection ID 32768
? for Help
Encrypt status: 0
Pairing complete: 0

? for Help

Started service discovery. Status: 0x0
UUID = 0x181a, attr handle: 0x0028, end grp handle: 0xffff

Started characteristic discover. Status: 0x00
charHandleCount = 0
Char Handle=0x0029 Value Handle=0x002A UUID: 2A6E

charHandleCount = 1
Char Handle=0x002D Value Handle=0x002E UUID: 2A6F

charHandleCount = 2
Char Handle=0x0031 Value Handle=0x0032 UUID: 2A6D


Start temp char descriptor discovery. Status: 0x00
Characteristics Descriptor Handle = 0x002B, UUID: 2901

Now I can look at the function wiced_bt_gatt_client_send_read_handle(connection_id, tempHandle, 0, (uint8_t *)&tempValue, sizeof(tempValue), GATT_AUTH_REQ_NONE); Read in temperature, humidity or air pressure values.

Gatt Event Complete Conn=32768 Op=2 status=0x0 Handle=0x2A len=2 Data=5a 09
GATTC_OPTYPE_READ_HANDLE
Temperatue value is: 23.94 °C
Gatt Event Complete Conn=32768 Op=2 status=0x0 Handle=0x2E len=2 Data=25 0e
GATTC_OPTYPE_READ_HANDLE
Humitity value is: 36.21 %
Gatt Event Complete Conn=32768 Op=2 status=0x0 Handle=0x32 len=4 Data=0c 87 0f 00
GATTC_OPTYPE_READ_HANDLE
Pressure value is: 1017.61 hPa
? for Help

I have a problem reading the description of the sensors. It only works with the temperature. I do not know why?

Started startCharacteristicUserDescriptor, Status: 0x0
Gatt Event Complete Conn=32768 Op=3 status=0x0 Handle=0x2B len=23 Data=54 65 6d 70 65 72 61 74 75 72 20 2d 34 30 2e 2e 2b 31 32 35 c2 b0 43
GATTC_OPTYPE_READ_BY_TYPE
Handle: 0x2b
Temperatur -40..+125°C

Only the 0x2B handler is used.

The call function:

static void startCharacteristicUserDescriptor( void )
{
/* val handle temp-2b, humi-2f, press-33 */
wiced_bt_uuid_t uuid;
uuid.len = LEN_UUID_16;
uuid.uu.uuid16 = 0x2901;

wiced_bt_gatt_status_t status = wiced_bt_gatt_client_send_read_by_type(connection_id, 0x0001, 0xffFF, &uuid, (uint8_t *)&descriptor, sizeof(descriptor), GATT_AUTH_REQ_NONE);
printf( "Started startCharacteristicUserDescriptor, Status: 0x%0X\r\n", status ); }

I don't know what to do here! Thanks for the help. there are many descriptions but reading in metrics from clients doesn't seem to be needed. I haven't found any examples (CTC client maybe).

0 Likes
lock attach
Attachments are accessible only for community members.

Hi @HeDi_4635501 ,

This is happening because the user descriptors of each characteristics have the same UUID, which is 2901. Hence, when you send a read by type request, you receive only the one with the lowest HANDLE. (temperature user descriptor handle<other user descriptor handles). So, to get the next lowest handle, you must send another read by type request and update the starting handle in the "wiced_bt_gatt_client_send_read_by_type (uint16_t conn_id, uint16_t s_handle, uint16_t e_handle, wiced_bt_uuid_t *p_uuid, uint8_t *p_read_buf, uint16_t len, wiced_bt_gatt_auth_req_t auth_req)" to one more than the handle of the received descriptor. (For eg, the handle of temperature user descriptor is x, so, send another read by type request with starting handle as x+1, continue sending read by type requests with updated starting handles till you receive all the descriptors).

Alternatively, you can change the definition of read_by_type_handler at the server end in your project in a way that it sends all the handles of the requested type in a single read by type request.

 

I am sharing with you a server project which is an anycloud BLE environment sensing example. Please refer to the "app_gatt_read_by_type_handler" definition in the "app_bt_gatt_handler.c" file. Using this implementation, all the handles with same type will be sent in just one read by type request, by calling the GATT_OPERATION_CPLT_EVT each time till all the handles are sent. Also sharing the client project and the terminal output for reference.

Finally, since you have done the discovery and know the corresponding handles, you can just use the " wiced_bt_gatt_client_send_read_handle" API.

Thanks and regards,

Advait Kulkarni

0 Likes
Hello and thanks for the info.
I wouldn't have gotten any further without the tips. I find the BLE implementation complicated.
My conclusion is to only work with the handle numbers.
My current program flow:
1. scan
2. Determine service handle for ESS
3. Determine the handle number for the characteristics of temperature, humidity and air pressure
4. determine the handle numbers for the user descriptors
This can be easily checked using the menu.
My question: points 2, 3 and 4 should run automatically, i.e. the handle number should be determined and saved automatically.
Then the values ​​should be queried and displayed cyclically via a timer (similar to your example, advertisement).
I now have new problems with RTOS and the bl management. The functions branch into the event handlers, so that I can't get the functions to be processed sequentially. The functions always end somewhere!
Start scanning works, but then???
How to start point 2, 3 and 4 automatically?
Once again thanks for the hints
Is my example, a board reads a sensor (temperature, humidity, air pressure and others) and forwards the data to a second board via Bluetooth. This (central device) reads in the data and displays them. It would be a nice example for Infineon.
best wishes
 
 
0 Likes

Hi @HeDi_4635501 ,

To get the sequence that you want, you can create a Bluetooth task  and inside this task, you can put all the Bluetooth code. You will need to use the "xTaskCreate" command in your int main. Please refer to the https://github.com/Infineon/mtb-example-anycloud-ble-capsense-buttons-slider (ble_task, capsense_task and led_task) example and the https://github.com/Infineon/mtb-example-btstack-freertos-hello-sensor (button_task) example to see how to create a task and how to synchronize it with a timer.

Thanks and regards.

Advait Kulkarni.

0 Likes
Hello,
I looked at several examples.
One problem is that some examples use the Bluetooth Host Stack Library and others use the Bluetooth Low Energy Middleware Library, which have different functions!
Furthermore, all examples are written for "GapRolePeripheral". This means that all programs do a wiced_bt_start_advertisements() and then wait.
I use "GapRoleCentral". This means that my program must first search for the GATT server (scanning). If this is successful, I need the handle numbers from the ESS Service as well as the characteristic temperature, humidity and air pressure.
If I now write these tasks one after the other in the ble_app_management_callback or in the ble_app_init function, there are problems because one job does not wait for the other.
Only after scanning and connecting can I query the ESS service and save the handle number. Then I can query the temperature. If a task is now started cyclically to read out the values, the handle numbers are still missing because the initialization is not yet complete.
So, my biggest problem is the initialization.
to scan and connection (client -> server)
read handle number from ESS
read handle number from temperature
read handle number from humidity
read handle number from air pressure
Each function has to wait for the other.
If the processing is successful, you can output the handle numbers on the appointment for testing.
I just can't do that because the BLE stack works in parallel. How to synchronize the BLE tasks. I don't know!!
Regards
Heinz
0 Likes

Hi @HeDi_4635501 ,

You have to use the Bluetooth host stack library only. To get the events in the desired sequence you have to create a Bluetooth task and block/unblock it using a queue.

For example:

Bluetooth_task():

{

Do the app init;

Establish connection->add data (a number that indicates case for your task immediately after connecting) in your queue that will be used to block/unblock the task;

Switch (queue_data):

                  Case ‘1’ :

                  //do the service discovery, add next data to the queue

                  Case ‘2’:

                  // send read request after given time interval

                  //start the timer, once it expires, send the request

                  .

                  .

                  .

                  .

                  And so on.

}

Please refer to this example : https://github.com/Infineon/training-modustoolbox-level2-psoc/tree/master/Projects/key_ch03_ex03_que... to see how led task is unblocked whenever there is some data in the queue (or how the task remains blocked whenever the queue is empty)

You can map the data in the queue to the case number of the next objective as per your sequence (scanning->connection->discovery->read request)

Thanks and regards.

Advait Kulkarni

0 Likes