8000
Skip to content

[modbus_controller] Replace format_hex_pretty with stack-based format_hex_pretty_to - #12781

Merged
bdraco merged 5 commits into
devfrom
modbus_controller
Jan 7, 2026
Merged

[modbus_controller] Replace format_hex_pretty with stack-based format_hex_pretty_to#12781
bdraco merged 5 commits into
devfrom
modbus_controller

Conversation

@bdraco
@bdraco bdraco commented Jan 1, 2026
Copy link
Copy Markdown
Member

What does this implement/fix?

Replace heap-allocating format_hex_pretty(...).c_str() with stack-based format_hex_pretty_to() in the modbus_controller component's verbose logging.

This eliminates std::string heap allocations in the LOGV paths for:

  • modbus_number.cpp - Number write raw logging (uses uint16_t data)
  • modbus_output.cpp - Binary output write raw logging (uses uint8_t data)
  • modbus_switch.cpp - Switch write raw logging (uses uint8_t data)

Also adds a new format_hex_pretty_to() overload for uint16_t* arrays to support the modbus_number case, which formats each 16-bit value as 4 hex chars in big-endian order (matching the existing format_hex_pretty behavior). The existing format_hex_pretty for uint16_t now wraps this new function.

The buffers are wrapped in compile guards to avoid stack allocation when verbose logging is disabled.

Buffer sizes:

  • modbus_number.cpp: 160 bytes (format_hex_pretty_uint16_size(32)) for up to 32 registers
  • modbus_output.cpp / modbus_switch.cpp: 192 bytes (format_hex_pretty_size(64)) for up to 64 bytes

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)
  • Developer breaking change (an API change that could break external components)
  • Code quality improvements to existing code or addition of tests
  • Other

Related issue or feature (if applicable):

  • n/a

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

  • n/a

Test Environment

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

Example entry for config.yaml:

# Standard modbus_controller configuration - no changes needed
uart:
  tx_pin: GPIO17
  rx_pin: GPIO16
  baud_rate: 9600

modbus:

modbus_controller:
  - id: my_modbus
    address: 0x01

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:

@github-actions
github-actions Bot commented Jan 1, 2026
Copy link
Copy Markdown
Contributor

To use the changes in this PR:

# Clone the repository:
git clone https://github.com/esphome/esphome
cd esphome

# Checkout the PR branch:
git fetch origin pull/12781/head:modbus_controller
git checkout modbus_controller

# Install the development version:
script/setup

# Activate the development version:
source venv/bin/activate

Now you can run esphome as usual to test the changes in this PR.


(Added by the PR bot)

@codecov-commenter
codecov-commenter commented Jan 1, 2026
Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 73.48%. Comparing base (ac42102) to head (c285ff8).

Additional details and impacted files
@@           Coverage Diff           @@
##              dev   #12781   +/-   ##
=======================================
  Coverage   73.48%   73.48%           
=======================================
  Files          53       53           
  Lines       11313    11313           
  Branches     1535     1535           
=======================================
  Hits         8313     8313           
  Misses       2602     2602           
  Partials      398      398           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions
github-actions Bot commented Jan 1, 2026
Copy link
Copy Markdown
Contributor

Memory Impact Analysis

Components: modbus_controller
Platform: esp8266-ard

Metric Target Branch This PR Change
RAM 29,944 bytes 29,724 bytes 📉 ✅ -220 bytes (-0.73%)
Flash 326,735 bytes 325,227 bytes 📉 ✅ -1,508 bytes (-0.46%)
📊 Component Memory Breakdown
Component Target Flash PR Flash Change
cpp_runtime 3,394 bytes 2,475 bytes 📉 -919 bytes (-27.08%)
[esphome]core 10,224 bytes 9,753 bytes 📉 🎉 -471 bytes (-4.61%)
cpp_stdlib 935 bytes 734 bytes 📉 -201 bytes (-21.50%)
[esphome]modbus_controller 20,111 bytes 20,272 bytes 📈 🔸 +161 bytes (+0.80%)
🔍 Symbol-Level Changes (click to expand)

Changed Symbols

Symbol Target Size PR Size Change
esphome::modbus_controller::ModbusSwitch::write_state(bool) 703 bytes 804 bytes 📈 +101 bytes (+14.37%)
esphome::modbus_controller::ModbusNumber::control(float) 744 bytes 804 bytes 📈 +60 bytes (+8.06%)

New Symbols (top 15)

Symbol Size
esphome::format_hex_pretty_to(char*, unsigned int, unsigned short const*, unsigned int, char) 233 bytes

Removed Symbols (top 15)

