8000 10BC0
Skip to content

[dsmr] Remove dependency on Arduino framework. Various bug fixes. Add missing sensors. - #11036

Merged
bdraco merged 3 commits into
esphome:devfrom
PolarGoose:dev
Jan 6, 2026
Merged

[dsmr] Remove dependency on Arduino framework. Various bug fixes. Add missing sensors.#11036
bdraco merged 3 commits into
esphome:devfrom
PolarGoose:dev

Conversation

@PolarGoose
@PolarGoose PolarGoose commented Oct 6, 2025
Copy link
Copy Markdown
Contributor

What does this implement/fix?

Introduce bare minimum changes in the DSMR component to:

  • Make it work without the Arduino framework.
  • Fix various existing bugs with the DSMR parsing.
  • Add missing sensor definitions.

The code uses arduino-dsmr-2 parser.
For more details on why this pull request was created, look at the discussion: Make the parser compile for Windows and Linux machines.
In short:

  • There are many bugs and unmerged pull requests accumulated in the arduino-dsmr parser.
  • Dependency on the Arduino framework causes problems for some ESPHome use cases.

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):

Test Environment

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

Example entry for config.yaml:

I used the following config to test on my ESP32-WROOM-32D board.

esphome:
  name: mydsmrtestbench
  friendly_name: my_dsmr_test_bench

esp32:
  board: esp32dev
  framework:
    type: esp-idf

wifi:
  ssid: SSID
  password: PASSWORD

logger:
  level: VERY_VERBOSE
  baud_rate: 1500000
  tx_buffer_size: 20000

uart:
  id: uart_dsmr
  baud_rate: 115200
  rx_pin: GPIO16
  rx_buffer_size: 1700

dsmr:
  uart_id: uart_dsmr
  crc_check: true
  decryption_key: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

