May be a silly suggestion but I recall when I tried to get this to work, I mixed up the pairs on the ethernet cable (Type B Config) going to the RS485 to TTL converter - switched these over and the same modbus error disappeared and it started working. I removed the R7 resistor and doubled up the ethernet pairs as seen below.
Here's a pic of a ESP32 Dev board that I made for a colleague - powered using a cellphone charger into the micro USB port
If I recall correctly, the brown jumper is power 5V from the ESP32 and the white jumper is ground (ran out of red and black jumpers). Used a wago type connector to bridge the DE & RE pins on the RS485 converter.
And here's my code courtesy of @slipx
esphome:
name: sunsynk
substitutions:
settings_skipped_updates: "30"
esp32:
board: esp32dev
framework:
type: arduino
# Enable logging
logger:
baud_rate: 0
# Enable Home Assistant API
api:
encryption:
key:
ota:
password:
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
power_save_mode: none
fast_connect: true
manual_ip:
static_ip: 192.168.0.135
gateway: 192.168.1.1
subnet: 255.255.255.0
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Sunsynk Fallback Hotspot"
password: "W88biQV6RGjF"
captive_portal:
# Enable time component to reset energy at midnight
# https://esphome.io/components/time.html#home-assistant-time-source
time:
- platform: homeassistant
id: homeassistant_time
uart:
id: mod_bus
tx_pin: 17
rx_pin: 16
baud_rate: 9600
stop_bits: 1
modbus:
id: sunsynk_modbus
flow_control_pin: 4
modbus_controller:
- id: sunsynk
address: 0x01
modbus_id: sunsynk_modbus
setup_priority: -10
update_interval: "15s"
command_throttle: "50ms"
############################################### BINARY SENSORS ###############################################
binary_sensor:
- platform: modbus_controller # 194 Grid Connected Status
modbus_controller_id: sunsynk
name: "Grid Connected Status"
id: grid_connected_status
register_type: holding
address: 194
############################################### SENSORS ###############################################
sensor:
- platform: modbus_controller # 013 Firmware Control Board
modbus_controller_id: sunsynk
name: "Firmware Control Board"
id: sunsynk_esphome_firmware_control_board
register_type: holding
skip_updates: ${settings_skipped_updates}
address: 13
- platform: modbus_controller # 014 Firmware Comms Board
modbus_controller_id: sunsynk
name: "Firmware Comms Board"
id: sunsynk_esphome_firmware_comms_board
register_type: holding
skip_updates: ${settings_skipped_updates}
address: 14
- platform: modbus_controller # 070 Battery Charge Day
modbus_controller_id: sunsynk
name: "Battery Charge Day"
id: sunsynk_esphome_battery_charge_day
register_type: holding
address: 70
unit_of_measurement: "kWh"
accuracy_decimals: 1
device_class: energy
state_class: total_increasing
filters: #GOOD
- lambda: |-
x = x / 10;
if (x > 32767) return (x - 65535) /1;
else return (x) /1;
- platform: modbus_controller # 071 Battery Discharge Day
modbus_controller_id: sunsynk
name: "Battery Discharge Day"
id: sunsynk_esphome_battery_discharge_day
register_type: holding
address: 71
unit_of_measurement: "kWh"
accuracy_decimals: 1
device_class: energy
state_class: total_increasing
filters: #GOOD
- lambda: |-
x = x / 10;
if (x > 32767) return (x - 65535) /1;
else return (x) /1;
- platform: modbus_controller # 072 Battery Charge Energy Total
modbus_controller_id: sunsynk
name: "Total Battery Charge (kWh)"
id: total_battery_charge_kwh
register_type: holding
address: 72
unit_of_measurement: "kWh"
accuracy_decimals: 1
device_class: energy
state_class: total_increasing
value_type: U_DWORD_R
filters:
- multiply: 0.1
- platform: modbus_controller # 074 Battery Discharge Energy Total
modbus_controller_id: sunsynk
name: "Total Battery Discharge (kWh)"
id: total_battery_discharge_kwh
register_type: holding
address: 74
unit_of_measurement: "kWh"
accuracy_decimals: 0
device_class: energy
state_class: total_increasing
value_type: U_DWORD_R
filters:
- multiply: 0.1
- platform: modbus_controller # 076 Grid Import Day (Buy)
modbus_controller_id: sunsynk
name: "Grid Import Day (Buy)"
id: sunsynk_esphome_grid_import_day
register_type: holding
address: 76
unit_of_measurement: "kWh"
accuracy_decimals: 1
device_class: energy
state_class: total_increasing
filters: # GOOD
- lambda: |-
if (x > 32767) return (x - 65535) / 10;
else return x /10;
- platform: modbus_controller # 078 Grid Import Energy Total (Buy)
modbus_controller_id: sunsynk
name: "Total Grid Import (kWh)"
id: total_grid_import_kwh
register_type: holding
address: 78
unit_of_measurement: "kWh"
accuracy_decimals: 2
device_class: energy
state_class: total_increasing
filters:
- multiply: 0.1
- platform: modbus_controller # 079 Grid Frequency
modbus_controller_id: sunsynk
name: "Grid Frequency"
id: sunsynk_esphome_grid_frequency
register_type: holding
address: 79
unit_of_measurement: "hz"
accuracy_decimals: 2
filters: #GOOD
- lambda: |-
if (x > 32767) return (x - 65535) /100;
else return (x) /100;
#device_class: none
state_class: measurement
- platform: modbus_controller # 081 Grid Export Energy Total (Sell)
modbus_controller_id: sunsynk
name: "Total Grid Export (kWh)"
id: total_grid_export_kwh
register_type: holding
address: 81
unit_of_measurement: "kWh"
accuracy_decimals: 2
device_class: energy
state_class: total_increasing
filters:
- lambda: |-
if (x > 32767) return (x - 65535) / 10;
else return x /10;
- platform: modbus_controller # 084 Daily Load
modbus_controller_id: sunsynk
name: "Daily Load Power (kWh)"
id: daily_load_power_kwh
register_type: holding
address: 84
unit_of_measurement: "kWh"
accuracy_decimals: 2
device_class: energy
state_class: total_increasing
filters:
- multiply: 0.1
- platform: modbus_controller # 085 Total Load
modbus_controller_id: sunsynk
name: "Total Load Power (kWh)"
id: total_load_power_kwh
register_type: holding
address: 85
unit_of_measurement: "kWh"
accuracy_decimals: 2
device_class: energy
state_class: total_increasing
value_type: U_DWORD_R
filters:
- multiply: 0.1
- platform: modbus_controller # 090 DC Transformer Temperature
modbus_controller_id: sunsynk
name: "SS DC Transformer Temperature"
id: sunsynk_esphome_dctransformer_temperature
register_type: holding
address: 090
unit_of_measurement: "°C"
accuracy_decimals: 1
device_class: temperature
state_class: measurement
filters: # GOOD
- lambda: |-
if (x > 32767) return ((x - 65535)-1000) / 10;
else return ((x)-1000) / 10;
- platform: modbus_controller # 091 Radiator Temperature
modbus_controller_id: sunsynk
name: "SS DC Radiator Temperature"
id: sunsynk_esphome_radiator_temperature
register_type: holding
address: 091
unit_of_measurement: "°C"
accuracy_decimals: 1
device_class: temperature
state_class: measurement
filters: # GOOD
- lambda: |-
if (x > 32767) return ((x - 65535)-1000) / 10;
else return ((x)-1000) / 10;
- platform: modbus_controller # 096 PV Energy Total
modbus_controller_id: sunsynk
name: "Total PV Power (kWh)"
id: total_pv_power_kwh
register_type: holding
address: 96
unit_of_measurement: "kWh"
accuracy_decimals: 2
device_class: energy
state_class: total_increasing
filters:
- multiply: 0.1
- platform: modbus_controller # 108 Day PV Power
modbus_controller_id: sunsynk
name: "Daily PV Power (kWh)"
id: daily_pv_power_kwh
register_type: holding
address: 108
unit_of_measurement: "kWh"
accuracy_decimals: 1
device_class: energy
state_class: total_increasing
filters:
- multiply: 0.1
- platform: modbus_controller # 109 DC1 Voltage
modbus_controller_id: sunsynk
name: "DC1 Voltage"
id: sunsynk_esphome_dc1_voltage
register_type: holding
address: 109
unit_of_measurement: "V"
device_class: voltage
state_class: measurement
filters:
- multiply: 0.1
- platform: modbus_controller # 111 DC2 Voltage
modbus_controller_id: sunsynk
name: "DC2 Voltage"
id: sunsynk_esphome_dc2_voltage
register_type: holding
address: 111
unit_of_measurement: "V"
filters:
- multiply: 0.1
device_class: voltage
state_class: measurement
- platform: modbus_controller # 110 DC1 Output Current
modbus_controller_id: sunsynk
name: "DC1 Current"
id: sunsynk_esphome_dc1_current
register_type: holding
address: 110
unit_of_measurement: "A"
accuracy_decimals: 1
device_class: current
state_class: measurement
filters:
- multiply: 0.1
- platform: modbus_controller # 112 DC2 Output Current
modbus_controller_id: sunsynk
name: "DC2 Current"
id: sunsynk_esphome_dc2_current
register_type: holding
address: 112
unit_of_measurement: "A"
accuracy_decimals: 1
device_class: current
state_class: measurement
filters:
- multiply: 0.1
- platform: modbus_controller # 154 Grid Inverter Voltage
modbus_controller_id: sunsynk
name: "Grid Inverter Voltage"
id: sunsynk_esphome_grid_inverter_voltage
register_type: holding
address: 154
unit_of_measurement: "V"
accuracy_decimals: 1
filters: #GOOD
- lambda: |-
if (x > 32767) return (x - 65535) /10;
else return (x) /10;
device_class: voltage
state_class: measurement
- platform: modbus_controller # 164 Inverter Output Current
modbus_controller_id: sunsynk
name: "Inverter Output Current"
id: sunsynk_esphome_inverter_output_current
register_type: holding
address: 164
unit_of_measurement: "A"
accuracy_decimals: 1
device_class: current
state_class: measurement
value_type: S_WORD
filters:
- multiply: 0.01
- platform: modbus_controller # 166 Aux Output Power
modbus_controller_id: sunsynk
name: "Aux Output Power"
id: sunsynk_esphome_aux_output_power
register_type: holding
address: 166
unit_of_measurement: "W"
accuracy_decimals: 0
device_class: power
state_class: measurement
filters: #GOOD
- lambda: |-
if (x > 32767) return (x - 65535) /1;
else return (x) /1;
- platform: modbus_controller # 169 (167+168) Grid Power
modbus_controller_id: sunsynk
name: "Grid Power"
id: grid_power
register_type: holding
address: 169
unit_of_measurement: "W"
accuracy_decimals: 0
device_class: power
state_class: measurement
#value_type: S_WORD
filters: #GOOD
- lambda: |-
float MIN_VALUE = -10000.0;
float MAX_VALUE = 10000.0;
if (MIN_VALUE <= x && x <= MAX_VALUE) return x;
else return {};
- platform: modbus_controller # 172 Grid External Power
modbus_controller_id: sunsynk
name: "Grid External Power"
id: grid_external_power
register_type: holding
address: 172
unit_of_measurement: "W"
accuracy_decimals: 0
device_class: power
state_class: measurement
#value_type: S_WORD
filters: #GOOD
- lambda: |-
float MIN_VALUE = -10000.0;
float MAX_VALUE = 10000.0;
if (MIN_VALUE <= x && x <= MAX_VALUE) return x;
else return {};
- platform: modbus_controller # 175 Inverter Output Power
modbus_controller_id: sunsynk
name: "Inverter Output Power"
id: sunsynk_esphome_inverter_output_power
register_type: holding
address: 175
unit_of_measurement: "W"
accuracy_decimals: 0
device_class: power
value_type: S_WORD
filters: #GOOD
- lambda: |-
if (x > 32767) return (0 - x + 65535) /-1;
else return (0 - x) /-1;
- platform: modbus_controller # 176 Load Power
modbus_controller_id: sunsynk
name: "Load Power 176"
id: ss_load_power_176
register_type: holding
address: 176
unit_of_measurement: "W"
accuracy_decimals: 0
device_class: power
state_class: measurement
value_type: S_WORD
filters: #GOOD
- lambda: |-
if (x > 32767) return (x - 65536) /1;
else return (x) /1;
- platform: modbus_controller # 177 Load Power
modbus_controller_id: sunsynk
name: "Load Power 177"
id: ss_load_power_177
register_type: holding
address: 177
unit_of_measurement: "W"
accuracy_decimals: 0
device_class: power
state_class: measurement
value_type: S_WORD
filters: #GOOD
- lambda: |-
if (x > 32767) return (x - 65536) /1;
else return (x) /1;
- platform: modbus_controller # 178 Load Power
modbus_controller_id: sunsynk
name: "Load Power"
id: load_power
register_type: holding
address: 178
unit_of_measurement: "W"
accuracy_decimals: 0
device_class: power
state_class: measurement
value_type: S_WORD
filters: #GOOD
- lambda: |-
if (x > 32767) return (x - 65536) /1;
else return (x) /1;
- platform: modbus_controller # 182 Battery Temperature
modbus_controller_id: sunsynk
name: "SS Battery Temperature"
id: sunsynk_esphome_battery_temperature
register_type: holding
address: 182
unit_of_measurement: "°C"
accuracy_decimals: 1
device_class: temperature
state_class: measurement
filters: # GOOD
- lambda: |-
if (x > 32767) return ((x - 65535)-1000) / 10;
else return ((x)-1000) / 10;
- platform: modbus_controller # 183 Battery Voltage
modbus_controller_id: sunsynk
name: "Battery Voltage"
id: sunsynk_esphome_battery_voltage
register_type: holding
address: 183
unit_of_measurement: "V"
accuracy_decimals: 1
filters: #GOOD
- lambda: |-
if (x > 32767) return (x - 65535) / 100;
else return x / 100;
device_class: voltage
state_class: measurement
- platform: modbus_controller # 184 Battery SOC
modbus_controller_id: sunsynk
name: "Battery SOC"
id: battery_soc
register_type: holding
address: 184
unit_of_measurement: "%"
accuracy_decimals: 0
device_class: battery
filters: #GOOD
- lambda: |-
if (x > 32767) return (x - 65535) /1;
else return (x) /1;
- platform: modbus_controller # 186 PV1 Power
modbus_controller_id: sunsynk
name: "PV1 Power"
id: pv1_power
register_type: holding
address: 186
unit_of_measurement: "W"
accuracy_decimals: 0
device_class: power
state_class: measurement
- platform: modbus_controller # 187 PV2 Power
modbus_controller_id: sunsynk
name: "PV2 Power"
id: pv2_power
register_type: holding
address: 187
unit_of_measurement: "W"
accuracy_decimals: 0
device_class: power
state_class: measurement
- platform: template # Sum of PV1 and PV2 to get total PV Power
name: "SS Total Solar"
unit_of_measurement: "W"
accuracy_decimals: 0
device_class: power
state_class: measurement
lambda: |-
return (id(pv1_power).state + id(pv2_power).state);
update_interval: 5s
- platform: modbus_controller # 190 Battery Output Power
modbus_controller_id: sunsynk
name: "Battery Output Power"
id: sunsynk_esphome_battery_output_power
register_type: holding
address: 190
unit_of_measurement: "W"
accuracy_decimals: 0
device_class: power
value_type: S_WORD
filters: #GOOD
- lambda: |-
if (x > 32767) return (x - 65536) /1;
else return (x) /1;
- platform: modbus_controller # 191 Battery Output Current
modbus_controller_id: sunsynk
name: "Battery Output Current"
id: sunsynk_esphome_battery_output_current
register_type: holding
address: 191
unit_of_measurement: "A"
accuracy_decimals: 1
device_class: current
state_class: measurement
value_type: S_WORD
filters: #GOOD
- lambda: |-
if (x > 32767) return (x - 65536) / 100;
else return x / 100;
- platform: modbus_controller # 192 Load Frequency
modbus_controller_id: sunsynk
name: "Load Frequency"
id: sunsynk_esphome_load_frequency
register_type: holding
address: 192
unit_of_measurement: "hz"
accuracy_decimals: 2
filters: #GOOD
- lambda: |-
if (x > 32767) return (x - 65535) /100;
else return (x) /100;
#device_class: none
state_class: measurement
- platform: modbus_controller # 216 Battery Charging Efficiency
modbus_controller_id: sunsynk
name: "Battery Charging Efficiency"
id: battery_charging_efficiency
register_type: holding
address: 216
unit_of_measurement: "%"
accuracy_decimals: 1
device_class: battery
filters: #GOOD
- lambda: |-
if (x > 32767) return (x - 65535) /10;
else return (x) /10;
- platform: modbus_controller # 217 Battery Capacity Shutdown
modbus_controller_id: sunsynk
name: "Battery Capacity Shutdown"
id: sunsynk_battery_capacity_shutdown
register_type: holding
address: 217
unit_of_measurement: "%"
accuracy_decimals: 0
device_class: battery
################################################ READ SETTINGS ################################################
- platform: modbus_controller # 250 Settings Timezone1
modbus_controller_id: sunsynk
name: "Setting Timezone1"
id: sunsynk_esphome_setting_timezone1
register_type: holding
skip_updates: ${settings_skipped_updates}
address: 250
filters: #GOOD
- lambda: |-
if (x > 32767) return (x - 65535) /1;
else return (x) /1;
icon: "mdi:clock"
- platform: modbus_controller # 251 Settings Timezone2
modbus_controller_id: sunsynk
name: "Setting Timezone2"
id: sunsynk_esphome_setting_timezone2
register_type: holding
skip_updates: ${settings_skipped_updates}
address: 251
filters: #GOOD
- lambda: |-
if (x > 32767) return (x - 65535) /1;
else return (x) /1;
icon: "mdi:clock"
- platform: modbus_controller # 252 Settings Timezone3
modbus_controller_id: sunsynk
name: "Setting Timezone3"
id: sunsynk_esphome_setting_timezone3
register_type: holding
skip_updates: ${settings_skipped_updates}
address: 252
filters: #GOOD
- lambda: |-
if (x > 32767) return (x - 65535) /1;
else return (x) /1;
icon: "mdi:clock"
- platform: modbus_controller # 253 Settings Timezone4
modbus_controller_id: sunsynk
name: "Setting Timezone4"
id: sunsynk_esphome_setting_timezone4
register_type: holding
skip_updates: ${settings_skipped_updates}
address: 253
icon: "mdi:clock"
- platform: modbus_controller # 254 Settings Timezone5
modbus_controller_id: sunsynk
name: "Setting Timezone5"
id: sunsynk_esphome_setting_timezone5
register_type: holding
skip_updates: ${settings_skipped_updates}
address: 254
filters: #GOOD
- lambda: |-
if (x > 32767) return (x - 65535) /1;
else return (x) /1;
icon: "mdi:clock"
- platform: modbus_controller # 255 Settings Timezone6
modbus_controller_id: sunsynk
name: "Setting Timezone6"
id: sunsynk_esphome_setting_timezone6
register_type: holding
skip_updates: ${settings_skipped_updates}
address: 255
filters: #GOOD
- lambda: |-
if (x > 32767) return (x - 65535) /1;
else return (x) /1;
icon: "mdi:clock"
- platform: modbus_controller # 268 Settings SoC Timezone1
modbus_controller_id: sunsynk
name: "Setting SoC Timezone1"
id: sunsynk_esphome_setting_soc_timezone1
register_type: holding
skip_updates: ${settings_skipped_updates}
address: 268
value_type: U_WORD
- platform: modbus_controller # 269 Settings SoC Timezone2
modbus_controller_id: sunsynk
name: "Setting SoC Timezone2"
id: sunsynk_esphome_setting_soc_timezone2
register_type: holding
skip_updates: ${settings_skipped_updates}
address: 269
value_type: U_WORD
- platform: modbus_controller # 270 Settings SoC Timezone3
modbus_controller_id: sunsynk
name: "Setting SoC Timezone3"
id: sunsynk_esphome_setting_soc_timezone3
register_type: holding
skip_updates: ${settings_skipped_updates}
address: 270
value_type: U_WORD
- platform: modbus_controller # 271 Settings SoC Timezone4
modbus_controller_id: sunsynk
name: "Setting SoC Timezone4"
id: sunsynk_esphome_setting_soc_timezone4
register_type: holding
skip_updates: ${settings_skipped_updates}
address: 271
value_type: U_WORD
- platform: modbus_controller # 272 Settings SoC Timezone5
modbus_controller_id: sunsynk
name: "Setting SoC Timezone5"
id: sunsynk_esphome_setting_soc_timezone5
register_type: holding
skip_updates: ${settings_skipped_updates}
address: 272
value_type: U_WORD
- platform: modbus_controller # 273 Settings SoC Timezone6
modbus_controller_id: sunsynk
name: "Setting SoC Timezone6"
id: sunsynk_esphome_setting_soc_timezone6
register_type: holding
skip_updates: ${settings_skipped_updates}
address: 273
value_type: U_WORD
- platform: modbus_controller # 274 Settings Grid Charge Timezone1
modbus_controller_id: sunsynk
name: "Setting Grid Charge Timezone1"
id: sunsynk_esphome_setting_grid_charge_timezone1
register_type: holding
skip_updates: ${settings_skipped_updates}
address: 274
- platform: modbus_controller # 275 Settings Grid Charge Timezone2
modbus_controller_id: sunsynk
name: "Setting Grid Charge Timezone2"
id: sunsynk_esphome_setting_grid_charge_timezone2
register_type: holding
skip_updates: ${settings_skipped_updates}
address: 275
- platform: modbus_controller # 276 Settings Grid Charge Timezone3
modbus_controller_id: sunsynk
name: "Setting Grid Charge Timezone3"
id: sunsynk_esphome_setting_grid_charge_timezone3
register_type: holding
skip_updates: ${settings_skipped_updates}
address: 276
- platform: modbus_controller # 277 Settings Grid Charge Timezone4
modbus_controller_id: sunsynk
name: "Setting Grid Charge Timezone4"
id: sunsynk_esphome_setting_grid_charge_timezone4
register_type: holding
skip_updates: ${settings_skipped_updates}
address: 277
- platform: modbus_controller # 278 Settings Grid Charge Timezone5
modbus_controller_id: sunsynk
name: "Setting Grid Charge Timezone5"
id: sunsynk_esphome_setting_grid_charge_timezone5
register_type: holding
skip_updates: ${settings_skipped_updates}
address: 278
- platform: modbus_controller # 279 Settings Grid Charge Timezone6
modbus_controller_id: sunsynk
name: "Setting Grid Charge Timezone6"
id: sunsynk_esphome_setting_grid_charge_timezone6
register_type: holding
skip_updates: ${settings_skipped_updates}
address: 279
################################################ WRITE SETTINGS ################################################
switch:
- platform: modbus_controller # 248 Toggle System Timer
use_write_multiple: true
modbus_controller_id: sunsynk
name: "Toggle System Timer"
id: sunsynk_esphome_toggle_Time_of_Use
register_type: holding
address: 248
bitmask: 1
entity_category: config
icon: "mdi:toggle-switch"
- platform: modbus_controller # 243 Priority Load
use_write_multiple: true
modbus_controller_id: sunsynk
name: "Toggle Priority Load"
id: sunsynk_esphome_toggle_priority_load
register_type: holding
address: 243
bitmask: 1
entity_category: config
icon: "mdi:toggle-switch"
- platform: modbus_controller # 274 Toggle Grid Charge Timezone1
use_write_multiple: true
modbus_controller_id: sunsynk
name: "Toggle Grid Charge Timezone1"
id: sunsynk_esphome_toggle_grid_charge_timezone1
register_type: holding
address: 274
bitmask: 1
entity_category: config
icon: "mdi:toggle-switch"
- platform: modbus_controller # 275 Toggle Grid Charge Timezone2
modbus_controller_id: sunsynk
use_write_multiple: true
name: "Toggle Grid Charge Timezone2"
id: sunsynk_esphome_toggle_grid_charge_timezone2
register_type: holding
address: 275
bitmask: 1
entity_category: config
icon: "mdi:toggle-switch"
- platform: modbus_controller # 276 Toggle Grid Charge Timezone3
modbus_controller_id: sunsynk
use_write_multiple: true
name: "Toggle Grid Charge Timezone3"
id: sunsynk_esphome_toggle_grid_charge_timezone3
register_type: holding
address: 276
bitmask: 1
entity_category: config
icon: "mdi:toggle-switch"
- platform: modbus_controller # 277 Toggle Grid Charge Timezone4
modbus_controller_id: sunsynk
use_write_multiple: true
name: "Toggle Grid Charge Timezone4"
id: sunsynk_esphome_toggle_grid_charge_timezone4
register_type: holding
address: 277
bitmask: 1
entity_category: config
icon: "mdi:toggle-switch"
- platform: modbus_controller # 278 Toggle Grid Charge Timezone5
modbus_controller_id: sunsynk
use_write_multiple: true
name: "Toggle Grid Charge Timezone5"
id: sunsynk_esphome_toggle_grid_charge_timezone5
register_type: holding
address: 278
bitmask: 1
entity_category: config
icon: "mdi:toggle-switch"
- platform: modbus_controller # 279 Toggle Grid Charge Timezone6
modbus_controller_id: sunsynk
use_write_multiple: true
name: "Toggle Grid Charge Timezone6"
id: sunsynk_esphome_toggle_grid_charge_timezone6
register_type: holding
address: 279
bitmask: 1
entity_category: config
icon: "mdi:toggle-switch"
number:
- platform: modbus_controller # 268 Settings SoC Timezone1
use_write_multiple: true
modbus_controller_id: sunsynk
id: sunsynk_esphome_set_soc_timezone1
name: "Set SoC Timezone1"
unit_of_measurement: "%"
address: 268
min_value: 0
max_value: 100
step: 5
value_type: U_WORD
- platform: modbus_controller # 269 Settings SoC Timezone2
use_write_multiple: true
modbus_controller_id: sunsynk
id: sunsynk_esphome_set_soc_timezone2
name: "Set SoC Timezone2"
unit_of_measurement: "%"
address: 269
min_value: 0
max_value: 100
step: 5
value_type: U_WORD
- platform: modbus_controller # 270 Settings SoC Timezone3
use_write_multiple: true
modbus_controller_id: sunsynk
id: sunsynk_esphome_set_soc_timezone3
name: "Set SoC Timezone3"
unit_of_measurement: "%"
address: 270
min_value: 0
max_value: 100
step: 5
value_type: U_WORD
- platform: modbus_controller # 271 Settings SoC Timezone4
use_write_multiple: true
modbus_controller_id: sunsynk
id: sunsynk_esphome_set_soc_timezone4
name: "Set SoC Timezone4"
unit_of_measurement: "%"
address: 271
min_value: 0
max_value: 100
step: 5
value_type: U_WORD
- platform: modbus_controller # 272 Settings SoC Timezone5
use_write_multiple: true
modbus_controller_id: sunsynk
id: sunsynk_esphome_set_soc_timezone5
name: "Set SoC Timezone5"
unit_of_measurement: "%"
address: 272
min_value: 0
max_value: 100
step: 5
value_type: U_WORD
- platform: modbus_controller # 273 Settings SoC Timezone6
use_write_multiple: true
modbus_controller_id: sunsynk
id: sunsynk_esphome_set_soc_timezone6
name: "Set SoC Timezone6"
unit_of_measurement: "%"
address: 273
min_value: 0
max_value: 100
step: 5
value_type: U_WORD
################################################ TEMPLATE SENSORS ################################################
text_sensor:
- platform: modbus_controller # 059 Overall State
modbus_controller_id: sunsynk
name: "Overall State"
id: sunsynk_overall_state
register_type: holding
skip_updates: ${settings_skipped_updates}
raw_encode: HEXBYTES
address: 59
lambda: |-
uint16_t value = modbus_controller::word_from_hex_str(x, 0);
switch (value) {
case 0: return std::string("standby");
case 1: return std::string("selftest");
case 2: return std::string("normal");
case 3: return std::string("alarm");
case 4: return std::string("fault");
default: return std::string("unknown");
}
- platform: template
name: "Sunsynk Time Slot 1"
id: sunsynk_time_slot_1
lambda: |-
int minutes, hours;
if (id(sunsynk_esphome_setting_timezone1).state) {
minutes = static_cast<int>(id(sunsynk_esphome_setting_timezone1).state) % 100;
hours = static_cast<int>(id(sunsynk_esphome_setting_timezone1).state) / 100;
} else {
minutes = 0;
hours = 0;
}
char formatted_time[6];
snprintf(formatted_time, sizeof(formatted_time), "%02d:%02d", hours, minutes);
return esphome::optional<std::string>(formatted_time);
- platform: template
name: "Sunsynk Time Slot 2"
id: sunsynk_time_slot_2
lambda: |-
int minutes, hours;
if (id(sunsynk_esphome_setting_timezone2).state) {
minutes = static_cast<int>(id(sunsynk_esphome_setting_timezone2).state) % 100;
hours = static_cast<int>(id(sunsynk_esphome_setting_timezone2).state) / 100;
} else {
minutes = 0;
hours = 0;
}
char formatted_time[6];
snprintf(formatted_time, sizeof(formatted_time), "%02d:%02d", hours, minutes);
return esphome::optional<std::string>(formatted_time);
- platform: template
name: "Sunsynk Time Slot 3"
id: sunsynk_time_slot_3
lambda: |-
int minutes, hours;
if (id(sunsynk_esphome_setting_timezone3).state) {
minutes = static_cast<int>(id(sunsynk_esphome_setting_timezone3).state) % 100;
hours = static_cast<int>(id(sunsynk_esphome_setting_timezone3).state) / 100;
} else {
minutes = 0;
hours = 0;
}
char formatted_time[6];
snprintf(formatted_time, sizeof(formatted_time), "%02d:%02d", hours, minutes);
return esphome::optional<std::string>(formatted_time);
- platform: template
name: "Sunsynk Time Slot 4"
id: sunsynk_time_slot_4
lambda: |-
int minutes, hours;
if (id(sunsynk_esphome_setting_timezone4).state) {
minutes = static_cast<int>(id(sunsynk_esphome_setting_timezone4).state) % 100;
hours = static_cast<int>(id(sunsynk_esphome_setting_timezone4).state) / 100;
} else {
minutes = 0;
hours = 0;
}
char formatted_time[6];
snprintf(formatted_time, sizeof(formatted_time), "%02d:%02d", hours, minutes);
return esphome::optional<std::string>(formatted_time);
- platform: template
name: "Sunsynk Time Slot 5"
id: sunsynk_time_slot_5
lambda: |-
int minutes, hours;
if (id(sunsynk_esphome_setting_timezone5).state) {
minutes = static_cast<int>(id(sunsynk_esphome_setting_timezone5).state) % 100;
hours = static_cast<int>(id(sunsynk_esphome_setting_timezone5).state) / 100;
} else {
minutes = 0;
hours = 0;
}
char formatted_time[6];
snprintf(formatted_time, sizeof(formatted_time), "%02d:%02d", hours, minutes);
return esphome::optional<std::string>(formatted_time);
- platform: template
name: "Sunsynk Time Slot 6"
id: sunsynk_time_slot_6
lambda: |-
int minutes, hours;
if (id(sunsynk_esphome_setting_timezone6).state) {
minutes = static_cast<int>(id(sunsynk_esphome_setting_timezone6).state) % 100;
hours = static_cast<int>(id(sunsynk_esphome_setting_timezone6).state) / 100;
} else {
minutes = 0;
hours = 0;
}
char formatted_time[6];
snprintf(formatted_time, sizeof(formatted_time), "%02d:%02d", hours, minutes);
return esphome::optional<std::string>(formatted_time);
- platform: template
name: "Sunsynk Battery Capacity"
lambda: |-
if (!id(grid_connected_status).state) {
float value = id(sunsynk_battery_capacity_shutdown).state;
char buffer[10];
dtostrf(value, 6, 0, buffer);
return std::string(buffer);
} else {
// Get the current date and time
time_t now = id(homeassistant_time).now().timestamp;
tm* currentTime = localtime(&now);
std::string timeSlot1 = id(sunsynk_time_slot_1).state;
std::string timeSlot2 = id(sunsynk_time_slot_2).state;
std::string timeSlot3 = id(sunsynk_time_slot_3).state;
std::string timeSlot4 = id(sunsynk_time_slot_4).state;
std::string timeSlot5 = id(sunsynk_time_slot_5).state;
std::string timeSlot6 = id(sunsynk_time_slot_6).state;
int hour, minute;
// Convert timeSlot1 to sellTime1Epoch
sscanf(timeSlot1.c_str(), "%d:%d", &hour, &minute);
currentTime->tm_hour = hour;
currentTime->tm_min = minute;
currentTime->tm_sec = 0;
time_t sellTime1Epoch = mktime(currentTime);
// ESP_LOGD("DEBUG", "sellTime1Epoch: %ld, now: %ld", sellTime1Epoch, now);
// Convert timeSlot2 to sellTime2Epoch
sscanf(timeSlot2.c_str(), "%d:%d", &hour, &minute);
currentTime->tm_hour = hour;
currentTime->tm_min = minute;
currentTime->tm_sec = 0;
time_t sellTime2Epoch = mktime(currentTime);
// ESP_LOGD("DEBUG", "sellTime2Epoch: %ld, now: %ld", sellTime2Epoch, now);
// Convert timeSlot3 to sellTime3Epoch
sscanf(timeSlot3.c_str(), "%d:%d", &hour, &minute);
currentTime->tm_hour = hour;
currentTime->tm_min = minute;
currentTime->tm_sec = 0;
time_t sellTime3Epoch = mktime(currentTime);
// Convert timeSlot4 to sellTime4Epoch
sscanf(timeSlot4.c_str(), "%d:%d", &hour, &minute);
currentTime->tm_hour = hour;
currentTime->tm_min = minute;
currentTime->tm_sec = 0;
time_t sellTime4Epoch = mktime(currentTime);
// Convert timeSlot5 to sellTime5Epoch
sscanf(timeSlot5.c_str(), "%d:%d", &hour, &minute);
currentTime->tm_hour = hour;
currentTime->tm_min = minute;
currentTime->tm_sec = 0;
time_t sellTime5Epoch = mktime(currentTime);
// Convert timeSlot6 to sellTime6Epoch
sscanf(timeSlot6.c_str(), "%d:%d", &hour, &minute);
currentTime->tm_hour = hour;
currentTime->tm_min = minute;
currentTime->tm_sec = 0;
time_t sellTime6Epoch = mktime(currentTime);
if (now >= sellTime1Epoch && now < sellTime2Epoch) {
float value = static_cast<float>(id(sunsynk_esphome_set_soc_timezone1).state);
char buffer[10];
dtostrf(value, 6, 0, buffer);
return std::string(buffer);
} else if (now >= sellTime2Epoch && now < sellTime3Epoch) {
float value = static_cast<float>(id(sunsynk_esphome_set_soc_timezone2).state);
char buffer[10];
dtostrf(value, 6, 0, buffer);
return std::string(buffer);
} else if (now >= sellTime3Epoch && now < sellTime4Epoch) {
float value = static_cast<float>(id(sunsynk_esphome_set_soc_timezone3).state);
char buffer[10];
dtostrf(value, 6, 0, buffer);
return std::string(buffer);
} else if (now >= sellTime4Epoch && now < sellTime5Epoch) {
float value = static_cast<float>(id(sunsynk_esphome_set_soc_timezone4).state);
char buffer[10];
dtostrf(value, 6, 0, buffer);
return std::string(buffer);
} else if (now >= sellTime5Epoch && now < sellTime6Epoch) {
float value = static_cast<float>(id(sunsynk_esphome_set_soc_timezone5).state);
char buffer[10];
dtostrf(value, 6, 0, buffer);
return std::string(buffer);
} else if (now >= sellTime6Epoch && now < sellTime1Epoch) {
float value = static_cast<float>(id(sunsynk_esphome_set_soc_timezone6).state);
char buffer[10];
dtostrf(value, 6, 0, buffer);
return std::string(buffer);
} else {
float value = id(sunsynk_battery_capacity_shutdown).state;
char buffer[10];
dtostrf(value, 6, 0, buffer);
return std::string(buffer);
}
}