8000 Avoid protobuf message construction when tx buffer is full by bdraco · Pull Request #8787 · esphome/esphome · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Avoid protobuf message construction when tx buffer is full #8787

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

Merged
merged 32 commits into from
May 15, 2025
Merged

Conversation

bdraco
Copy link
Member
@bdraco bdraco commented May 14, 2025

What does this implement/fix?

This PR refactors the api_connection to avoid protobuf message construction when the transmit buffer is full.

The code in api_connection.cpp has been restructured to change how messages are sent, avoiding the need to add buffer-full checks in every single send function. This approach is cleaner and solves the problem at its source.

  • Avoids constructing protobuf messages that would fail to send due to a full tx_buffer

  • Eliminates the wasteful cycle of:

    1. Constructing messages
    2. Failing to send
    3. Queuing
    4. Destroying the failed message
    5. Reconstructing the message when retrying
  • Functional changes are

    1. try_to_clear_buffer calls in the new helpers which try again to send the buffer if can_write_without_blocking if false before proceeding to queue the message.
    2. Wrap process_queue with a can_write_without_blocking check
    3. All the try_ functions are now marked as protected because it didn't seem like the intent was to make them part of the public API

Testing

external_components:
  - source: github://pr#8787
    components: [ api ]
    refresh: 0s

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)
  • Code quality improvements to existing code or addition of tests
  • 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:

…e tx_buffer is full

Also do not try to dequeue if the buffer is full
@bdraco bdraco changed the title Refactor api_connection to trying to send messages if the tx_buffer is full Refactor api_connection to avoid trying to send messages if the tx_buffer is full May 14, 2025
@bdraco bdraco changed the title Refactor api_connection to avoid trying to send messages if the tx_buffer is full Refactor api_connection to avoid protobuf message construction if tx_buffer is full May 14, 2025
@bdraco bdraco changed the title Refactor api_connection to avoid protobuf message construction if tx_buffer is full Avoid protobuf message construction when tx buffer is full May 14, 2025
@bdraco bdraco marked this pull request as ready for review May 14, 2025 05:38
@bdraco bdraco requested a review from OttoWinter as a code owner May 14, 2025 05:38
@probot-esphome
Copy link

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

bdraco and others added 2 commits May 14, 2025 17:27
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
Copy link
Member
@jesserockz jesserockz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice logical changes and cleanups.
Testing now on some devices

@jesserockz
Copy link
Member

Working on a handful of devices and one with a bunch of sensors that all send at the same time

@bdraco
Copy link
Member Author
bdraco commented May 15, 2025

Thanks.

Some more dummy entities I used for testing

button:
  - platform: factory_reset
    id: factory_reset_btn
    name: Factory reset

sensor:
  # Uptime sensor.
  - platform: uptime
    name: Ethernet Uptime
  - platform: template
    name: Free Memory
    lambda: return heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
    unit_of_measurement: 'B'
    state_class: measurement
  - platform: template
    id: test_climate_sensor
    lambda: return 20.0;

binary_sensor:
  - platform: template
    name: "Test Binary Sensor"
    lambda: return false;

cover:
  - platform: time_based
    name: "Test Cover"
    open_duration: 5s
    close_duration: 5s
    open_action:
      - logger.log: "Cover opening"
    close_action:
      - logger.log: "Cover closing"
    stop_action:
      - logger.log: "Cover stopping"

fan:
  - platform: binary
    output: test_light_output
    name: "Test Fan"

switch:
  - platform: template
    id: test_switch
    name: "Test Switch"
    lambda: return false;
    turn_on_action:
      - logger.log: "Switch turned on"
    turn_off_action:
      - logger.log: "Switch turned off"
      

text_sensor:
  - platform: version
    name: "ESPHome Version"

light:
  - platform: binary
    name: "Test Light"
    output: test_light_output

climate:
  - platform: bang_bang
    name: "Test Climate"
    sensor: test_climate_sensor
    default_target_temperature_low: 20°C
    default_target_temperature_high: 22°C
    heat_action:
      - switch.turn_on: test_switch
    idle_action:
      - switch.turn_off: test_switch

number:
  - platform: template
    name: "Test Number"
    min_value: 0
    max_value: 100
    step: 1
    lambda: return 50.0;
    set_action:
      - logger.log: "Number set"

select:
  - platform: template
    name: "Test Select"
    options:
      - "Option 1"
      - "Option 2"
    initial_option: "Option 1"
    optimistic: true
    set_action:
      - logger.log: "Select changed"

text:
  - platform: template
    name: "Test Text"
    mode: text
    initial_value: "Hello"
    set_action:
      - logger.log: "Text changed"

lock:
  - platform: output
    name: "Test Lock"
    output: test_light_output

output:
  - platform: gpio
    pin: GPIO0
    id: test_light_output
  - platform: gpio
    pin: GPIO2
    id: test_climate_heat
  - platform: gpio
    pin: GPIO3
    id: test_climate_cool

# Date, Time, and DateTime entities
datetime:
  - platform: template
    type: date
    name: "Test Date"
    initial_value: "2023-05-13"
    optimistic: true
    on_value:
      - logger.log: "Date changed"
  - platform: template
    type: time
    name: "Test Time"
    initial_value: "12:30:00"
    optimistic: true
    on_value:
      - logger.log: "Time changed"
  - platform: template
    type: datetime
    name: "Test DateTime"
    optimistic: true
    on_value:
      - logger.log: "DateTime changed"

# Valve
valve:
  - platform: template
    name: "Test Valve"
    open_action:
      - logger.log: "Valve opening"
    close_action:
      - logger.log: "Valve closing"
    stop_action:
      - logger.log: "Valve stopping"

# For now, commenting out media_player since it requires hardware support
# media_player:
#   - platform: speaker
#     name: "Test Media Player"

# Alarm Control Panel
alarm_control_panel:
  - platform: template
    name: "Test Alarm"
    codes:
      - "1234"
    arming_away_time: 0s
    arming_home_time: 0s
    pending_time: 0s
    trigger_time: 300s
    restore_mode: ALWAYS_DISARMED
    on_disarmed:
      - logger.log: "Alarm disarmed"
    on_arming:
      - logger.log: "Alarm arming"
    on_armed_away:
      - logger.log: "Alarm armed away"
    on_armed_home:
      - logger.log: "Alarm armed home"
    on_pending:
      - logger.log: "Alarm pending"
    on_triggered:
      - logger.log: "Alarm triggered"

# Event
event:
  - platform: template
    name: "Test Event"
    event_types:
      - first_event
      - second_event

@bdraco bdraco merged commit bb1f24a into dev May 15, 2025
29 checks passed
@bdraco bdraco deleted the cleanup_api branch May 15, 2025 02:25
@jesserockz jesserockz added this to the 2025.5.0b4 milestone May 19, 2025
jesserockz added a commit that referenced this pull request May 19, 2025
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
@jesserockz jesserockz mentioned this pull request May 19, 2025
@jesserockz jesserockz mentioned this pull request May 21, 2025
sa-crespo pushed a commit to sa-crespo/esphome that referenced this pull request May 26, 2025
)

Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
sa-crespo pushed a commit to sa-crespo/esphome that referenced this pull request May 26, 2025
)

Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants
0