sensor:
  - platform: dsmr

    energy_delivered_lux:
      name: "Energy Consumed Luxembourg. OBIS: 1-0:1.8.0"
    energy_delivered_tariff1:
      name: "Energy Consumed Tariff 1. OBIS: 1-0:1.8.1"
    energy_delivered_tariff2:
      name: "Energy Consumed Tariff 2. OBIS: 1-0:1.8.2"
    energy_delivered_tariff3:
      name: "Energy Consumed Tariff 3. OBIS: 1-0:1.8.3"
    energy_delivered_tariff4:
      name: "Energy Consumed Tariff 4. OBIS: 1-0:1.8.4"
    energy_returned_lux:
      name: "Energy Produced Luxembourg. OBIS: 1-0:2.8.0"
    energy_returned_tariff1:
      name: "Energy Produced Tariff 1. OBIS: 1-0:2.8.1"
    energy_returned_tariff2:
      name: "Energy Produced Tariff 2. OBIS: 1-0:2.8.2"
    energy_returned_tariff3:
      name: "Energy Produced Tariff 3. OBIS: 1-0:2.8.3"
    energy_returned_tariff4:
      name: "Energy Produced Tariff 4. OBIS: 1-0:2.8.4"
    energy_delivered_tariff1_ch:
      name: "Energy Consumed Tariff 1 (CH). OBIS: 1-1:1.8.1"
    energy_delivered_tariff2_ch:
      name: "Energy Consumed Tariff 2 (CH). OBIS: 1-1:1.8.2"
    energy_returned_tariff1_ch:
      name: "Energy Produced Tariff 1 (CH). OBIS: 1-1:2.8.1"
    energy_returned_tariff2_ch:
      name: "Energy Produced Tariff 2 (CH). OBIS: 1-1:2.8.2"
    total_imported_energy:
      name: "Reactive Energy Imported (Total). OBIS: 1-0:3.8.0"
    reactive_energy_delivered_tariff1:
      name: "Reactive Energy Imported Tariff 1. OBIS: 1-0:3.8.1"
    reactive_energy_delivered_tariff2:
      name: "Reactive Energy Imported Tariff 2. OBIS: 1-0:3.8.2"
    reactive_energy_delivered_tariff3:
      name: "Reactive Energy Imported Tariff 3. OBIS: 1-0:3.8.3"
    reactive_energy_delivered_tariff4:
      name: "Reactive Energy Imported Tariff 4. OBIS: 1-0:3.8.4"
    total_exported_energy:
      name: "Reactive Energy Exported (Total). OBIS: 1-0:4.8.0"
    reactive_energy_returned_tariff1:
      name: "Reactive Energy Exported Tariff 1. OBIS: 1-0:4.8.1"
    reactive_energy_returned_tariff2:
      name: "Reactive Energy Exported Tariff 2. OBIS: 1-0:4.8.2"
    reactive_energy_returned_tariff3:
      name: "Reactive Energy Exported Tariff 3. OBIS: 1-0:4.8.3"
    reactive_energy_returned_tariff4:
      name: "Reactive Energy Exported Tariff 4. OBIS: 1-0:4.8.4"
    power_delivered:
      name: "Power Consumed. OBIS: 1-0:1.7.0"
      accuracy_decimals: 3
    power_returned:
      name: "Power Produced. OBIS: 1-0:2.7.0"
      accuracy_decimals: 3
    power_delivered_ch:
      name: "Power Consumed (CH). OBIS: 1-1:1.7.0"
    power_returned_ch:
      name: "Power Produced (CH). OBIS: 1-1:2.7.0"
    reactive_power_delivered:
      name: "Reactive Power Imported. OBIS: 1-0:3.7.0"
    reactive_power_returned:
      name: "Reactive Power Exported. OBIS: 1-0:4.7.0"
    electricity_threshold:
      name: "Electricity Threshold. OBIS: 0-0:17.0.0"
    electricity_switch_position:
      name: "Electricity Switch Position. OBIS: 0-0:96.3.10"
    electricity_failures:
      name: "Electricity Failures. OBIS: 0-0:96.7.21"
    electricity_long_failures:
      name: "Long Electricity Failures. OBIS: 0-0:96.7.9"
    electricity_sags_l1:
      name: "Voltage Sags L1. OBIS: 1-0:32.32.0"
    electricity_sags_l2:
      name: "Voltage Sags L2. OBIS: 1-0:52.32.0"
    electricity_sags_l3:
      name: "Voltage Sags L3. OBIS: 1-0:72.32.0"
    electricity_swells_l1:
      name: "Voltage Swells L1. OBIS: 1-0:32.36.0"
    electricity_swells_l2:
      name: "Voltage Swells L2. OBIS: 1-0:52.36.0"
    electricity_swells_l3:
      name: "Voltage Swells L3. OBIS: 1-0:72.36.0"
    voltage_sag_time_l1:
      name: "Voltage Sag Time L1. OBIS: 1-0:32.33.0"
    voltage_sag_time_l2:
      name: "Voltage Sag Time L2. OBIS: 1-0:52.33.0"
    voltage_sag_time_l3:
      name: "Voltage Sag Time L3. OBIS: 1-0:72.33.0"
    voltage_sag_l1:
      name: "Voltage Sag L1. OBIS: 1-0:32.34.0"
    voltage_sag_l2:
      name: "Voltage Sag L2. OBIS: 1-0:52.34.0"
    voltage_sag_l3:
      name: "Voltage Sag L3. OBIS: 1-0:72.34.0"
    voltage_swell_time_l1:
      name: "Voltage Swell Time L1. OBIS: 1-0:32.37.0"
    voltage_swell_time_l2:
      name: "Voltage Swell Time L2. OBIS: 1-0:52.37.0"
    voltage_swell_time_l3:
      name: "Voltage Swell Time L3. OBIS: 1-0:72.37.0"
    voltage_swell_l1:
      name: "Voltage Swell L1. OBIS: 1-0:32.38.0"
    voltage_swell_l2:
      name: "Voltage Swell L2. OBIS: 1-0:52.38.0"
    voltage_swell_l3:
      name: "Voltage Swell L3. OBIS: 1-0:72.38.0"
    current_l1:
      name: "Current Phase 1. OBIS: 1-0:31.7.0"
    current_l2:
      name: "Current Phase 2. OBIS: 1-0:51.7.0"
    current_l3:
      name: "Current Phase 3. OBIS: 1-0:71.7.0"
    current:
      name: "Current. OBIS: 1-0:11.7.0"
    current_n:
      name: "Neutral Current. OBIS: 1-0:91.7.0"
    current_sum:
      name: "Current Sum. OBIS: 1-0:90.7.0"
    current_fuse_l1:
      name: "Current Fuse Phase 1. OBIS: 1-0:31.4.0"
    current_fuse_l2:
      name: "Current Fuse Phase 2. OBIS: 1-0:51.4.0"
    current_fuse_l3:
      name: "Current Fuse Phase 3. OBIS: 1-0:71.4.0"
    power_delivered_l1:
      name: "Power Consumed Phase 1. OBIS: 1-0:21.7.0"
    power_delivered_l2:
      name: "Power Consumed Phase 2. OBIS: 1-0:41.7.0"
    power_delivered_l3:
      name: "Power Consumed Phase 3. OBIS: 1-0:61.7.0"
    power_returned_l1:
      name: "Power Produced Phase 1. OBIS: 1-0:22.7.0"
    power_returned_l2:
      name: "Power Produced Phase 2. OBIS: 1-0:42.7.0"
    power_returned_l3:
      name: "Power Produced Phase 3. OBIS: 1-0:62.7.0"
    reactive_power_delivered_l1:
      name: "Reactive Power Imported L1. OBIS: 1-0:23.7.0"
    reactive_power_delivered_l2:
      name: "Reactive Power Imported L2. OBIS: 1-0:43.7.0"
    reactive_power_delivered_l3:
      name: "Reactive Power Imported L3. OBIS: 1-0:63.7.0"
    reactive_power_returned_l1:
      name: "Reactive Power Exported L1. OBIS: 1-0:24.7.0"
    reactive_power_returned_l2:
      name: "Reactive Power Exported L2. OBIS: 1-0:44.7.0"
    reactive_power_returned_l3:
      name: "Reactive Power Exported L3. OBIS: 1-0:64.7.0"
    voltage_l1:
      name: "Voltage Phase 1. OBIS: 1-0:32.7.0"
    voltage_l2:
      name: "Voltage Phase 2. OBIS: 1-0:52.7.0"
    voltage_l3:
      name: "Voltage Phase 3. OBIS: 1-0:72.7.0"
    voltage_avg_l1:
      name: "Voltage Avg Phase 1. OBIS: 1-0:32.24.0"
    voltage_avg_l2:
      name: "Voltage Avg Phase 2. OBIS: 1-0:52.24.0"
    voltage_avg_l3:
      name: "Voltage Avg Phase 3. OBIS: 1-0:72.24.0"
    voltage:
      name: "Voltage (Overall). OBIS: 1-0:12.7.0"
    frequency:
      name: "Grid Frequency. OBIS: 1-0:14.7.0"
    abs_power:
      name: "Absolute active instantaneous power. OBIS: 1-0:15.7.0"
    gas_delivered:
      name: "Gas Consumed. OBIS: 0-1:24.2.1"
    gas_delivered_be:
      name: "Gas Consumed Belgium. OBIS: 0-1:24.2.3"
    water_delivered:
      name: "Water Consumed. OBIS: 0-2:24.2.1"
    thermal_delivered:
      name: "Thermal Energy Consumed. OBIS: 0-3:24.2.1"
    sub_delivered:
      name: "Submeter Volume. OBIS: 0-4:24.2.1"
    gas_device_type:
      name: "Gas Device Type. OBIS: 0-1:24.1.0"
    gas_valve_position:
      name: "Gas Valve Position. OBIS: 0-1:24.4.0"
    thermal_device_type:
      name: "Thermal Device Type. OBIS: 0-3:24.1.0"
    thermal_valve_position:
      name: "Thermal Valve Position. OBIS: 0-3:24.4.0"
    water_device_type:
      name: "Water Device Type. OBIS: 0-2:24.1.0"
    water_valve_position:
      name: "Water Valve Position. OBIS: 0-2:24.4.0"
    sub_device_type:
      name: "Submeter Device Type. OBIS: 0-4:24.1.0"
    sub_valve_position:
      name: "Submeter Valve Position. OBIS: 0-4:24.4.0"
    apparent_delivery_power:
      name: "Apparent Power Delivered. OBIS: 1-0:9.7.0"
    apparent_delivery_power_l1:
      name: "Apparent Power Delivered L1. OBIS: 1-0:29.7.0"
    apparent_delivery_power_l2:
      name: "Apparent Power Delivered L2. OBIS: 1-0:49.7.0"
    apparent_delivery_power_l3:
      name: "Apparent Power Delivered L3. OBIS: 1-0:69.7.0"
    apparent_return_power:
      name: "Apparent Power Returned. OBIS: 1-0:10.7.0"
    apparent_return_power_l1:
      name: "Apparent Power Returned L1. OBIS: 1-0:30.7.0"
    apparent_return_power_l2:
      name: "Apparent Power Returned L2. OBIS: 1-0:50.7.0"
    apparent_return_power_l3:
      name: "Apparent Power Returned L3. OBIS: 1-0:70.7.0"
    active_demand_power:
      name: "Active Demand (Avg3 Plus). OBIS: 1-0:1.24.0"
    active_demand_abs:
      name: "Active Demand (Avg3) Absolute. OBIS: 1-0:15.24.0"
    active_energy_import_current_average_demand:
      name: "Current Average Quarterly Demand for Peak Tarrif Belgium. OBIS: 1-0:1.4.0"
    active_energy_export_current_average_demand:
      name: "Avg Export Demand (Active). OBIS: 1-0:2.4.0"
    reactive_energy_import_current_average_demand:
      name: "Avg Import Demand (Reactive). OBIS: 1-0:3.4.0"
    reactive_energy_export_current_average_demand:
      name: "Avg Export Demand (Reactive). OBIS: 1-0:4.4.0"
    apparent_energy_import_current_average_demand:
      name: "Avg Import Demand (Apparent). OBIS: 1-0:9.4.0"
    apparent_energy_export_current_average_demand:
      name: "Avg Export Demand (Apparent). OBIS: 1-0:10.4.0"
    active_energy_import_last_completed_demand:
      name: "Last Completed Import Demand (Active). OBIS: 1-0:1.5.0"
    active_energy_export_last_completed_demand:
      name: "Last Completed Export Demand (Active). OBIS: 1-0:2.5.0"
    reactive_energy_import_last_completed_demand:
      name: "Last Completed Import Demand (Reactive). OBIS: 1-0:3.5.0"
    reactive_energy_export_last_completed_demand:
      name: "Last Completed Export Demand (Reactive). OBIS: 1-0:4.5.0"
    apparent_energy_import_last_completed_demand:
      name: "Last Completed Import Demand (Apparent). OBIS: 1-0:9.5.0"
    apparent_energy_export_last_completed_demand:
      name: "Last Completed Export Demand (Apparent). OBIS: 1-0:10.5.0"
    active_energy_import_maximum_demand_running_month:
      name: "Max Import Demand This Month (Active). OBIS: 1-0:1.6.0"
    active_energy_import_maximum_demand_last_13_months:
      name: "Average of Monthly Max Import (Active, 13 months). OBIS: 0-0:98.1.0"
    fw_core_version:
      name: "Meter FW Core Version. OBIS: 1-0:0.2.0"
    fw_module_version:
      name: "Meter FW Module Version. OBIS: 1-1:0.2.0"

