Created
May 30, 2025 07:12
-
-
Save KrzysztofHajdamowicz/f5cdde881a96a7dfcd71a29dec8bb500 to your computer and use it in GitHub Desktop.
Home-Assistant, Eastron SDM72, SDM630 modbus config generator
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# Edit line 324 to adjust list od modbus addresses used in your setup! | |
import yaml | |
import re | |
# Template data as a string | |
template_yaml = """ | |
- name: Meter_METERID_CHANGEME_volts_L1/N | |
slave: METERID_CHANGEME | |
address: 0 | |
input_type: input | |
precision: 2 | |
data_type: float32 | |
unit_of_measurement: V | |
device_class: voltage | |
state_class: measurement | |
unique_id: UUID_CHANGEME | |
- name: Meter_METERID_CHANGEME_volts_L2/N | |
slave: METERID_CHANGEME | |
address: 2 | |
input_type: input | |
precision: 2 | |
data_type: float32 | |
unit_of_measurement: V | |
device_class: voltage | |
state_class: measurement | |
unique_id: UUID_CHANGEME | |
- name: Meter_METERID_CHANGEME_volts_L3/N | |
slave: METERID_CHANGEME | |
address: 4 | |
input_type: input | |
precision: 2 | |
data_type: float32 | |
unit_of_measurement: V | |
device_class: voltage | |
state_class: measurement | |
unique_id: UUID_CHANGEME | |
- name: Meter_METERID_CHANGEME_volts_average | |
slave: METERID_CHANGEME | |
address: 42 | |
input_type: input | |
precision: 2 | |
data_type: float32 | |
unit_of_measurement: V | |
device_class: voltage | |
state_class: measurement | |
unique_id: UUID_CHANGEME | |
- name: Meter_METERID_CHANGEME_L1_current | |
address: 6 | |
input_type: input | |
slave: METERID_CHANGEME | |
precision: 3 | |
data_type: float32 | |
unit_of_measurement: A | |
device_class: current | |
state_class: measurement | |
unique_id: UUID_CHANGEME | |
- name: Meter_METERID_CHANGEME_L2_current | |
address: 8 | |
input_type: input | |
slave: METERID_CHANGEME | |
precision: 3 | |
data_type: float32 | |
unit_of_measurement: A | |
device_class: current | |
state_class: measurement | |
unique_id: UUID_CHANGEME | |
- name: Meter_METERID_CHANGEME_L3_current | |
address: 10 | |
input_type: input | |
slave: METERID_CHANGEME | |
precision: 3 | |
data_type: float32 | |
unit_of_measurement: A | |
device_class: current | |
state_class: measurement | |
unique_id: UUID_CHANGEME | |
- name: Meter_METERID_CHANGEME_L1_power | |
address: 12 | |
input_type: input | |
slave: METERID_CHANGEME | |
precision: 3 | |
scale: 1 | |
data_type: float32 | |
unit_of_measurement: W | |
device_class: power | |
state_class: measurement | |
unique_id: UUID_CHANGEME | |
- name: Meter_METERID_CHANGEME_L2_power | |
address: 14 | |
input_type: input | |
slave: METERID_CHANGEME | |
precision: 3 | |
data_type: float32 | |
unit_of_measurement: W | |
device_class: power | |
state_class: measurement | |
unique_id: UUID_CHANGEME | |
- name: Meter_METERID_CHANGEME_L3_power | |
address: 16 | |
input_type: input | |
slave: METERID_CHANGEME | |
precision: 3 | |
data_type: float32 | |
unit_of_measurement: W | |
device_class: power | |
state_class: measurement | |
unique_id: UUID_CHANGEME | |
- name: Meter_METERID_CHANGEME_L1_power_apparent | |
address: 18 | |
input_type: input | |
slave: METERID_CHANGEME | |
precision: 2 | |
data_type: float32 | |
unit_of_measurement: VA | |
device_class: apparent_power | |
state_class: measurement | |
unique_id: UUID_CHANGEME | |
- name: Meter_METERID_CHANGEME_L2_power_apparent | |
address: 20 | |
input_type: input | |
slave: METERID_CHANGEME | |
precision: 2 | |
data_type: float32 | |
unit_of_measurement: VA | |
device_class: apparent_power | |
state_class: measurement | |
unique_id: UUID_CHANGEME | |
- name: Meter_METERID_CHANGEME_L3_power_apparent | |
address: 22 | |
input_type: input | |
slave: METERID_CHANGEME | |
precision: 2 | |
data_type: float32 | |
unit_of_measurement: VA | |
device_class: apparent_power | |
state_class: measurement | |
unique_id: UUID_CHANGEME | |
- name: Meter_METERID_CHANGEME_L1_power_reactive | |
address: 24 | |
input_type: input | |
slave: METERID_CHANGEME | |
precision: 2 | |
data_type: float32 | |
unit_of_measurement: var | |
device_class: reactive_power | |
state_class: measurement | |
unique_id: UUID_CHANGEME | |
- name: Meter_METERID_CHANGEME_L2_power_reactive | |
address: 26 | |
input_type: input | |
slave: METERID_CHANGEME | |
precision: 2 | |
data_type: float32 | |
unit_of_measurement: var | |
device_class: reactive_power | |
state_class: measurement | |
unique_id: UUID_CHANGEME | |
- name: Meter_METERID_CHANGEME_L3_power_reactive | |
address: 28 | |
input_type: input | |
slave: METERID_CHANGEME | |
precision: 2 | |
data_type: float32 | |
unit_of_measurement: var | |
device_class: reactive_power | |
state_class: measurement | |
unique_id: UUID_CHANGEME | |
- name: Meter_METERID_CHANGEME_L1_power_factor | |
address: 30 | |
input_type: input | |
slave: METERID_CHANGEME | |
precision: 2 | |
data_type: float32 | |
device_class: power_factor | |
state_class: measurement | |
unique_id: UUID_CHANGEME | |
- name: Meter_METERID_CHANGEME_L2_power_factor | |
address: 32 | |
input_type: input | |
slave: METERID_CHANGEME | |
precision: 2 | |
data_type: float32 | |
device_class: power_factor | |
state_class: measurement | |
unique_id: UUID_CHANGEME | |
- name: Meter_METERID_CHANGEME_L3_power_factor | |
address: 34 | |
input_type: input | |
slave: METERID_CHANGEME | |
precision: 2 | |
data_type: float32 | |
device_class: power_factor | |
state_class: measurement | |
unique_id: UUID_CHANGEME | |
- name: Meter_METERID_CHANGEME_total_current | |
address: 48 | |
input_type: input | |
slave: METERID_CHANGEME | |
precision: 3 | |
data_type: float32 | |
unit_of_measurement: A | |
device_class: current | |
unique_id: UUID_CHANGEME | |
- name: Meter_METERID_CHANGEME_total_power | |
address: 52 | |
input_type: input | |
slave: METERID_CHANGEME | |
precision: 2 | |
data_type: float32 | |
unit_of_measurement: W | |
device_class: power | |
state_class: measurement | |
unique_id: UUID_CHANGEME | |
- name: Meter_METERID_CHANGEME_total_power_apparent | |
address: 56 | |
input_type: input | |
slave: METERID_CHANGEME | |
precision: 2 | |
data_type: float32 | |
unit_of_measurement: VA | |
device_class: apparent_power | |
state_class: measurement | |
unique_id: UUID_CHANGEME | |
- name: Meter_METERID_CHANGEME_total_power_reactive | |
address: 60 | |
input_type: input | |
slave: METERID_CHANGEME | |
precision: 2 | |
data_type: float32 | |
unit_of_measurement: var | |
device_class: reactive_power | |
state_class: measurement | |
unique_id: UUID_CHANGEME | |
- name: Meter_METERID_CHANGEME_frequency | |
address: 70 | |
input_type: input | |
slave: METERID_CHANGEME | |
precision: 2 | |
data_type: float32 | |
unit_of_measurement: Hz | |
state_class: measurement | |
device_class: frequency | |
unique_id: UUID_CHANGEME | |
- name: Meter_METERID_CHANGEME_import_active | |
address: 72 | |
input_type: input | |
slave: METERID_CHANGEME | |
precision: 2 | |
data_type: float32 | |
unit_of_measurement: kWh | |
device_class: energy | |
state_class: total_increasing | |
unique_id: UUID_CHANGEME | |
- name: Meter_METERID_CHANGEME_export_active | |
address: 74 | |
input_type: input | |
slave: METERID_CHANGEME | |
precision: 2 | |
data_type: float32 | |
unit_of_measurement: kWh | |
device_class: energy | |
state_class: total_increasing | |
unique_id: UUID_CHANGEME | |
- name: Meter_METERID_CHANGEME_import_reactive | |
address: 78 | |
input_type: input | |
slave: METERID_CHANGEME | |
precision: 2 | |
data_type: float32 | |
unit_of_measurement: kVArh | |
device_class: energy | |
state_class: total_increasing | |
unique_id: UUID_CHANGEME | |
- name: Meter_METERID_CHANGEME_export_reactive | |
address: 80 | |
input_type: input | |
slave: METERID_CHANGEME | |
precision: 2 | |
data_type: float32 | |
unit_of_measurement: kVArh | |
device_class: energy | |
state_class: total_increasing | |
unique_id: UUID_CHANGEME | |
""" | |
def generate_meter_config(meter_id): | |
"""Generate configuration for a specific meter ID""" | |
# Load the template | |
template_data = yaml.safe_load(template_yaml) | |
# Process each sensor in the template | |
for sensor in template_data: | |
# Replace METERID_CHANGEME with actual meter ID | |
sensor['name'] = sensor['name'].replace('METERID_CHANGEME', str(meter_id)) | |
# Update slave ID to match meter ID | |
sensor['slave'] = meter_id | |
# Generate unique_id based on meter ID and address | |
address = sensor['address'] | |
sensor['unique_id'] = f"modbus_{meter_id}_address_{address}" | |
return template_data | |
def generate_all_meters(): | |
"""Generate configurations for all meters (1-8 and 200)""" | |
all_configs = {} | |
# Generate for meters 1-8 and 200 | |
meter_ids = list(range(1, 9)) + [200] | |
for meter_id in meter_ids: | |
config = generate_meter_config(meter_id) | |
all_configs[f'meter_{meter_id}'] = config | |
return all_configs | |
def generate_flat_config(): | |
"""Generate a flat list of all sensors for all meters""" | |
flat_config = [] | |
# Generate for meters 1-8 and 200 | |
meter_ids = list(range(1, 9)) + [200] | |
for meter_id in meter_ids: | |
config = generate_meter_config(meter_id) | |
flat_config.extend(config) | |
return flat_config | |
def save_configs(configs, combined=False): | |
"""Save configurations to YAML files""" | |
if combined: | |
# Generate flat configuration for Home Assistant | |
flat_config = generate_flat_config() | |
with open('all_meters_config.yaml', 'w') as f: | |
yaml.dump(flat_config, f, default_flow_style=False, sort_keys=False) | |
print("Generated combined configuration: all_meters_config.yaml") | |
else: | |
# Save each meter in a separate file | |
for meter_name, config in configs.items(): | |
filename = f'{meter_name}_config.yaml' | |
with open(filename, 'w') as f: | |
yaml.dump(config, f, default_flow_style=False, sort_keys=False) | |
print(f"Generated configuration: {filename}") | |
def main(): | |
# Generate configurations for all meters | |
all_configs = generate_all_meters() | |
# Save as separate files | |
save_configs(all_configs, combined=False) | |
# Save as a combined flat file for Home Assistant | |
save_configs(all_configs, combined=True) | |
# Print a sample to verify | |
print("\nSample from combined configuration:") | |
flat_sample = generate_flat_config()[:4] # First 4 sensors | |
print(yaml.dump(flat_sample, default_flow_style=False)) | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment