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

Fix missing conn_id check in bluetooth_proxy disconnect event #6590

Closed
wants to merge 2 commits into from

Conversation

bdraco
Copy link
Member

@bdraco bdraco commented Apr 19, 2024

What does this implement/fix?

Fix missing conn_id check in bluetooth_proxy disconnect event
Pointed out by @elupus while debugging home-assistant/core#103117

Test yaml

external_components:
  - source: github://pr#6590
    components: [ bluetooth_proxy ]

Types of changes

  • Bugfix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Other

Related issue or feature (if applicable): fixes

Pull request in esphome-docs with documentation (if applicable): esphome/esphome-docs#

Test Environment

  • ESP32
  • ESP32 IDF
  • ESP8266
  • RP2040
  • BK72xx
  • RTL87xx

Example entry for config.yaml:

# Example config.yaml

Checklist:

  • The code change is tested and works locally.
  • Tests have been added to verify that the new code works (under tests/ folder).

If user exposed functionality or configuration variables are added/changed:

@bdraco
Copy link
Member Author

bdraco commented Apr 20, 2024

Pushed to al my production and so far so good. But I didn't see a problem before, however that is likely because I have so many proxies and it was very rare for one to have more than one connection at a time

@elupus
Copy link
Contributor

elupus commented Apr 20, 2024

I think it looks correct. Will report back if i get confirmation on that other issue.

@bdraco bdraco marked this pull request as ready for review April 20, 2024 14:45
@bdraco bdraco requested a review from jesserockz as a code owner April 20, 2024 14:45
@probot-esphome
Copy link

Hey there @jesserockz, mind taking a look at this pull request as it has been labeled with an integration (bluetooth_proxy) you are listed as a code owner for? Thanks!
(message by CodeOwnersMention)

@bdraco
Copy link
Member Author

bdraco commented Apr 20, 2024

Running fine overnight here

@elupus
Copy link
Contributor

elupus commented Apr 21, 2024

Looks like the base class has similar code:

Im suddenly not fully sure here. A bit unclear från docs how one is expected to handle this.

@elupus
Copy link
Contributor

elupus commented Apr 21, 2024

So there are virtual and physical connections. If there are multiple virtual connections to same device, there will not be a disconnect event, only a close event untill all virtual connections are closed.

I dont think this change here will make a difference, might break things if there was never any OPEN event. That said, this should likely listen to CLOSE events with that check.

Not sure if the proxy code manages this virtual connections.

@bdraco
Copy link
Member Author

bdraco commented Apr 21, 2024

https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/bluetooth/esp_gattc.html

close is the virtual
open is the virtual
disconnect is for the physical
connect is for the physical

@bdraco bdraco marked this pull request as draft April 21, 2024 09:11
@bdraco
Copy link
Member Author

bdraco commented Apr 21, 2024

Looks like we don't handle ESP_GATTC_CANCEL_OPEN_EVT

@bdraco
Copy link
Member Author

bdraco commented Apr 21, 2024

not sure ESP_GATTC_CANCEL_OPEN_EVT actually ever happens?

@bdraco
Copy link
Member Author

bdraco commented Apr 21, 2024

ESP_GATTC_CANCEL_OPEN_EVT is never referenced in the underlying code so I don't think it actually ever happens

@bdraco
Copy link
Member Author

bdraco commented Apr 21, 2024

I dont think this change here will make a difference, might break things if there was never any OPEN event. That said, this should likely listen to CLOSE events with that check.

Should be fine if there is never an open event as it will end up freeing the connection slot as it does the same thing as an open failure

@bdraco
Copy link
Member Author

bdraco commented Apr 21, 2024

Here is the order of events for a connection to a lock