text_sensor:
  - platform: dsmr
    identification:
      name: "DSMR Identification"
    p1_version:
      name: "DSMR Version. OBIS: 1-3:0.2.8"
    p1_version_be:
      name: "DSMR Version Belgium. OBIS: 0-0:96.1.4"
    timestamp:
      name: "Telegram Timestamp. OBIS: 0-0:1.0.0"
    electricity_tariff:
      name: "Electricity Tariff. OBIS: 0-0:96.14.0"
    electricity_failure_log:
      name: "Electricity Failure Log. OBIS: 1-0:99.97.0"
    message_short:
      name: "Message Short. OBIS: 0-0:96.13.1"
    message_long:
      name: "Message Long. OBIS: 0-0:96.13.0"
    equipment_id:
      name: "Electric Meter Equipment ID. OBIS: 0-0:96.1.1"
    gas_equipment_id:
      name: "Gas Equipment ID. OBIS: 0-1:96.1.0"
    gas_equipment_id_be:
      name: "Gas Equipment ID Belgium. OBIS: 0-1:96.1.1"
    thermal_equipment_id:
      name: "Thermal Equipment ID. OBIS: 0-3:96.1.0"
    water_equipment_id:
      name: "Water Equipment ID. OBIS: 0-2:96.1.0"
    sub_equipment_id:
      name: "Submeter Equipment ID. OBIS: 0-4:96.1.0"
    gas_delivered_text:
      name: "Unformatted gas data. OBIS: 0-1:24.3.0"
    fw_core_checksum:
      name: "FW Core Checksum. OBIS: 1-0:0.2.8"
    fw_module_checksum:
      name: "FW Module Checksum. OBIS: 1-1:0.2.8"

    # The (decrypted) unparsed telegram, marked as an internal sensor.
    # Can also be used to trigger an action based on the last values.
    telegram:
      name: "Raw DSMR Telegram"
      internal: true

  - platform: version
    name: "ESPHome Version"
    hide_timestamp: true

