Got an Update to v153. It broke down :). Here´s the new config.
It even gives better values.
sml:
id: mysml
uart_id: uart_bus
sensor:
- platform: sml
name: "Meter Reading"
sml_id: mysml
obis_code: "1-0:1.8.0"
unit_of_measurement: kWh
accuracy_decimals: 4
device_class: energy
state_class: total_increasing
filters:
- multiply: 0.0000001
- platform: total_daily_energy
name: "Daily Export"
power_id: export_power
filters:
- multiply: 0.001
unit_of_measurement: kWh
- platform: sml
name: "Total Power Consumption"
id: verbrauch
sml_id: mysml
obis_code: "1-0:16.7.0"
unit_of_measurement: W
accuracy_decimals: 2
filters:
- multiply: 0.01
on_value:
- sensor.template.publish:
id: export_power
state: !lambda |-
if ((id(verbrauch).state) >= 0) {
return 0;
} else {
return (id(verbrauch).state /-1.0);
}
- platform: sml
name: "Power Consumption L1"
sml_id: mysml
id: l1
obis_code: "1-0:36.7.0"
unit_of_measurement: W
accuracy_decimals: 2
filters:
- multiply: 0.01
- platform: sml
name: "Power Consumption L2"
sml_id: mysml
id: l2
obis_code: "1-0:56.7.0"
unit_of_measurement: W
accuracy_decimals: 2
filters:
- multiply: 0.01
- platform: sml
name: "Power Consumption L3"
sml_id: mysml
id: l3
obis_code: "1-0:76.7.0"
unit_of_measurement: W
accuracy_decimals: 2
filters:
- multiply: 0.01
- platform: sml
name: "Voltage L1"
sml_id: mysml
id: u1
obis_code: "1-0:32.7.0"
unit_of_measurement: V
accuracy_decimals: 2
filters:
- multiply: 0.1
- platform: sml
name: "Voltage L2"
sml_id: mysml
id: u2
obis_code: "1-0:52.7.0"
unit_of_measurement: V
accuracy_decimals: 2
filters:
- multiply: 0.1
- platform: sml
name: "Voltage L3"
sml_id: mysml
id: u3
obis_code: "1-0:72.7.0"
unit_of_measurement: V
accuracy_decimals: 2
filters:
- multiply: 0.1
- platform: template
name: "Current L1"
id: i1
unit_of_measurement: "A"
accuracy_decimals: 2
update_interval: 1s
lambda: |-
if (id(u1).has_state() && id(l1).has_state() && id(u1).state > 0) {
return fabs(id(l1).state / id(u1).state);
} else {
return 0.0;
}
- platform: template
name: "Current L2"
id: i2
unit_of_measurement: "A"
accuracy_decimals: 2
update_interval: 1s
lambda: |-
if (id(u2).has_state() && id(l2).has_state() && id(u2).state > 0) {
return fabs(id(l2).state / id(u2).state);
} else {
return 0.0;
}
- platform: template
name: "Current L3"
id: i3
unit_of_measurement: "A"
accuracy_decimals: 2
update_interval: 1s
lambda: |-
if (id(u3).has_state() && id(l3).has_state() && id(u3).state > 0) {
return fabs(id(l3).state / id(u3).state);
} else {
return 0.0;
}
- platform: template
name: "Total Current"
id: i_total
unit_of_measurement: "A"
accuracy_decimals: 2
update_interval: 1s
lambda: |-
return id(i1).state + id(i2).state + id(i3).state;
- platform: template
name: "Power Factor L1"
id: pf1
accuracy_decimals: 2
update_interval: 1s
lambda: |-
if (!id(l1).has_state()) return 0.95; // Fallback
// Power absolute value for calculation
float power_abs = fabs(id(l1).state);
// Export (negative power)
if (id(l1).state < 0) {
// Inverters typically have better PF (0.95-0.99)
return 0.95 + (std::rand() % 4) * 0.01;
}
// Import (positive power)
else {
if (power_abs < 20.0) {
// Low load: worse PF (0.85-0.90)
return 0.85 + (std::rand() % 5) * 0.01;
} else if (power_abs < 100.0) {
// Medium load: medium PF (0.90-0.94)
return 0.90 + (std::rand() % 4) * 0.01;
} else {
// High load: better PF (0.94-0.98)
return 0.94 + (std::rand() % 4) * 0.01;
}
}
- platform: template
name: "Power Factor L2"
id: pf2
accuracy_decimals: 2
update_interval: 1s
lambda: |-
if (!id(l2).has_state()) return 0.95; // Fallback
// Power absolute value for calculation
float power_abs = fabs(id(l2).state);
// Export (negative power)
if (id(l2).state < 0) {
// Inverters typically have better PF (0.95-0.99)
return 0.95 + (std::rand() % 4) * 0.01;
}
// Import (positive power)
else {
if (power_abs < 20.0) {
// Low load: worse PF (0.85-0.90)
return 0.85 + (std::rand() % 5) * 0.01;
} else if (power_abs < 100.0) {
// Medium load: medium PF (0.90-0.94)
return 0.90 + (std::rand() % 4) * 0.01;
} else {
// High load: better PF (0.94-0.98)
return 0.94 + (std::rand() % 4) * 0.01;
}
}
- platform: template
name: "Power Factor L3"
id: pf3
accuracy_decimals: 2
update_interval: 1s
lambda: |-
if (!id(l3).has_state()) return 0.95; // Fallback
// Power absolute value for calculation
float power_abs = fabs(id(l3).state);
// Export (negative power)
if (id(l3).state < 0) {
// Inverters typically have better PF (0.95-0.99)
return 0.95 + (std::rand() % 4) * 0.01;
}
// Import (positive power)
else {
if (power_abs < 20.0) {
// Low load: worse PF (0.85-0.90)
return 0.85 + (std::rand() % 5) * 0.01;
} else if (power_abs < 100.0) {
// Medium load: medium PF (0.90-0.94)
return 0.90 + (std::rand() % 4) * 0.01;
} else {
// High load: better PF (0.94-0.98)
return 0.94 + (std::rand() % 4) * 0.01;
}
}
# Apparent power for phase L1
- platform: template
name: "Apparent Power L1"
id: apparent_power_l1
unit_of_measurement: "VA"
accuracy_decimals: 2
update_interval: 1s
lambda: |-
if (id(l1).has_state() && id(pf1).has_state() && id(pf1).state > 0) {
return fabs(id(l1).state) / id(pf1).state;
} else {
return 0.0;
}
# Apparent power for phase L2
- platform: template
name: "Apparent Power L2"
id: apparent_power_l2
unit_of_measurement: "VA"
accuracy_decimals: 2
update_interval: 1s
lambda: |-
if (id(l2).has_state() && id(pf2).has_state() && id(pf2).state > 0) {
return fabs(id(l2).state) / id(pf2).state;
} else {
return 0.0;
}
# Apparent power for phase L3
- platform: template
name: "Apparent Power L3"
id: apparent_power_l3
unit_of_measurement: "VA"
accuracy_decimals: 2
update_interval: 1s
lambda: |-
if (id(l3).has_state() && id(pf3).has_state() && id(pf3).state > 0) {
return fabs(id(l3).state) / id(pf3).state;
} else {
return 0.0;
}
# Total apparent power
- platform: template
name: "Total Apparent Power"
id: apparent_power_total
unit_of_measurement: "VA"
accuracy_decimals: 2
update_interval: 1s
lambda: |-
return id(apparent_power_l1).state + id(apparent_power_l2).state + id(apparent_power_l3).state;
- platform: template
name: "Grid Frequency"
id: freq
unit_of_measurement: "Hz"
accuracy_decimals: 1
update_interval: 10s
lambda: |-
static float last_freq = 50.0;
// Simulate realistic, slightly fluctuating grid frequency
// The frequency changes only slowly, never abruptly
float new_freq = last_freq + ((float)(rand() % 5 - 2) / 20.0); // -0.1 to +0.1 Hz change
// Limit to realistic range
if (new_freq < 49.8) new_freq = 49.8;
if (new_freq > 50.2) new_freq = 50.2;
last_freq = new_freq;
return new_freq;
udp:
- id: udp_sender
port:
listen_port: 18511
broadcast_port: 18512
addresses:
- 192.168.0.54
# 1) Sender: unicast to Venus battery 192.168.0.55:22222
- id: udp_shelly_sender
port:
listen_port: 18001 # any local sending port
broadcast_port: 22222 # target port of the battery
addresses:
- 192.168.0.55 # fixed IP of the battery
# 2) Server: listens on port 1010 for EM.GetStatus
- id: udp_server
port:
listen_port: 1010
broadcast_port: 1010
on_receive:
then:
- lambda: |-
std::string msg(data.begin(), data.end());
if (msg.find("\"method\":\"EM.GetStatus\"") == std::string::npos) return;
- udp.write:
id: udp_shelly_sender
data: !lambda |-
char buf[1024];
int len = snprintf(buf, sizeof(buf),
"{"
"\"id\":0,"
"\"src\":\"shellypro3em-e682e89c1724\","
"\"result\":{"
"\"id\":0,"
"\"a_current\":%.2f,\"a_voltage\":%.1f,\"a_act_power\":%.2f,"
"\"a_aprt_power\":%.2f,\"a_pf\":%.2f,\"a_freq\":%.1f,"
"\"b_current\":%.2f,\"b_voltage\":%.1f,\"b_act_power\":%.2f,"
"\"b_aprt_power\":%.2f,\"b_pf\":%.2f,\"b_freq\":%.1f,"
"\"c_current\":%.2f,\"c_voltage\":%.1f,\"c_act_power\":%.2f,"
"\"c_aprt_power\":%.2f,\"c_pf\":%.2f,\"c_freq\":%.1f,"
"\"total_current\":%.2f,"
"\"total_act_power\":%.2f,"
"\"total_aprt_power\":%.2f"
"}"
"}",
id(i1).state, id(u1).state, id(l1).state,
id(apparent_power_l1).state, id(pf1).state, id(freq).state,
id(i2).state, id(u2).state, id(l2).state,
id(apparent_power_l2).state, id(pf2).state, id(freq).state,
id(i3).state, id(u3).state, id(l3).state,
id(apparent_power_l3).state, id(pf3).state, id(freq).state,
id(i_total).state,
id(verbrauch).state,
id(apparent_power_total).state
);
return std::vector<uint8_t>(buf, buf + len);