Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions content/components/sml.md
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,47 @@ sensor:
state_class: measurement
```

## Reading multiple meters

If you are reading data from more meters than your controller has UARTs available (e.g. more than two for an ESP32), you can use multiplexing to switch between reading data from different meters.

In order to do this, after each SML update, the used UART can be set to listen to a different pin.
An example on how to do this is this:

```yaml
uart:
- baud_rate: 9600
data_bits: 8
rx_pin:
number: GPIO17 # Set to the first of the GPIO pins in multiplex_pins
id: uart_multiplex_rx_pin
stop_bits: 1
rx_buffer_size: 512
id: uart_multiplexed
sml:
- id: sml_multiplexed
uart_id: uart_multiplexed
on_data:
- lambda: |-
std::vector<gpio_num_t> multiplex_pins = {::GPIO_NUM_17,::GPIO_NUM_19};
Comment on lines +236 to +237
Copy link

Copilot AI Sep 8, 2025

Choose a reason for hiding this comment

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

The lambda code uses ESP-IDF specific gpio_num_t and GPIO_NUM_* constants without explaining this is ESP-specific. Consider adding a note that this example is for ESP32/ESP8266 platforms or provide a more platform-agnostic example.

Copilot uses AI. Check for mistakes.
static size_t current_index = 0;
current_index = (current_index + 1) % multiplex_pins.size();
gpio_num_t new_rx_pin = multiplex_pins[current_index];
id(uart_multiplex_rx_pin).set_pin(new_rx_pin);
Copy link

Copilot AI Sep 8, 2025

Choose a reason for hiding this comment

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

The load_settings(true) call and its parameter are not explained. Consider adding a comment explaining what this does and why the true parameter is necessary for the multiplexing to work properly.

Suggested change
id(uart_multiplex_rx_pin).set_pin(new_rx_pin);
id(uart_multiplex_rx_pin).set_pin(new_rx_pin);
// Reload the UART settings after changing the RX pin.
// The 'true' parameter forces the reload, which is necessary for multiplexing to work properly.

Copilot uses AI. Check for mistakes.
id(uart_multiplexed).load_settings(true);
sensor:
- platform: sml
name: "Solar Roof"
sml_id: sml_multiplexed
server_id: "12345ab" # IMPORTANT! Set the correct server id
obis_code: "1-0:2.8.0"
- platform: sml
name: "Solar Carport"
sml_id: sml_multiplexed
server_id: "67890cd" # IMPORTANT! Set the correct server id
obis_code: "1-0:2.8.0"
```
Comment on lines +222 to +254
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.

⚠️ Potential issue

Fix YAML indentation (invalid as written) and guard pin switch on valid frames.

  • The list items under uart:, sml:, and sensor: must be indented.
  • Only rotate RX after a valid SML frame to reduce missed reads.
  • Use realistic server_id examples (consistent length/format with earlier docs).
  • Consider adding a short note that the gpio_num_t example is ESP32/ESP-IDF–specific.
 ```yaml
-uart:
-- baud_rate: 9600
-  data_bits: 8
-  rx_pin:
-    number: GPIO17 # Set to the first of the GPIO pins in multiplex_pins
-    id: uart_multiplex_rx_pin
-  stop_bits: 1
-  rx_buffer_size: 512
-  id: uart_multiplexed
+uart:
+  - baud_rate: 9600
+    data_bits: 8
+    rx_pin:
+      number: GPIO17  # Set to the first of the GPIO pins in multiplex_pins
+      id: uart_multiplex_rx_pin
+    stop_bits: 1
+    rx_buffer_size: 512
+    id: uart_multiplexed
 sml:
-- id: sml_multiplexed
-  uart_id: uart_multiplexed
-  on_data:
-    - lambda: |-
-        std::vector<gpio_num_t> multiplex_pins = {::GPIO_NUM_17,::GPIO_NUM_19};
-        static size_t current_index = 0;
-        current_index = (current_index + 1) % multiplex_pins.size();
-        gpio_num_t new_rx_pin = multiplex_pins[current_index];
-        id(uart_multiplex_rx_pin).set_pin(new_rx_pin);
-        id(uart_multiplexed).load_settings(true);
+  - id: sml_multiplexed
+    uart_id: uart_multiplexed
+    on_data:
+      - lambda: |-
+          // NOTE: ESP32-only example using ESP-IDF types (gpio_num_t).
+          std::vector<gpio_num_t> multiplex_pins = {::GPIO_NUM_17, ::GPIO_NUM_19};
+          if (valid) {
+            static size_t current_index = 0;
+            current_index = (current_index + 1) % multiplex_pins.size();
+            gpio_num_t new_rx_pin = multiplex_pins[current_index];
+            id(uart_multiplex_rx_pin).set_pin(new_rx_pin);
+            id(uart_multiplexed).load_settings(true);
+          }
 sensor:
-- platform: sml
-  name: "Solar Roof"
-  sml_id: sml_multiplexed
-  server_id: "12345ab" # IMPORTANT! Set the correct server id
-  obis_code: "1-0:2.8.0"
-- platform: sml
-  name: "Solar Carport"
-  sml_id: sml_multiplexed
-  server_id: "67890cd" # IMPORTANT! Set the correct server id
-  obis_code: "1-0:2.8.0"
+  - platform: sml
+    name: "Solar Roof"
+    sml_id: sml_multiplexed
+    server_id: "0123456789abcdef"  # Set your meter's server_id
+    obis_code: "1-0:2.8.0"
+  - platform: sml
+    name: "Solar Carport"
+    sml_id: sml_multiplexed
+    server_id: "fedcba9876543210"  # Set your meter's server_id
+    obis_code: "1-0:2.8.0"
🤖 Prompt for AI Agents
In content/components/sml.md around lines 222–254, fix the invalid YAML and
unsafe pin rotation: indent the list items under uart:, sml:, and sensor: so
each block is a proper list element (e.g., "- baud_rate..." under uart:), change
the on_data lambda to only rotate the RX pin after a validated SML frame (wrap
the current_index increment, set_pin and load_settings calls in an if(valid)
guard or equivalent), replace the example server_id values with realistic-length
hex strings consistent with the docs, and add a brief inline note that
gpio_num_t/::GPIO_NUM_* usage is ESP32/ESP-IDF specific.


## See Also

- {{< apiref "sml/sml.h" "sml/sml.h" >}}