Checklist:

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

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

@PolarGoose
PolarGoose requested a review from glmnet as a code owner October 6, 2025 01:28
Copilot AI review requested due to automatic review settings October 6, 2025 01:28
@github-actions
github-actions Bot commented Oct 6, 2025
Copy link
Copy Markdown
Contributor

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

@glmnet, @zuidwijk - 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.

@github-actions
github-actions Bot commented Oct 6, 2025
Copy link
Copy Markdown
Contributor

To use the changes from this PR as an external component, add the following to your ESPHome configuration YAML file:

external_components:
  - source: github://pr#11036
    components: [dsmr]
    refresh: 1h

(Added by the PR bot)

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 pull request removes the Arduino framework dependency from the DSMR component and switches to a new parser library to fix various bugs. The changes replace the existing arduino-dsmr library with arduino-dsmr-2 and its associated crypto library, while updating namespace references and removing Arduino-specific conditional compilation guards.

Key changes:

  • Switch from arduino-dsmr to arduino-dsmr-2 parser library
  • Remove Arduino framework dependency and related conditional compilation
  • Update namespace references from ::dsmr::fields to arduino_dsmr_2::fields

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
esphome/components/dsmr/dsmr.h Updates include paths, namespace references, and removes Arduino conditional compilation
esphome/components/dsmr/dsmr.cpp Updates parser namespace and removes Arduino conditional compilation
esphome/components/dsmr/init.py Replaces library dependencies and removes Arduino framework requirement

Comment thread esphome/components/dsmr/__init__.py Outdated
Comment thread esphome/components/dsmr/__init__.p 8000 y Outdated
@codecov-commenter
codecov-commenter commented Oct 6, 2025
Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 73.43%. Comparing base (fc7e55b) to head (0317062).

Additional details and impacted files
@@            Coverage Diff             @@
##              dev   #11036      +/-   ##
==========================================
- Coverage   73.46%   73.43%   -0.03%     
==========================================
  Files          53       53              
  Lines       11310    11310              
  Branches     1535     1535              
==========================================
- Hits         8309     8306       -3     
- Misses       2602     2604       +2     
- Partials      399      400       +1     

☔ 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.

@zuidwijk
Copy link
8000 Copy Markdown

To use the changes from this PR as an external component, add the following to your ESPHome configuration YAML file:

external_components:
  - source: github://pr#11036
    components: [dsmr]
    refresh: 1h

(Added by the PR bot)

I'll try this weekend. Next week I'm in Oslo for work and week after in Belgium. I'll try as quickly as I can to test this.

@jeroen85
Copy link
Copy Markdown
Contributor

Great @PolarGoose ! Was waiting for someone to make these changes for a long time now 👍

I have it running now on version 2025.10.0 as an external component (on ESP-IDF framework).
Compiled without any issues and is currently running without any issues. Works as expected.

external_components:
  - source: github://pr#11036
    components: [dsmr]
    refresh: 1h

@zuidwijk
Copy link
Copy Markdown

Tried on 2025.9.3 and 2025.10.1 and both works!

Comment thread esphome/components/dsmr/__init__.py
Comment thread esphome/components/dsmr/__init__.py Outdated
@PolarGoose
Copy link
Copy Markdown
Contributor Author

@bdraco,
I have fixed your review comments. Could you please take a look again?

@jeroen85, @zuidwijk,
Thanks a lot for your testing.

@bdraco
bdraco commented Oct 21, 2025
Copy link
Copy Markdown
Member

You have modified clang-tidy configuration but have not updated the hash.

Please run script/clang_tidy_hash.py --update and commit the changes

@bdraco
bdraco commented Oct 21, 2025
Copy link
Copy Markdown
Member

clang-tidy is failing on zephyr


Error: /home/runner/work/esphome/esphome/esphome/components/dsmr/dsmr.h:8:10: error: 'arduino-dsmr-2/fields.h' file not found [clang-diagnostic-error]
    8 | #include <arduino-dsmr-2/fields.h>

@github-actions
github-actions Bot commented Oct 21, 2025
Copy link
Copy Markdown
Contributor

Memory Impact Analysis

Components: dsmr
Platform: esp8266-ard