[04:24:46][D][esp32_ble_tracker:215]: Pausing scan to make connection...
[04:24:46][I][esp32_ble_client:067]: [0] [78:9C:85:0A:94:40] 0x00 Attempting BLE connection
[04:24:47][D][esp32_ble_client:110]: [0] [78:9C:85:0A:94:40] ESP_GATTC_CONNECT_EVT
[04:24:47][D][esp32_ble_client:110]: [0] [78:9C:85:0A:94:40] ESP_GATTC_OPEN_EVT
[04:24:47][I][esp32_ble_client:154]: [0] [78:9C:85:0A:94:40] Connected
[04:24:47][D][esp32_ble_tracker:266]: Starting scan...
[04:24:47][D][esp32_ble_client:110]: [0] [78:9C:85:0A:94:40] ESP_GATTC_REG_FOR_NOTIFY_EVT
[04:24:47][D][esp32_ble_client:188]: [0] [78:9C:85:0A:94:40] cfg_mtu status 0, mtu 512
[04:24:47][D][esp32_ble_client:110]: [0] [78:9C:85:0A:94:40] ESP_GATTC_WRITE_DESCR_EVT
[04:24:47][D][esp32_ble_client:110]: [0] [78:9C:85:0A:94:40] ESP_GATTC_NOTIFY_EVT
[04:24:47][D][esp32_ble_client:110]: [0] [78:9C:85:0A:94:40] ESP_GATTC_WRITE_CHAR_EVT
[04:24:47][D][esp32_ble_client:110]: [0] [78:9C:85:0A:94:40] ESP_GATTC_NOTIFY_EVT
[04:24:47][D][esp32_ble_client:110]: [0] [78:9C:85:0A:94:40] ESP_GATTC_WRITE_CHAR_EVT
[04:24:47][D][esp32_ble_client:110]: [0] [78:9C:85:0A:94:40] ESP_GATTC_REG_FOR_NOTIFY_EVT
[04:24:47][D][esp32_ble_client:110]: [0] [78:9C:85:0A:94:40] ESP_GATTC_WRITE_DESCR_EVT
[04:24:47][D][esp32_ble_client:110]: [0] [78:9C:85:0A:94:40] ESP_GATTC_NOTIFY_EVT
[04:24:47][D][esp32_ble_client:110]: [0] [78:9C:85:0A:94:40] ESP_GATTC_WRITE_CHAR_EVT
[04:24:47][D][esp32_ble_client:110]: [0] [78:9C:85:0A:94:40] ESP_GATTC_NOTIFY_EVT
[04:24:49][D][esp32_ble_client:110]: [0] [78:9C:85:0A:94:40] ESP_GATTC_NOTIFY_EVT
[04:24:49][D][esp32_ble_client:110]: [0] [78:9C:85:0A:94:40] ESP_GATTC_NOTIFY_EVT
[04:24:54][D][esp32_ble_client:110]: [0] [78:9C:85:0A:94:40] ESP_GATTC_NOTIFY_EVT
[04:24:54][D][esp32_ble_client:110]: [0] [78:9C:85:0A:94:40] ESP_GATTC_WRITE_CHAR_EVT
[04:24:54][D][esp32_ble_client:110]: [0] [78:9C:85:0A:94:40] ESP_GATTC_NOTIFY_EVT
[04:24:54][D][esp32_ble_client:110]: [0] [78:9C:85:0A:94:40] ESP_GATTC_WRITE_CHAR_EVT
[04:24:54][D][esp32_ble_client:110]: [0] [78:9C:85:0A:94:40] ESP_GATTC_NOTIFY_EVT
[04:24:54][D][esp32_ble_client:110]: [0] [78:9C:85:0A:94:40] ESP_GATTC_WRITE_CHAR_EVT
[04:24:54][D][esp32_ble_client:110]: [0] [78:9C:85:0A:94:40] ESP_GATTC_NOTIFY_EVT
[04:24:56][D][esp32_ble_client:110]: [0] [78:9C:85:0A:94:40] ESP_GATTC_NOTIFY_EVT
[04:24:56][D][esp32_ble_client:110]: [0] [78:9C:85:0A:94:40] ESP_GATTC_NOTIFY_EVT
[04:25:06][D][esp32_ble_client:306]: [0] [78:9C:85:0A:94:40] Event 39
[04:25:06][D][esp32_ble_client:110]: [0] [78:9C:85:0A:94:40] ESP_GATTC_WRITE_CHAR_EVT
[04:25:06][D][esp-idf:000]: W (52904) BT_APPL: gattc_conn_cb: if=3 st=0 id=3 rsn=0x13

[04:25:06][D][esp-idf:000]: W (52908) BT_APPL: gattc_conn_cb: if=4 st=0 id=4 rsn=0x13

[04:25:06][D][esp-idf:000]: W (52909) BT_APPL: gattc_conn_cb: if=5 st=0 id=5 rsn=0x13

[04:25:06][D][esp-idf:000]: W (52911) BT_HCI: hcif disc complete: hdl 0x0, rsn 0x13

[04:25:06][D][esp32_ble_client:172]: [0] [78:9C:85:0A:94:40] ESP_GATTC_DISCONNECT_EVT, reason 19
[04:25:06][D][esp32_ble_client:110]: [0] [] ESP_GATTC_CLOSE_EVT

