esphome:
name: esp32-sofar
comment: SofarSolar Logger (Modbus/RS485)
esp32:
board: esp32dev
substitutions:
devicename: sofarsolar-logger
friendly_name: SofarSolar
hostname: esp32-${inverter_short_name}
comment: ${friendly_name} Modbus Interface
friendly_node_name: ESP-Sofar
inverter_short_name: sofar
upper_inverter_short_name: Sofar
esp_id: esp_${inverter_short_name}
external_components:
- source:
type: git
url: https://github.com/zdzichu6969/esphome-components
components: [ heapmon ]
refresh: 12h
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
reboot_timeout: 300s
power_save_mode: none
ap:
ssid: Fallback-AP-${hostname}
password: ""
ap_timeout: 300s
api:
encryption:
key: !secret api_encryption_key
reboot_timeout: 0s
ota:
password: !secret ota_password
safe_mode: True
mdns:
captive_portal:
logger:
level: INFO
baud_rate: 0
uart:
id: mod_bus
tx_pin: GPIO17
rx_pin: GPIO16
baud_rate: 9600
stop_bits: 1
rx_buffer_size: 512
modbus:
id: mod_bus_sofar
send_wait_time: 500ms
modbus_controller:
- id: sofarsolar
address: 0x01
modbus_id: mod_bus_sofar
update_interval: 5s
setup_priority: -10
command_throttle: 750ms
text_sensor:
- platform: template
name: ${friendly_node_name} Uptime (human readable)
id: uptime_human
icon: "mdi:clock-start"
update_interval: 5s
entity_category: diagnostic
- platform: version
name: ${friendly_node_name} ESPHome Version
id: ${friendly_name}_esphome_version
- platform: wifi_info
ip_address:
name: ${friendly_node_name} IP Address
id: ${friendly_name}_ip_address
icon: mdi:ip-network
- platform: modbus_controller
modbus_controller_id: sofarsolar
name: ${friendly_name} Status
id: ${esp_id}_status
register_type: holding
icon: "mdi:information-outline"
address: 0x0000
response_size: 2
lambda: |-
auto z = "Unknown";
char d = data[item->offset+1];
if (d == 0) z = "Wait";
else if (d == 1) z = "Check";
else if (d == 2) z = "Normal";
else if (d == 3) z = "Fault";
else if (d == 4) z = "Permanent";
return {z};
- platform: modbus_controller
modbus_controller_id: sofarsolar
name: ${friendly_name} Fault Message
id: inverter_fault_message
register_type: holding
icon: "mdi:alert-outline"
address: 0x0001
response_size: 10
lambda: |-
std::string z = "";
int idx = item->offset;
//byte[0]
if ((data[idx] & 0x1) != 0) z += "GridOVP,";
if ((data[idx] & 0x2) != 0) z += "GridUVP,";
if ((data[idx] & 0x4) != 0) z += "GridOFP,";
if ((data[idx] & 0x8) != 0) z += "GridUFP,";
if ((data[idx] & 0x10) != 0) z += "PVUVP,";
if ((data[idx] & 0x20) != 0) z += "GridLVRT,";
if ((data[idx] & 0x40) != 0) z += "reserve-ID7,";
if ((data[idx] & 0x80) != 0) z += "reserve-ID8,";
//byte[1]
idx++;
if ((data[idx] & 0x1) != 0) z += "PVOVP,";
if ((data[idx] & 0x2) != 0) z += "IpvUnbalance,";
if ((data[idx] & 0x4) != 0) z += "PvConfigSetWrong,";
if ((data[idx] & 0x8) != 0) z += "GFCIFault,";
if ((data[idx] & 0x10) != 0) z += "PhaseSequenceFault,";
if ((data[idx] & 0x20) != 0) z += "HwBoostOCP,";
if ((data[idx] & 0x40) != 0) z += "HwAcOCP,";
if ((data[idx] & 0x80) != 0) z += "AcRmsOCP,";
//byte[2]
idx++;
if ((data[idx] & 0x1) != 0) z += "HwADFaultIGrid,";
if ((data[idx] & 0x2) != 0) z += "HwADFaultDCI,";
if ((data[idx] & 0x4) != 0) z += "HwADFaultVGrid,";
if ((data[idx] & 0x8) != 0) z += "GFCIDeviceFault,";
if ((data[idx] & 0x10) != 0) z += "MChip_Fault,";
if ((data[idx] & 0x20) != 0) z += "HwAuxPowerFault,";
if ((data[idx] & 0x40) != 0) z += "BusVoltZeroFault,";
if ((data[idx] & 0x80) != 0) z += "IacRmsUnbalance,";
//byte[3]
idx++;
if ((data[idx] & 0x1) != 0) z += "BusUVP,";
if ((data[idx] & 0x2) != 0) z += "BusOVP,";
if ((data[idx] & 0x4) != 0) z += "VbusUnbalance,";
if ((data[idx] & 0x8) != 0) z += "DciOCP,";
if ((data[idx] & 0x10) != 0) z += "SwOCPInstant,";
if ((data[idx] & 0x20) != 0) z += "SwBOCPInstant,";
if ((data[idx] & 0x40) != 0) z += "reserved-ID31,";
if ((data[idx] & 0x80) != 0) z += "reserved-ID32,";
//byte[4]
idx++;
if (data[idx] != 0) z += "reserved-ID33~40,";
//byte[5]
idx++;
if (data[idx] != 0) z += "reserved-ID41~48,";
//byte[6]
idx++;
if ((data[idx] & 0x1) != 0) z += "ConsistentFault_VGrid,";
if ((data[idx] & 0x2) != 0) z += "ConsistentFault_FGrid,";
if ((data[idx] & 0x4) != 0) z += "ConsistentFault_DCI,";
if ((data[idx] & 0x8) != 0) z += "ConsistentFault_GFCI,";
if ((data[idx] & 0x10) != 0) z += "SpiCommLose,";
if ((data[idx] & 0x20) != 0) z += "SciCommLose,";
if ((data[idx] & 0x40) != 0) z += "RelayTestFail,";
if ((data[idx] & 0x80) != 0) z += "PvIsoFault,";
//byte[7]
idx++;
if ((data[idx] & 0x1) != 0) z += "OverTempFault_Inv,";
if ((data[idx] & 0x2) != 0) z += "OverTempFault_Boost,";
if ((data[idx] & 0x4) != 0) z += "OverTempFault_Env,";
if ((data[idx] & 0x8) != 0) z += "PEConnectFault,";
if ((data[idx] & 0x10) != 0) z += "reserved-ID61,";
if ((data[idx] & 0x20) != 0) z += "reserved-ID62,";
if ((data[idx] & 0x40) != 0) z += "reserved-ID63,";
if ((data[idx] & 0x80) != 0) z += "reserved-ID64,";
//byte[8]
idx++;
if ((data[idx] & 0x1) != 0) z += "unrecoverHwAcOCP,";
if ((data[idx] & 0x2) != 0) z += "unrecoverBusOVP,";
if ((data[idx] & 0x4) != 0) z += "unrecoverIacRmsUnbalance,";
if ((data[idx] & 0x8) != 0) z += "unrecoverIpvUnbalance,";
if ((data[idx] & 0x10) != 0) z += "unrecoverVbusUnbalance,";
if ((data[idx] & 0x20) != 0) z += "unrecoverOCPInstant,";
if ((data[idx] & 0x40) != 0) z += "unrecoverPvConfigSetWrong,";
if ((data[idx] & 0x80) != 0) z += "reserved-ID72,";
//byte[9]
idx++;
if ((data[idx] & 0x1) != 0) z += "reserved-ID73,";
if ((data[idx] & 0x2) != 0) z += "unrecoverIPVInstant,";
if ((data[idx] & 0x4) != 0) z += "unrecoverWRITEEEPROM,";
if ((data[idx] & 0x8) != 0) z += "unrecoverREADEEPROM,";
if ((data[idx] & 0x10) != 0) z += "unrecoverRelayFail,";
if ((data[idx] & 0x20) != 0) z += "reserved-ID78,";
if ((data[idx] & 0x40) != 0) z += "reserved-ID79,";
if ((data[idx] & 0x80) != 0) z += "reserved-ID80,";
if(z.length() > 0){
z.pop_back();
}
return {z};
sensor:
- platform: wifi_signal
id: ${esp_id}_wifi_signal
name: ${friendly_node_name} WiFi Signal
update_interval: 30s
icon: "mdi:wifi"
- platform: uptime
id: ${esp_id}_uptime
name: ${friendly_node_name} Uptime
filters:
- lambda: return x / 60.0;
unit_of_measurement: minutes
icon: "mdi:clock-start"
- platform: heapmon
id: heapspace
name: ${friendly_node_name} Heapsize
icon: "mdi:memory"
update_interval: 5s
filters:
- throttle: 30s
entity_category: diagnostic
- platform: modbus_controller
modbus_controller_id: sofarsolar
name: ${friendly_name} DC1 Voltage
id: ${esp_id}_dc_v1
register_type: holding
address: 0x0006
unit_of_measurement: "V"
state_class: "measurement"
device_class: "voltage"
icon: "mdi:alpha-v-circle-outline"
value_type: U_WORD
accuracy_decimals: 1
filters:
- multiply: 0.1
- platform: modbus_controller
modbus_controller_id: sofarsolar
name: ${friendly_name} DC1 Current
id: ${esp_id}_dc_c1
register_type: holding
address: 0x0007
unit_of_measurement: "A"
state_class: "measurement"
device_class: "current"
icon: "mdi:alpha-a-circle-outline"
value_type: U_WORD
accuracy_decimals: 2
filters:
- multiply: 0.01
- platform: modbus_controller
modbus_controller_id: sofarsolar
name: ${friendly_name} DC2 Voltage
id: ${esp_id}_dc_v2
register_type: holding
address: 0x0008
unit_of_measurement: "V"
state_class: "measurement"
device_class: "voltage"
icon: "mdi:alpha-v-circle-outline"
value_type: U_WORD
accuracy_decimals: 1
filters:
- multiply: 0.1
- platform: modbus_controller
modbus_controller_id: sofarsolar
name: ${friendly_name} DC2 Current
id: ${esp_id}_dc_c2
register_type: holding
address: 0x0009
unit_of_measurement: "A"
state_class: "measurement"
device_class: "current"
icon: "mdi:alpha-a-circle-outline"
value_type: U_WORD
accuracy_decimals: 2
filters:
- multiply: 0.01
- platform: modbus_controller
modbus_controller_id: sofarsolar
name: ${friendly_name} DC1 Power
id: ${esp_id}_dc_power1
register_type: holding
address: 0x000a
unit_of_measurement: "W"
state_class: "measurement"
device_class: "power"
icon: "mdi:solar-power"
value_type: U_WORD
filters:
- multiply: 10
- platform: modbus_controller
modbus_controller_id: sofarsolar
name: ${friendly_name} DC2 Power
id: ${esp_id}_dc_power2
register_type: holding
address: 0x000b
unit_of_measurement: "W"
state_class: "measurement"
device_class: "power"
icon: "mdi:solar-power"
value_type: U_WORD
filters:
- multiply: 10
- platform: modbus_controller
modbus_controller_id: sofarsolar
name: ${friendly_name} AC Power
id: ${esp_id}_ac_power
register_type: holding
address: 0x000c
unit_of_measurement: "W"
state_class: "measurement"
device_class: "power"
icon: "mdi:solar-power-variant-outline"
value_type: U_WORD
filters:
- multiply: 10
- platform: modbus_controller
modbus_controller_id: sofarsolar
name: ${friendly_name} AC Reactive Power
id: ${esp_id}_ac_reactive_power
register_type: holding
address: 0x000d
unit_of_measurement: "kVar"
state_class: "measurement"
icon: "mdi:math-cos"
value_type: S_WORD
filters:
- multiply: 10
- platform: modbus_controller
modbus_controller_id: sofarsolar
name: ${friendly_name} L1 Voltage
id: ${esp_id}_ac_v1
register_type: holding
address: 0x000f
unit_of_measurement: "V"
state_class: "measurement"
device_class: "voltage"
icon: "mdi:alpha-v-circle"
value_type: U_WORD
accuracy_decimals: 1
filters:
- multiply: 0.1
- platform: modbus_controller
modbus_controller_id: sofarsolar
name: ${friendly_name} L2 Voltage
id: ${esp_id}_ac_v2
register_type: holding
address: 0x0011
unit_of_measurement: "V"
state_class: "measurement"
device_class: "voltage"
icon: "mdi:alpha-v-circle"
value_type: U_WORD
accuracy_decimals: 1
filters:
- multiply: 0.1
- platform: modbus_controller
modbus_controller_id: sofarsolar
name: ${friendly_name} L3 Voltage
id: ${esp_id}_ac_v3
register_type: holding
address: 0x0013
unit_of_measurement: "V"
state_class: "measurement"
device_class: "voltage"
icon: "mdi:alpha-v-circle"
value_type: U_WORD
accuracy_decimals: 1
filters:
- multiply: 0.1
- platform: modbus_controller
modbus_controller_id: sofarsolar
name: ${friendly_name} L1 Current
id: ${esp_id}_ac_c1
register_type: holding
address: 0x0010
unit_of_measurement: "A"
state_class: "measurement"
device_class: "current"
icon: "mdi:alpha-a-circle"
value_type: U_WORD
accuracy_decimals: 2
filters:
- multiply: 0.01
- platform: modbus_controller
modbus_controller_id: sofarsolar
name: ${friendly_name} L2 Current
id: ${esp_id}_ac_c2
register_type: holding
address: 0x0012
unit_of_measurement: "A"
state_class: "measurement"
device_class: "current"
icon: "mdi:alpha-a-circle"
value_type: U_WORD
accuracy_decimals: 2
filters:
- multiply: 0.01
- platform: modbus_controller
modbus_controller_id: sofarsolar
name: ${friendly_name} L3 Current
id: ${esp_id}_ac_c3
register_type: holding
address: 0x0014
unit_of_measurement: "A"
state_class: "measurement"
device_class: "current"
icon: "mdi:alpha-a-circle"
value_type: U_WORD
accuracy_decimals: 2
filters:
- multiply: 0.01
- platform: modbus_controller
modbus_controller_id: sofarsolar
name: ${friendly_name} AC Freq
id: ${esp_id}_ac_freq
register_type: holding
address: 0x000e
unit_of_measurement: "Hz"
state_class: "measurement"
icon: "mdi:current-ac"
value_type: U_WORD
accuracy_decimals: 2
filters:
- multiply: 0.01
- platform: modbus_controller
modbus_controller_id: sofarsolar
name: ${friendly_name} Energy total
id: ${esp_id}_energy_total
register_type: holding
address: 0x0015
unit_of_measurement: "kWh"
accuracy_decimals: 2
device_class: "energy"
state_class: "total_increasing"
icon: "mdi:solar-power-variant-outline"
value_type: U_DWORD
- platform: modbus_controller
modbus_controller_id: sofarsolar
name: ${friendly_name} Energy generation time total
id: ${esp_id}_energy_generation_time_total
register_type: holding
address: 0x0017
unit_of_measurement: "h"
icon: "mdi:timeline-clock"
value_type: U_DWORD
- platform: modbus_controller
modbus_controller_id: sofarsolar
name: ${friendly_name} Energy today
id: ${esp_id}_energy_today
register_type: holding
address: 0x0019
unit_of_measurement: "kWh"
state_class: "measurement"
device_class: "energy"
icon: "mdi:solar-power-variant-outline"
value_type: U_WORD
accuracy_decimals: 2
filters:
- multiply: 0.01
- platform: modbus_controller
modbus_controller_id: sofarsolar
name: ${friendly_name} Energy generation time today
id: ${esp_id}_energy_generation_time_today
register_type: holding
address: 0x001A
unit_of_measurement: "min"
icon: "mdi:timeline-clock"
value_type: U_WORD
- platform: modbus_controller
modbus_controller_id: sofarsolar
name: ${friendly_name} Temprature module
id: ${esp_id}_temp_module
register_type: holding
address: 0x001B
unit_of_measurement: "°C"
state_class: "measurement"
device_class: "temperature"
icon: "mdi:temperature-celsius"
value_type: U_WORD
filters:
- throttle: 10min
- platform: modbus_controller
modbus_controller_id: sofarsolar
name: ${friendly_name} Temprature inverter
id: ${esp_id}_temp_inverter
register_type: holding
address: 0x001C
unit_of_measurement: "°C"
state_class: "measurement"
device_class: "temperature"
icon: "mdi:temperature-celsius"
value_type: U_WORD
filters:
- throttle: 30s
- platform: modbus_controller
modbus_controller_id: sofarsolar
name: ${friendly_name} Bus voltage
id: ${esp_id}_bus_voltage
register_type: holding
address: 0x001D
unit_of_measurement: "V"
state_class: "measurement"
device_class: "voltage"
icon: "mdi:alpha-v-circle-outline"
value_type: U_WORD
accuracy_decimals: 1
filters:
- multiply: 0.1
- platform: modbus_controller
modbus_controller_id: sofarsolar
name: ${friendly_name} PV1+ isolation resistance
id: ${esp_id}_dc_isolation_resistance1
register_type: holding
address: 0x0024
unit_of_measurement: "Ohm"
state_class: "measurement"
icon: "mdi:omega"
value_type: U_WORD
- platform: modbus_controller
modbus_controller_id: sofarsolar
name: ${friendly_name} PV2+ isolation resistance
id: ${esp_id}_dc_isolation_resistance2
register_type: holding
address: 0x0025
unit_of_measurement: "Ohm"
state_class: "measurement"
icon: "mdi:omega"
value_type: U_WORD
- platform: modbus_controller
modbus_controller_id: sofarsolar
name: ${friendly_name} PV- isolation resistance
id: ${esp_id}_cathode_to_ground_impedance
register_type: holding
address: 0x0026
unit_of_measurement: "Ohm"
state_class: "measurement"
icon: "mdi:omega"
value_type: U_WORD
- platform: template
name: ${friendly_name} DC Power (total)
id: ${esp_id}_dc_power_total
lambda: |-
return (id(${esp_id}_dc_power2).state + id(${esp_id}_dc_power1).state);
unit_of_measurement: W
state_class: "measurement"
device_class: "power"
accuracy_decimals: 0
icon: "mdi:alpha-a-circle-outline"
update_interval: 5s
- platform: uptime
name: ${friendly_name} Uptime
id: uptime_sensor
update_interval: 5s
icon: "mdi:clock-start"
internal: true
entity_category: diagnostic
on_raw_value:
then:
- text_sensor.template.publish:
id: uptime_human
state: !lambda |-
int seconds = round(id(uptime_sensor).raw_state);
seconds = seconds % (24 * 3600);
int hours = seconds / 3600;
seconds = seconds % 3600;
int minutes = seconds / 60;
seconds = seconds % 60;
return (
(hours ? to_string(hours) + "h " : "") +
(minutes ? to_string(minutes) + "m " : "") +
(to_string(seconds) + "s")
).c_str();
- platform: copy
source_id: ${esp_id}_wifi_signal
id: ${esp_id}_wifi_signal_hr
name: "${friendly_node_name} WiFi %"
filters:
- lambda: return min(max(2 * (x + 100.0), 0.0), 100.0);
unit_of_measurement: "%"
icon: "mdi:wifi"
device_class: "signal_strength"
entity_category: "diagnostic"
switch:
- platform: restart
name: ${friendly_node_name} Restart
binary_sensor:
- platform: status
name: ${friendly_node_name} Status