Metric Target Branch This PR Change
RAM 29,540 bytes 30,672 bytes 📈 🚨 +1,132 bytes (+3.83%)
Flash 288,755 bytes 291,983 bytes 📈 🚨 +3,228 bytes (+1.12%)
📊 Component Memory Breakdown
Component Target Flash PR Flash Change
rom_functions 5,470 bytes 7,296 bytes 📈 +1,826 bytes (+33.38%)
cpp_stdlib 65 bytes 1,093 bytes 📈 +1,028 bytes (+1581.54%)
wifi_config 6,576 bytes 5,642 bytes 📉 -934 bytes (-14.20%)
cpp_runtime 650 bytes 1,093 bytes 📈 +443 bytes (+68.15%)
math_lib 1,899 bytes 2,201 bytes 📈 +302 bytes (+15.90%)
xtensa 451 bytes 612 bytes 📈 +161 bytes (+35.70%)
interrupt_handlers 1,218 bytes 1,346 bytes 📈 +128 bytes (+10.51%)
error_handling 132 bytes 221 bytes 📈 +89 bytes (+67.42%)
other 8,454 bytes 8,481 bytes 📈 +27 bytes (+0.32%)
[esphome]dsmr 2,978 bytes 2,971 bytes 📉 ✅ -7 bytes (-0.24%)
🔍 Symbol-Level Changes (click to expand)

Changed Symbols

Symbol Target Size PR Size Change
void std::__cxx11::basic_string<char, std::char_traits, std::allocator >::_M_construc...void std::__cxx11::basic_string<char, std::char_traits, std::allocator >::_M_construct<char const*>(char const*, char const*, std::forward_iterator_tag) [$isra$0]
108 bytes 92 bytes 📉 -16 bytes (-14.81%)
esphome::dsmr::Dsmr::set_decryption_key(std::__cxx11::basic_string<char, std::char_traits, ...esphome::dsmr::Dsmr::set_decryption_key(std::__cxx11::basic_string<char, std::char_traits, std::allocator > const&)
255 bytes 251 bytes 📉 -4 bytes (-1.57%)
esphome::dsmr::Dsmr::start_requesting_data_() 83 bytes 81 bytes 📉 -2 bytes (-2.41%)
esphome::dsmr::Dsmr::parse_telegram() 483 bytes 482 bytes 📉 -1 bytes (-0.21%)

New Symbols (top 15)

Symbol Size
std::__detail::__prime_list 1,028 bytes
dsmr_parser::ParsedData<dsmr_parser::fields::identification>::parse_line(dsmr_parser::ObisId cons...dsmr_parser::ParsedData<dsmr_parser::fields::identification>::parse_line(dsmr_parser::ObisId const&, char const*, char const*)
648 bytes
dsmr_parser::ParseResult dsmr_parser::P1Parser::parse<dsmr_parser::fields::identification>(...dsmr_parser::ParseResult dsmr_parser::P1Parser::parse<dsmr_parser::fields::identification>(dsmr_parser::ParsedData<dsmr_parser::fields::identification>&, char const*, unsigned int, bool, bool)
403 bytes
dsmr_parser::ParseResult dsmr_parser::P1Parser::parse_da 6D38 ta<dsmr_parser::fields::identificat...dsmr_parser::ParseResult dsmr_parser::P1Parser::parse_data<dsmr_parser::fields::identification>(dsmr_parser::ParsedData<dsmr_parser::fields::identification>&, char const*, char const*, bool)
330 bytes
floor 296 bytes
std::__detail::_Prime_rehash_policy::_M_need_rehash(unsigned int, unsigned int, unsigned int) const 234 bytes
dsmr_parser::ObisIdParser::parse(char const*, char const*) 221 bytes
dsmr_parser::ParseResult dsmr_parser::P1Parser::parse_line<dsmr_parser::ParsedData<dsmr_par...dsmr_parser::ParseResult dsmr_parser::P1Parser::parse_line<dsmr_parser::ParsedData<dsmr_parser::fields::identification> >(dsmr_parser::ParsedData<dsmr_parser::fields::identification>&, char const*, char const*, bool)
155 bytes
std::__detail::_Prime_rehash_policy::_M_next_bkt(unsigned int) const 147 bytes
std::__cxx11::basic_string<char, std::char_traits, std::allocator >::_M_mutate(unsign...std::__cxx11::basic_string<char, std::char_traits, std::allocator >::_M_mutate(unsigned int, unsigned int, char const*, unsigned int)
139 bytes
std::_Hashtable<dsmr_parser::ObisId, std::pair<dsmr_parser::ObisId const, dsmr_parser::ParseResul...std::_Hashtable<dsmr_parser::ObisId, std::pair<dsmr_parser::ObisId const, dsmr_parser::ParseResult ()(dsmr_parser::ParsedData<dsmr_parser::fields::identification>&, char const, char const*)>, std::allocator<std::pair<dsmr_parser::ObisId const, dsmr_parser::ParseResult ()(dsmr_parser::ParsedData<dsmr_parser::fields::identification>&, char const, char const*)> >, std::__detail::_Select1st, std::equal_to<dsmr_parser::ObisId>, dsmr_parser::ParsedData<dsmr_parser::fields::identification>::fields_map()::{lambda()#1}::operator()() const::{lambda(dsmr_parser::ObisId const&)#1} const, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_M_find_before_node(unsigned int, {lambda()#1}, unsigned int) const [$isra$0]
95 bytes
std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::push_back(char) 85 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) [$isra$0]
82 bytes
std::_Hashtable<dsmr_parser::ObisId, std::pair<dsmr_parser::ObisId const, dsmr_parser::ParseResul...std::_Hashtable<dsmr_parser::ObisId, std::pair<dsmr_parser::ObisId const, dsmr_parser::ParseResult ()(dsmr_parser::ParsedData<dsmr_parser::fields::identification>&, char const, char const*)>, std::allocator<std::pair<dsmr_parser::ObisId const, dsmr_parser::ParseResult ()(dsmr_parser::ParsedData<dsmr_parser::fields::identification>&, char const, char const*)> >, std::__detail::_Select1st, std::equal_to<dsmr_parser::ObisId>, dsmr_parser::ParsedData<dsmr_parser::fields::identification>::fields_map()::{lambda()#1}::operator()() const::{lambda(dsmr_parser::ObisId const&)#1} const, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::clear()
66 bytes
dsmr_parser::ParsedData<dsmr_parser::fields::identification>::fields_map()::{lambda()#1}::operato...dsmr_parser::ParsedData<dsmr_parser::fields::identification>::fields_map()::{lambda()#1}::operator()() const::{lambda(dsmr_parser::ParsedData<dsmr_parser::fields::identification>&, char const*, char const)#2}::_FUN({lambda()#1}, char const, char const)
63 bytes
10 more new symbols... Total: 4,206 bytes

Removed Symbols (top 15)

Symbol Size
dsmr::ParseResult dsmr::P1Parser::parsedsmr::fields::identification(dsmr::ParsedData<dsmr...dsmr::ParseResult dsmr::P1Parser::parsedsmr::fields::identification(dsmr::ParsedDatadsmr::fields::identification, char const, unsigned int, bool, bool)
352 bytes
dsmr::ParseResult dsmr::P1Parser::parse_datadsmr::fields::identification(dsmr::ParsedData...dsmr::ParseResult dsmr::P1Parser::parse_datadsmr::fields::identification(dsmr::ParsedDatadsmr::fields::identification, char const, char const*, bool)
283 bytes
dsmr::ObisIdParser::parse(char const*, char const*) 233 bytes
dsmr::ParseResult dsmr::P1Parser::parse_line<dsmr::ParsedDatadsmr::fields::identification...dsmr::ParseResult dsmr::P1Parser::parse_line<dsmr::ParsedDatadsmr::fields::identification >(dsmr::ParsedDatadsmr::fields::identification, char const, char const*, bool)
155 bytes
dsmr::ParsedDatadsmr::fields::identification::parse_line(dsmr::ObisId const&, char const*, char...dsmr::ParsedDatadsmr::fields::identification::parse_line(dsmr::ObisId const&, char const*, char const*)
145 bytes
dsmr::fields::identification::id 6 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.

@bdraco
bdraco commented Oct 21, 2025
Copy link
Copy Markdown
Member

So now we need a docs PR linked. Once the docs PR is linked, the bot will remove the needs-docs label.

Also be sure to update the Arduino to ESP-IDF guide as well in the docs as it currently mentions there is no dsmr option for IDF which can now be removed

@jesserockz
jesserockz commented Oct 21, 2025 9E88
Copy link
Copy Markdown
Member

@PolarGoose I have created a new home for the dmsr library in an org and glmnet kindly transferred his fork there. https://github.com/esphome-libs/arduino-dsmr

Can you make a PR to that repo with your changes, and once merged there I will give you access to write to that repo.

Jesse

@PolarGoose
Copy link
Copy Markdown
Contributor Author

@jesserockz,

I have made a pull request to esphome-libs.
Do you want the current pull request to use esphome-libs fork, or can we switch later and use my fork for now?

@ktomi96
ktomi96 commented Oct 25, 2025
Copy link
Copy Markdown

@PolarGoose Tested on 2025.10.2, it works for me.
I seen that arduino_dsmr_2 support more then 2 tariff. I have found esphome/components/dsmr/sensor.py needs to be changed to utilize more then 2 tarifs.

@rdehuyss
Copy link
Copy Markdown

Really looking forward to this - it's my last esphome board which depends on arduino.

Nice work, @PolarGoose 🙏!

@RogierSchuring
Copy link
Copy Markdown

Tested and works on an ESP8266 (esp12e) on ESPHOME 2025.11.0 with:

external_components:
  - source: github://pr#11036
    components: [dsmr]
    refresh: 1h

Fixes an issue that new DSRM meters do not always send unit.

@PolarGoose
Copy link
Copy Markdown
Contributor Author

@rdehuyss, @RogierSchuring,

Thank you for testing. Glad that this pull request is useful.

@bdraco, @swoboda1337,

  • Are you waiting for a specific roadmap date to merge these changes, or did you just not have time to process this pull request?
  • Do you want me to add my name to the CODEOWNERS in dsmr/__init__.py?

@bdraco
bdraco commented Nov 24, 2025
Copy link
Copy Markdown
Member
  • Are you waiting for a specific roadmap date to merge these changes, or did you just not have time to process this pull request?

Just waiting on time to review. I have 400+ in my backlog right now

  • Do you want me to add my name to the CODEOWNERS in dsmr/__init__.py?

Yes please

@bdraco
bdraco commented Nov 24, 2025
Copy link
Copy Markdown
Member

To clear the needs-tests label, add a test in tests/components/dsmr/ for idf

@esphome esphome Bot added has-tests and removed needs-tests labels Nov 24, 2025

# Crypto
cg.add_library("rweather/Crypto", "0.4.0")
cg.add_library("polargoose/Crypto-no-arduino", "0.4.0")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

jesserockz: Do you think we need to move this to esphome libs before merging?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think so

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

In my opinion, it is easier to remove the dependency on this library in the following pull request.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

By the way, @jesserockz previously said here:

Another PR is fine for this work.

@PolarGoose
Copy link
Copy Markdown
Contributor Author

@swoboda1337, @bdraco,

The Build target branch for memory impact CI job fails. Have you seen similar issues before? I don't see from the log why it fails.

@swoboda1337
Copy link
Copy Markdown
Member

Not sure

@bdraco
bdraco commented Dec 7, 2025
Copy link
Copy Markdown
Member

Try resolving the conflicts and see if it solves it

@PolarGoose
Copy link
Copy Markdown
Contributor Author

@bdraco, @swoboda1337,

The issue is still present. I think it is related to the file tests/components/dsmr/test.esp32-idf.yaml that I have added. I don't see anything wrong with it. However, it triggers the Build target branch for memory impact CI job.

@bdraco
bdraco commented Dec 8, 2025
Copy link
Copy Markdown
Member

The impact analysis should be running
./script/test_build_components -c dsmr -e compile -t esp32-idf for this PR

@PolarGoose
Copy link
Copy Markdown
Contributor Author

@bdraco,

The impact analysis should be running ./script/test_build_components -c dsmr -e compile -t esp32-idf for this PR

This command works if I run it locally. However, the CI job fails :)

@bdraco
bdraco commented Dec 9, 2025
Copy link
Copy Markdown
Member

I'll see if I can figure out why. Also would you please have a look at the conflicts again (sorry we merged some platformio fixes)

@bdraco
bdraco commented Dec 9, 2025
Copy link
Copy Markdown
Member

So the reason its failing is its trying to build dev (target branch) with esp-idf and failing. We will have to override the CI and merge without the memory impact analysis. This is fine though.

@bdraco
bdraco commented Dec 9, 2025
Copy link
Copy Markdown
Member

I'm testing a solution to allow merges without the need to force when target branch can't build #12381

@PolarGoose
Copy link
Copy Markdown
Contributor Author

@bdraco,

Thanks, now it works.
If you need me to make any other changes, please let me know. Otherwise, I leave the rest to you and your friends :)

@bdraco bdraco left a comment
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks @PolarGoose

@bdraco
bdraco enabled auto-merge (squash) January 5, 2026 23:29
@bdraco
bdraco disabled auto-merge January 5, 2026 23:33
@bdraco
bdraco enabled auto-merge (squash) January 5, 2026 23:35
@bdraco
bdraco merged commit 7ed4922 into esphome:dev Jan 6, 2026
31 of 32 checks passed
@esphome esphome Bot added the by-code-owner label Jan 6, 2026
@rdehuyss
rdehuyss commented Jan 6, 2026
Copy link
Copy Markdown

🎉 🎉 🎉 🎉

Thanks for the hard work @PolarGoose, @bdraco and the rest of the @esphomebot team!

@github-actions github-actions Bot locked and limited conversation to collaborators Jan 7, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet
0