@elupus
Copy link
Contributor

elupus commented Apr 21, 2024

My point was if we have

open() > 1
conn_event
open_event

Second virtual connection starts up

open() > 2
open_event

First virtual connection is closed

close(1)
close_event

(no disconnect here, so proxy still thinks the virtual connection is open)

close(2)
disconnect_event
close_event

Strange order of close disconnect from your log. Now both the proxy connection will be considered closed.

@bdraco
Copy link
Member Author

bdraco commented Apr 21, 2024

Didn't realize it was possible with the proxy code to create more than one virtual connection to the same device. Need to check that it actually is and the library doesn't assume already connected means you get the same connection

@elupus
Copy link
Contributor

elupus commented Apr 21, 2024

I am not sure it is, but ive seen users playing with ble_client configs on the esp proxy itself. See this log.

[13:26:03][I][bluetooth_proxy:278]: [0] [B0:D2:78:91:4C:42] Connecting v3 with cache
[13:26:03][D][esp32_ble_tracker:215]: Pausing scan to make connection...
[13:26:03][I][esp32_ble_client:067]: [0] [B0:D2:78:91:4C:42] 0x00 Attempting BLE connection
[13:26:04][D][esp32_ble_client:110]: [0] [B0:D2:78:91:4C:42] ESP_GATTC_CONNECT_EVT
[13:26:04][D][esp32_ble_client:110]: [0] [B0:D2:78:91:4C:42] ESP_GATTC_OPEN_EVT
[13:26:04][I][esp32_ble_client:154]: [0] [B0:D2:78:91:4C:42] Connected
[13:26:04][D][esp32_ble_client:110]: [3] [B0:D2:78:91:4C:42] ESP_GATTC_CONNECT_EVT
[13:26:04][D][esp32_ble_tracker:266]: Starting scan...
[13:26:04][D][esp32_ble_client:188]: [0] [B0:D2:78:91:4C:42] cfg_mtu status 0, mtu 247
[13:26:04][D][esp32_ble_client:110]: [0] [B0:D2:78:91:4C:42] ESP_GATTC_READ_CHAR_EVT
[13:26:04][D][esp32_ble_client:110]: [0] [B0:D2:78:91:4C:42] ESP_GATTC_READ_CHAR_EVT
[13:26:04][D][esp32_ble_client:110]: [0] [B0:D2:78:91:4C:42] ESP_GATTC_READ_CHAR_EVT
[13:26:04][D][esp32_ble_client:110]: [0] [B0:D2:78:91:4C:42] ESP_GATTC_READ_CHAR_EVT
[13:26:04][D][esp32_ble_client:110]: [0] [B0:D2:78:91:4C:42] ESP_GATTC_READ_CHAR_EVT
[13:26:05][D][esp32_ble_client:110]: [0] [B0:D2:78:91:4C:42] ESP_GATTC_READ_CHAR_EVT
[13:26:05][D][esp32_ble_client:110]: [0] [B0:D2:78:91:4C:42] ESP_GATTC_READ_CHAR_EVT
[13:26:05][D][esp32_ble_client:110]: [0] [B0:D2:78:91:4C:42] ESP_GATTC_READ_CHAR_EVT
[13:26:05][D][esp32_ble_client:110]: [0] [B0:D2:78:91:4C:42] ESP_GATTC_READ_CHAR_EVT
[13:26:05][D][esp32_ble_client:110]: [0] [B0:D2:78:91:4C:42] ESP_GATTC_READ_CHAR_EVT
[13:26:05][D][esp32_ble_client:110]: [0] [B0:D2:78:91:4C:42] ESP_GATTC_READ_CHAR_EVT
[13:26:05][D][esp32_ble_client:110]: [0] [B0:D2:78:91:4C:42] ESP_GATTC_READ_CHAR_EVT
[13:26:05][D][esp32_ble_client:110]: [0] [B0:D2:78:91:4C:42] ESP_GATTC_READ_CHAR_EVT
[13:26:10][I][esp32_ble_client:084]: [0] [B0:D2:78:91:4C:42] Disconnecting.
[13:26:10][D][esp-idf:000]: W (419421) BT_HCI: hci cmd send: disconnect: hdl 0x0, rsn:0x13

[13:26:10][D][esp-idf:000]: W (419425) BT_APPL: gattc_conn_cb: if=3 st=0 id=3 rsn=0x16