Symbol Size
esphome::format_hex_pretty[abi:cxx11](unsigned short const*, unsigned int, char, bool) 381 bytes
std::__cxx11::basic_string<char, std::char_traits, std::allocator >::_M_replace(unsig...std::__cxx11::basic_string<char, std::char_traits, std::allocator >::_M_replace(unsigned int, unsigned int, char const*, unsigned int)
280 bytes
std::__cxx11::to_string(unsigned int) 279 bytes
esphome::format_hex_pretty_uint8(unsigned char const*, unsigned int, char, bool) 237 bytes
std::__detail::__to_chars_10_impl<unsigned int>(char*, unsigned int, unsigned int)::__digits 201 bytes
std::__cxx11::basic_string<char, std::char_traits, std::allocator > std::operator+<ch...std::__cxx11::basic_string<char, std::char_traits, std::allocator > std::operator+<char, std::char_traits, std::allocator >(std::__cxx11::basic_string<char, std::char_traits, std::allocator >&&, std::__cxx11::basic_string<char, std::char_traits, std::allocator >&&)
87 bytes
std::__cxx11::basic_string<char, std::char_traits, std::allocator >::_M_append(char c...std::__cxx11::basic_string<char, std::char_traits, std::allocator >::_M_append(char const*, unsigned int)
84 bytes
std::__cxx11::basic_string<char, std::char_traits, std::allocator >::basic_string(std...std::__cxx11::basic_string<char, std::char_traits, std::allocator >::basic_string(std::__cxx11::basic_string<char, std::char_traits, std::allocator >&&)
71 bytes
std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::append(char const*) 57 bytes
esphome::format_hex_pretty[abi:cxx11](std::vector<unsigned char, std::allocator > ...esphome::format_hex_pretty[abi:cxx11](std::vector<unsigned char, std::allocator > const&, char, bool)
43 bytes
esphome::format_hex_pretty[abi:cxx11](std::vector<unsigned short, std::allocator ...esphome::format_hex_pretty[abi:cxx11](std::vector<unsigned short, std::allocator > const&, char, bool)
43 bytes

Note: This analysis measures static RAM and Flash usage only (compile-time allocation).
Dynamic memory (heap) cannot be measured automatically.
⚠️ You must test this PR on a real device to measure free heap and ensure no runtime memory issues.

This analysis runs automatically when components change. Memory usage is measured from a representative test configuration.

@esphome esphome Bot added core and removed small-pr PR < 30 lines labels Jan 1, 2026
@bdraco
bdraco marked this pull request as ready for review January 1, 2026 02:48
Copilot AI review requested due to automatic review settings January 1, 2026 02:48
@bdraco
bdraco requested review from a team and martgras as code owners January 1, 2026 02:48
@github-actions
github-actions Bot commented Jan 1, 2026
Copy link
Copy Markdown
Contributor

👋 Hi there! This PR modifies 5 file(s) with codeowners.

@martgras, @esphome/core - As codeowner(s) of the affected files, your review would be appreciated! 🙏

Note: Automatic review request may have failed, but you're still welcome to review.

Copilot AI left a comment
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR optimizes verbose logging in the modbus_controller component by replacing heap-allocating format_hex_pretty(...).c_str() calls with stack-based format_hex_pretty_to() calls. The changes introduce a new format_hex_pretty_to() overload for uint16_t* arrays and refactor the existing format_hex_pretty() for uint16_t to use the new function.

Key changes:

  • Adds new format_hex_pretty_to() overload for uint16_t arrays with corresponding helper function format_hex_pretty_uint16_size()
  • Refactors existing format_hex_pretty() for uint16_t to delegate to the new buffer-based function
  • Updates three modbus component files to use stack-allocated buffers with compile guards for verbose logging

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
esphome/core/helpers.h Declares new format_hex_pretty_to() overload for uint16_t arrays and size calculation helper
esphome/core/helpers.cpp Implements uint16_t version of format_hex_pretty_to() and refactors format_hex_pretty() to use it
esphome/components/modbus_controller/switch/modbus_switch.cpp Replaces heap allocation with stack buffer for verbose logging of uint8_t data
esphome/components/modbus_controller/output/modbus_output.cpp Replaces heap allocation with stack buffer for verbose logging of uint8_t data
esphome/components/modbus_controller/number/modbus_number.cpp Replaces heap allocation with stack buffer for verbose logging of uint16_t data

Comment thread esphome/components/modbus_controller/output/modbus_output.cpp
Comment thread esphome/components/modbus_controller/number/modbus_number.cpp
Comment thread esphome/core/helpers.h
Comment thread esphome/components/modbus_controller/switch/modbus_switch.cpp
@bdraco
bdraco commented Jan 7, 2026
Copy link
Copy Markdown
Member Author

thanks

@bdraco
bdraco merged commit d86d1f9 into dev Jan 7, 2026
27 checks passed
@bdraco
bdraco deleted the modbus_controller branch January 7, 2026 18:29
@github-actions github-actions Bot locked and limited conversation to collaborators Jan 9, 2026
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.

4 participants

0