BLE scanner

newsettler_AI
Posts: 121
Joined: Wed Apr 05, 2017 12:49 pm

BLE scanner

Postby newsettler_AI » Tue Jun 20, 2017 3:19 pm

Hi,

I have two esp32 modules.

My goal is to send and read data via BLE from one esp32 module to another esp32 module.

I'm trying to use GATT_SERVER and GATT_CLIENT from idf examples:
https://github.com/espressif/esp-idf/tr ... att_server
https://github.com/espressif/esp-idf/tr ... att_client

I have edited in CLIENT 72 row:

Code: Select all

static const char device_name[] = "SERV_MODULE";
and set same in SERVER 51 row:

Code: Select all

#define TEST_DEVICE_NAME            "SERV_MODULE"
When I'm running both modules I see that they connected:

Server side log:

Code: Select all

[0;32mI (552) SERVER_DEMO: REGISTER_APP_EVT, status 0, app_id 0
[0m
[0;32mI (552) SERVER_DEMO: REGISTER_APP_EVT, status 0, app_id 1
[0m
[0;32mI (552) SERVER_DEMO: CREATE_SERVICE_EVT, status 0,  service_handle 40
[0m
[0;32mI (562) SERVER_DEMO: CREATE_SERVICE_EVT, status 0,  service_handle 44
[0m
[0;32mI (572) SERVER_DEMO: SERVICE_START_EVT, status 0, service_handle 40
[0m
[0;32mI (572) SERVER_DEMO: ADD_CHAR_EVT, status 0,  attr_handle 42, service_handle 40
[0m
[0;32mI (582) SERVER_DEMO: the gatts demo char length = 3
[0m
[0;32mI (592) SERVER_DEMO: prf_char[0] =11
[0m
[0;32mI (592) SERVER_DEMO: prf_char[1] =22
[0m
[0;32mI (602) SERVER_DEMO: prf_char[2] =33
[0m
[0;32mI (602) SERVER_DEMO: SERVICE_START_EVT, status 0, service_handle 44
[0m
[0;32mI (612) SERVER_DEMO: ADD_CHAR_EVT, status 0,  attr_handle 46, service_handle 44
[0m
[0;32mI (622) SERVER_DEMO: ADD_DESCR_EVT, status 0, attr_handle 43, service_handle 40
[0m
[0;32mI (622) SERVER_DEMO: ADD_DESCR_EVT, status 0, attr_handle 47, service_handle 44
[0m
[0;32mI (14832) SERVER_DEMO: ESP_GATTS_CONNECT_EVT, conn_id 0, remote 30:ae:a4:01:34:ca:, is_conn 1
[0m
[0;32mI (14832) SERVER_DEMO: SERVICE_START_EVT, conn_id 0, remote 30:ae:a4:01:34:ca:, is_conn 1
[0m
[0;32mI (14902) SERVER_DEMO: update connetion params status = 15, min_int = 30, max_int = 50,                  conn_int = 0,latency = 0, timeout = 400[0m
[0;31mE (15402) BT: gatt_disc_cmpl_cback() - Register for service changed indication failure[0m
[0;32mI (15452) SERVER_DEMO: update connetion params status = 13, min_int = 6, max_int = 6,                  conn_int = 0,latency = 0, timeout = 2000[0m
[0;32mI (15452) SERVER_DEMO: update connetion params status = 0, min_int = 6, max_int = 6,                  conn_int = 0,latency = 0, timeout = 2000[0m
[0;32mI (15812) SERVER_DEMO: update connetion params status = 13, min_int = 28, max_int = 28,                  conn_int = 0,latency = 0, timeout = 2000[0m
[0;32mI (15812) SERVER_DEMO: update connetion params status = 0, min_int = 28, max_int = 28,                  conn_int = 0,latency = 0, timeout = 2000[0m
CLIENT side log:

Code: Select all

[0;32mI (542) CLIENT_DEMO: register callback[0m
[0;32mI (552) CLIENT_DEMO: EVT 0, gattc if 3[0m
[0;32mI (552) CLIENT_DEMO: REG_EVT[0m
[0;32mI (552) CLIENT_DEMO: EVT 0, gattc if 4[0m
[0;32mI (552) CLIENT_DEMO: REG_EVT[0m
[0;32mI (572) CLIENT_DEMO: 24 0a c4 00 17 52 [0m
[0;32mI (572) CLIENT_DEMO: Searched Adv Data Len 30, Scan Response Len 0[0m
[0;32mI (572) CLIENT_DEMO: Searched Device Name Len 18[0m
[0;32mI (582) CLIENT_DEMO: SERV_MODULE[0m
[0;32mI (582) CLIENT_DEMO: HP[0m
[0;32mI (592) CLIENT_DEMO: 
[0m
[0;32mI (592) CLIENT_DEMO: Searched device SERV_MODULE
[0m
[0;32mI (602) CLIENT_DEMO: Connect to the remote device.[0m
[0;32mI (612) CLIENT_DEMO: Stop scan successfully[0m
[0;32mI (672) CLIENT_DEMO: EVT 40, gattc if 3[0m
[0;32mI (672) CLIENT_DEMO: EVT 2, gattc if 3[0m
[0;32mI (672) CLIENT_DEMO: ESP_GATTC_OPEN_EVT conn_id 0, if 3, status 0, mtu 23[0m
[0;32mI (672) CLIENT_DEMO: REMOTE BDA:[0m
[0;32mI (682) CLIENT_DEMO: 24 0a c4 00 17 52 [0m
[0;32mI (682) CLIENT_DEMO: EVT 40, gattc if 4[0m
[0;32mI (692) CLIENT_DEMO: EVT 2, gattc if 4[0m
[0;32mI (692) CLIENT_DEMO: ESP_GATTC_OPEN_EVT conn_id 0, if 4, status 0, mtu 23[0m
[0;32mI (702) CLIENT_DEMO: REMOTE BDA:[0m
[0;32mI (702) CLIENT_DEMO: 24 0a c4 00 17 52 [0m
[0;31mE (1342) BT: gatt_disc_cmpl_cback() - Register for service changed indication failure[0m
[0;32mI (1552) CLIENT_DEMO: EVT 7, gattc if 3[0m
[0;32mI (1552) CLIENT_DEMO: SEARCH RES: conn_id = 0[0m
[0;32mI (1552) CLIENT_DEMO: UUID16: 1801[0m
[0;32mI (1552) CLIENT_DEMO: EVT 7, gattc if 3[0m
[0;32mI (1552) CLIENT_DEMO: SEARCH RES: conn_id = 0[0m
[0;32mI (1562) CLIENT_DEMO: UUID16: 1800[0m
[0;32mI (1562) CLIENT_DEMO: EVT 7, gattc if 3[0m
[0;32mI (1572) CLIENT_DEMO: SEARCH RES: conn_id = 0[0m
[0;32mI (1572) CLIENT_DEMO: UUID16: ff[0m
[0;32mI (1582) CLIENT_DEMO: EVT 7, gattc if 3[0m
[0;32mI (1582) CLIENT_DEMO: SEARCH RES: conn_id = 0[0m
[0;32mI (1592) CLIENT_DEMO: UUID16: ee[0m
[0;32mI (1592) CLIENT_DEMO: EVT 6, gattc if 3[0m
[0;32mI (1592) CLIENT_DEMO: SEARCH_CMPL: conn_id = 0, status 0[0m
[0;32mI (1602) CLIENT_DEMO: EVT 7, gattc if 4[0m
[0;32mI (1602) CLIENT_DEMO: SEARCH RES: conn_id = 0[0m
[0;32mI (1612) CLIENT_DEMO: UUID16: 1801[0m
[0;32mI (1612) CLIENT_DEMO: EVT 7, gattc if 4[0m
[0;32mI (1622) CLIENT_DEMO: SEARCH RES: conn_id = 0[0m
[0;32mI (1622) CLIENT_DEMO: UUID16: 1800[0m
[0;32mI (1632) CLIENT_DEMO: EVT 7, gattc if 4[0m
[0;32mI (1632) CLIENT_DEMO: SEARCH RES: conn_id = 0[0m
[0;32mI (1642) CLIENT_DEMO: UUID16: ff[0m
[0;32mI (1642) CLIENT_DEMO: EVT 7, gattc if 4[0m
[0;32mI (1642) CLIENT_DEMO: SEARCH RES: conn_id = 0[0m
[0;32mI (1652) CLIENT_DEMO: UUID16: ee[0m
[0;32mI (1652) CLIENT_DEMO: EVT 6, gattc if 4[0m
[0;32mI (1662) CLIENT_DEMO: SEARCH_CMPL: conn_id = 0, status 0[0m
[0;32mI (1662) CLIENT_DEMO: EVT 35, gattc if 3[0m
[0;32mI (1672) CLIENT_DEMO: EVT 35, gattc if 4[0m
I assume that connection is done properly.
How can I read data on client side?

User avatar
kolban
Posts: 1683
Joined: Mon Nov 16, 2015 4:43 pm
Location: Texas, USA

Re: BLE scanner

Postby kolban » Wed Jun 21, 2017 5:01 am

BLE is a tricky little beastie. Full of acronyms, concepts, states, events and more. However, at a higher level, it sounds like you want a BLE Peripheral and BLE Central. The BLE Peripheral will advertise its existence and the BLE Central will scan for advertising peripherals. Once the Peripheral makes itself known to the Central, the Central can form a connection to the Peripheral. At this point, we have a connection between the two. It is my understanding that both a Peripheral and a Central will both be GATT Servers. Meaning that you can now initiate a read from one to the other.

The units of data are called "Characteristics" and are composed of a characteristic identifier (a UUID), properties and a value. Let us assume that the BLE Central has a characteristic value that you want to retrieve from the BLE Peripheral. On the BLE Peripheral you would invoke esp_ble_gattc_read_char to ask to read a characteristic as a client. This should cause a GATT Server event to be raised on the BLE Central of type ESP_GATTS_READ_EVT. Again on the BLE Central, on receipt of the ESP_GATTS_READ_EVT, you should invoke the esp_ble_gatts_send_response(). This should send the value from the BLE Central. Back on the BLE Peripheral, you should now receive an ESP_GATTC_READ_CHAR_EVT which will contain the data transmitted by the BLE Central. This will have concluded the interaction.

BLE Peripheral BLE Central
esp_ble_gattc_read_char ------>ESP_GATTS_READ_EVT
ESP_GATTC_READ_CHAR_EVTN <---- esp_ble_gatts_send_response
Free book on ESP32 available here: https://leanpub.com/kolban-ESP32

newsettler_AI
Posts: 121
Joined: Wed Apr 05, 2017 12:49 pm

Re: BLE scanner

Postby newsettler_AI » Wed Jun 21, 2017 9:24 am

Hi Kolban,

thanks for explanations.

I see that this way is a bit complex.
My main goal is to get data, its not necessary to pair modules. Let me explain my task more detailed. Let say first module ("slave") is some sensor and it sending data. Second module ("master") is device that gets this data.

I think only broadcasting will be suitable for my task too. According to TexasInstrument analogue I need some kind of broadcaster (slave) and observer (master).

As I understand, I need to implement GAP advertisement on "slave" module.

In "raw" data I expect to get from "slave" something like:

Code: Select all

02010603ffAABBCC03090A0B0C
where
020106 flag that indicates this module configured as broadcaster (i.e. without connection/pairing)
03ffAABBCC is my data AA, BB, CC
03090A0B0C name of device

I tried to run gatt_server with configuration "use raw data".
I can see this "raw" data from mobile phone (in nrf connectify), but I have issue with "master" module.


May be there is example of some observer/scanner for ESP32 without any additions?
I have checked this example
https://github.com/espressif/esp-idf/tr ... th/ble_adv

Looks like there is some function that can provide scan too:

Code: Select all

static int host_rcv_pkt(uint8_t *data, uint16_t len)
but here is output log:

Code: Select all

BLE advt task start
host rcv pkt: 040e0405030c00
controller rcv pkt ready
BLE Advertise, flag_send_avail: 1, cmd_sent: 1
host rcv pkt: 040e0405062000
controller rcv pkt ready
BLE Advertise, flag_send_avail: 1, cmd_sent: 2
host rcv pkt: 040e0405082000
controller rcv pkt ready
BLE Advertise, flag_send_avail: 1, cmd_sent: 3
host rcv pkt: 040e04050a2000
controller rcv pkt ready
BLE Advertise, flag_send_avail: 1, cmd_sent: 4
BLE Advertise, flag_send_avail: 1, cmd_sent: 4
BLE Advertise, flag_send_avail: 1, cmd_sent: 4
BLE Advertise, flag_send_avail: 1, cmd_sent: 4
BLE Advertise, flag_send_avail: 1, cmd_sent: 4
BLE Advertise, flag_send_avail: 1, cmd_sent: 4
BLE Advertise, flag_send_avail: 1, cmd_sent: 4
BLE Advertise, flag_send_avail: 1, cmd_sent: 4
Infinite loop of this string

Code: Select all

BLE Advertise, flag_send_avail: 1, cmd_sent: 4
And I'm not sure from where this packet appeared 040e0405062000

User avatar
kolban
Posts: 1683
Joined: Mon Nov 16, 2015 4:43 pm
Location: Texas, USA

Re: BLE scanner

Postby kolban » Wed Jun 21, 2017 2:21 pm

I'm going to stick my neck out and say that the example shown in your last post should be flagged as "ultra low level". I would not recommend anyone to use the Host Controller Interface (HCI) unless they absolutely know what they are doing and have a skill of 7 out of 10 (at least) in Bluetooth. The HCI is one of the lowest levels of Bluetooth protocol. If others have a different opinion, I'd love to chat about that in a discussion in a separate thread ....

The pattern you describe is known as the Observer/Broadcaster pattern. The broadcaster broadcasts a message each period of time and it is received by all observers. The payload is maxed at 31 bytes (practically 27 or less) however an extra 31 bytes can be added through a procedure known as a scan response.

There are a couple of downsides to Observer/Broadcaster pattern:

1. The Broadcaster will spend energy transmitting without knowing if there are any Observers. Sending information when not needed is a waste of energy and a problem for energy conscious solutions.
2. There will be a latency between a new measurement taken and it being broadcast. The broadcast happens on its schedule which means that when a new sensor measurement arrives, if the broadcast just completed then there will be a full interval before it is broadcast.
3. The loss of a the broadcaster will not be implicitly known to the Observer
4. Security sensitive payload data should never be broadcast

I understand from your post that you are looking for a sample that provides an Observer/Broadcaster pair. I would suggest that the sample you listed is not the one with which to start.
Free book on ESP32 available here: https://leanpub.com/kolban-ESP32

newsettler_AI
Posts: 121
Joined: Wed Apr 05, 2017 12:49 pm

Re: BLE scanner

Postby newsettler_AI » Wed Jun 21, 2017 3:57 pm

The pattern you describe is known as the Observer/Broadcaster pattern. The broadcaster broadcasts a message each period of time and it is received by all observers. The payload is maxed at 31 bytes (practically 27 or less) however an extra 31 bytes can be added through a procedure known as a scan response.
Currently I have written this in GATT_SERVER:

Code: Select all

static uint8_t raw_adv_data[] = {
        0x02, 0x01, 0x06,						    // 0x02 len,  0x01 type(FLAGS) , 0x06 - value
        0x04, 0xFF, 0x19, 0x37,0x64				    // 0x04 len , 0xFF type , value (manuf data): 0x19 0x37 0x64
};

static uint8_t raw_scan_rsp_data[] = {
		0x10, 0x09, 							// 0x10 len in hex (16 dec) of string +1 , 09 type (name)
		0x4d, 0x59, 0x5f, 0x45, 0x53, 0x50, 0x33, 0x32, 0x5f, 0x53, 0x45, 0x4e, 0x53, 0x4f, 0x52 // MY_ESP32_SENSOR
};
I understand that direct input of raw data is not the best way to work with ble, but I need to get at least some results.
There are a couple of downsides to Observer/Broadcaster pattern:

1. The Broadcaster will spend energy transmitting without knowing if there are any Observers. Sending information when not needed is a waste of energy and a problem for energy conscious solutions.
2. There will be a latency between a new measurement taken and it being broadcast. The broadcast happens on its schedule which means that when a new sensor measurement arrives, if the broadcast just completed then there will be a full interval before it is broadcast.
3. The loss of a the broadcaster will not be implicitly known to the Observer
4. Security sensitive payload data should never be broadcast
At first stages of my tasks I see this in next way:
Broadcaster sending data each 10 seconds. When I need to read data, I'm running Observer (with scan time larger than 10 sec or w/e it was configured in broadcaster) and read data, then power off Observer manualy. For the first steps I dont need to monitor data with minimum latency (this will be further) or to fix loss of sensor. This all issues will be for next steps (kind of there is no point to worry about latency if I cant get any data at all)

I'm trying to modify client side in GATT_CLIENT to read "raw" data that I put in GATT_SERVER.

Is there a way how can I read just full GAP info (or get all "raw" data) ?

Can I just put my data into Manufacturer data (0xFF sequence of GAP) and read it on other module?
Correct me if I'm wrong, but beacons works on same principle, without pairing and sending data to all who is "listening"?

newsettler_AI
Posts: 121
Joined: Wed Apr 05, 2017 12:49 pm

Re: BLE scanner

Postby newsettler_AI » Mon Jun 26, 2017 4:09 pm

Few сenturies later I found that all neccessary info about scan located in ble_scan_result_evt_param structure, advertisement data is at ble_adv part .

Need to add

Code: Select all

ESP_LOGI(GATTC_TAG,"BLE_ADV:%s", scan_result->scan_rst.ble_adv);
in esp_gap_cb function. :)

Who is online

Users browsing this forum: Bing [Bot], Google [Bot] and 72 guests