[13:26:10][D][esp-idf:000]: W (419427) BT_APPL: gattc_conn_cb: if=4 st=0 id=4 rsn=0x16

[13:26:10][D][esp-idf:000]: W (419428) BT_APPL: gattc_conn_cb: if=5 st=0 id=5 rsn=0x16

[13:26:10][D][esp-idf:000]: W (419430) BT_APPL: gattc_conn_cb: if=6 st=0 id=6 rsn=0x16

[13:26:10][D][esp32_ble_client:110]: [0] [B0:D2:78:91:4C:42] ESP_GATTC_CLOSE_EVT
[13:26:10][D][esp32_ble_client:172]: [0] [B0:D2:78:91:4C:42] ESP_GATTC_DISCONNECT_EVT, reason 22
[13:26:10][D][esp32_ble_client:172]: [3] [B0:D2:78:91:4C:42] ESP_GATTC_DISCONNECT_EVT, reason 22
[13:26:10][D][esp-idf:000]: W (419465) BT_HCI: hcif disc complete: hdl 0x0, rsn 0x16

@bdraco
Copy link
Member Author

bdraco commented Apr 21, 2024

It looks like if you try to connect to an address and it's already connected we return the existing connection

if (connection->state() == espbt::ClientState::CONNECTED ||

@bdraco
Copy link
Member Author

bdraco commented Apr 21, 2024

That definitely doesn't look right. It shouldn't see two connect events. It does look like the check is wrong in esp32_ble_client as well.

[13:26:04][D][esp32_ble_client:110]: [0] [B0:D2:78:91:4C:42] ESP_GATTC_CONNECT_EVT
[13:26:04][D][esp32_ble_client:110]: [0] [B0:D2:78:91:4C:42] ESP_GATTC_OPEN_EVT
[13:26:04][I][esp32_ble_client:154]: [0] [B0:D2:78:91:4C:42] Connected
[13:26:04][D][esp32_ble_client:110]: [3] [B0:D2:78:91:4C:42] ESP_GATTC_CONNECT_EVT

@bdraco
Copy link
Member Author

bdraco commented Apr 21, 2024

We don't set the conn_id until the open event. Hmmm

@bdraco
Copy link
Member Author

bdraco commented Apr 21, 2024

Do you by chance have a reproducer for the above log transaction?

@elupus
Copy link
Contributor

elupus commented Apr 21, 2024

Do you by chance have a reproducer for the above log transaction?

This is all i know:
home-assistant/core#103117 (comment)

@bdraco
Copy link
Member Author

bdraco commented Apr 21, 2024

Are they using the esphome component and the Home Assistant integration at the same time?

home-assistant/core#103117 (comment)

@elupus
Copy link
Contributor

elupus commented Apr 21, 2024

I think in this case incorrectly so yes. I don't think that is the original source of the problem though. I think they have ended up trying many weird things. That said, we should probably behave good in that case too (or fail in a understandable way)

@elupus
Copy link
Contributor

elupus commented Apr 21, 2024

Looks like we don't need to check any conn_id in the proxy code. The base class should have filtered all those events already. but we should likely look at both disconnect and close event.

@elupus
Copy link
Contributor

elupus commented Apr 21, 2024

Here is actually one of those cases where the proxy missing the close event: home-assistant/core#103117 (comment) if you look at the last log lines, we have an event == 5, which is ESP_GATTC_CLOSE_EVT , but no disconnect ever comes. So it's likely still connected by some background connection, which breaks the next proxy connection.

@elupus
Copy link
Contributor

elupus commented Apr 21, 2024

Looks like some things changes (and broke) in #5277, the proxy code will no longer get the failed event status for a ESP_GATTC_OPEN_EVT. It now will return false in base class for this here: https://github.com/esphome/esphome/pull/5277/files#diff-63fb25f9255daa17cf4c5e4faa27822d42c678f5fbca526e44010ba4055ce905R145 so the proxy will no longer parse this event.

@elupus elupus mentioned this pull request Apr 21, 2024
13 tasks
@elupus
Copy link
Contributor

elupus commented Apr 21, 2024

I made an alternate change here: #6596 not sure how i'm going to test that thou.

@bdraco
Copy link
Member Author

bdraco commented May 3, 2024

superseded by #6596

@bdraco bdraco closed this May 3, 2024
@github-actions github-actions bot locked and limited conversation to collaborators May 5, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants