Jump to content

My Sunsynk 8Kw & data collection setup


Recommended Posts

Martinisonline, I have been using use the ESPHome solution with the SunSynk 8.8kW inverter since about 10 Feb (just after my Inverter was installed), and updates are pretty immediate. Life graphs such as Inverter Power update every 2-3 s here - so I guess it is a function of when the inverter sends an update on the bus? Other data such as Battery SOC updates much slower, so I think it only sends it when the value changes?

In terms of setting write updates, it is normally also instantaneous here, but I sometimes observe  a slight lag (0,5s?), when I for example toggle the grid option for a time period, but it is not something one does so interactively that it bothers one.

I am surprised by the ESPHome device's performance (ESP32) - I have 81! entities defined on it, with absolutely no issue so far - it is running 24/7 unless I reboot/recompile to refine the ESPHome code. I had just done last night the very nice power flow that emulates the SunSynk screen -see attached screen, and had to add a few missing sensors that was not defined in the ESPHome setup.

Screenshot 2023-03-01 at 20.34.34.png

Link to comment
Share on other sites

3 hours ago, CorneSchutte said:

Martinisonline, I have been using use the ESPHome solution with the SunSynk 8.8kW inverter since about 10 Feb (just after my Inverter was installed), and updates are pretty immediate. Life graphs such as Inverter Power update every 2-3 s here - so I guess it is a function of when the inverter sends an update on the bus? Other data such as Battery SOC updates much slower, so I think it only sends it when the value changes?

In terms of setting write updates, it is normally also instantaneous here, but I sometimes observe  a slight lag (0,5s?), when I for example toggle the grid option for a time period, but it is not something one does so interactively that it bothers one.

I am surprised by the ESPHome device's performance (ESP32) - I have 81! entities defined on it, with absolutely no issue so far - it is running 24/7 unless I reboot/recompile to refine the ESPHome code. I had just done last night the very nice power flow that emulates the SunSynk screen -see attached screen, and had to add a few missing sensors that was not defined in the ESPHome setup.

Screenshot 2023-03-01 at 20.34.34.png

Excellent. Like a lot the format style.

my Inverter is a Deye 5K and I'm using a solution based in a raspberry Pi with USB-RS-485 adapter and with a Solark Modbus HA integration. It is working for about 1 year flawless, with a refresh rate of about every 5 seconds.

Now I'm thinking to start to sell the surplus energy to the provider but want to do some automations to change some parameters automatically in the Inverter, specifically the battery charge rate according to time of the day and PV production.

The integration I have, doesn't have the "write" functionality, is read only.

I'm thinking to update the system and start to use this ESP32 approach to gain the "write" possibility. I have some ESP32 devices around and I did before some very simple projects with ESPHome. I've read the thread and the examples provided, but still is a bit confusing how the ESPHome intregration works and how it writes into the inverter registers.

Had a look on the version shared by Klatremis, but the registers are completely different from the Deye 5Kw equipment.

Can you share more details about your solution? ESPHome code...?

Thank you.

 

Screenshot 2023-03-01 222308.png

Link to comment
Share on other sites

"My" ESPHome code, which is a combination of others work before me.

But I believe the Deye registers are completely different?

esphome:
  name: "sunsynk"

preferences:
  flash_write_interval: 5min

esp32:
  board: esp32dev
  framework:
    type: arduino

#################################### GLOBALS ####################################
substitutions:
  modbus_update_interval: "3s"
  settings_skipped_updates: "10"
  query_throttle: "50ms"
  device_name: sunsynk
  friendly_name: SunSynk Link

#################################### STATIC SECTION ####################################
wifi:
  ssid: XXXX
  password: XXX
  fast_connect: true

ota:
  safe_mode: true
  reboot_timeout: 10min
  num_attempts: 5

web_server:
  port: 80

#captive_portal:

# Enable logging
#logger:
#  baud_rate: 0

# Enable Home Assistant API
api:


# https://esphome.io/components/time.html#home-assistant-time-source
time:
  - platform: homeassistant
    id: homeassistant_time

#################################### STATIC SECTION ####################################

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_esphome
   address: 0x01
   modbus_id: sunsynk_modbus
   setup_priority: -10
   update_interval: ${modbus_update_interval}
   command_throttle: ${query_throttle}

switch:
  - platform: restart
    name: "${friendly_name} Restart"

  - platform: modbus_controller      # 248 Toggle System Timer
    use_write_multiple: true
    modbus_controller_id: sunsynk_esphome
    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          # 274 Toggle Grid Charge Timezone1
    use_write_multiple: true
    modbus_controller_id: sunsynk_esphome
    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_esphome
    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_esphome
    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_esphome
    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_esphome
    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_esphome
    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_esphome
    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_esphome
    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_esphome
    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_esphome
    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_esphome
    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_esphome
    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  

sensor: 
   
 - platform: wifi_signal
   name: WiFi signal ${device_name} 
   id: wifi_s
   internal: true
   update_interval: 60s
 - platform: template
   name: Wifi ${device_name}
   unit_of_measurement: '%'
   accuracy_decimals: 0
   icon: "mdi:wifi"
   lambda: |-
        if (id(wifi_s).state < -92.0)
          return 1.0;
        if (id(wifi_s).state > -21.0)
          return 100.0;
        else
          return round(( -0.0154 * id(wifi_s).state * id(wifi_s).state ) - ( 0.3794 * id(wifi_s).state ) + 98.182 );
   update_interval: 60s
 - platform: uptime
   filters:
      - lambda: return x / 3600;
   unit_of_measurement: hours
   name: ${device_name} Uptime

 - platform: modbus_controller          #72 Battery Charge Total
   modbus_controller_id: sunsynk_esphome
   name: "SS Battery Charge Total"
   id: sunsynk_esphome_battery_charge_total
   register_type: holding
   address: 72
   unit_of_measurement: "kWh"
   accuracy_decimals: 1
   device_class: energy
   state_class: total_increasing
   filters:
    - lambda: |-
           x = x / -1;
           if (x > 32767) return (0 - x + 65535) /10;
           else return (0 - x) /10;
 - platform: modbus_controller          #74 Battery Discharge Total
   modbus_controller_id: sunsynk_esphome
   name: "SS Battery Discharge Total"
   id: sunsynk_esphome_battery_discharge_total
   register_type: holding
   address: 74
   unit_of_measurement: "kWh"
   accuracy_decimals: 0
   device_class: energy
   state_class: total_increasing
   filters:
    - lambda: |-
           if (x > 32767) return (x - 65535) /10;
           else return (x) /10;

 - platform: modbus_controller          # 81 Grid Export Total (Sell)
   modbus_controller_id: sunsynk_esphome
   name: "SS Grid Export Total (Sell)"
   id: sunsynk_esphome_grid_export_total_sell
   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          # 78 Grid Import Total (Buy)
   modbus_controller_id: sunsynk_esphome
   name: "SS Grid Import Total (Buy)"
   id: sunsynk_esphome_grid_import_total_buy
   register_type: holding
   address: 78
   unit_of_measurement: "kWh"
   accuracy_decimals: 0
   device_class: energy
   state_class: total_increasing
   filters: #GOOD
    - lambda: |-
           x = x / -1;
           if (x > 32767) return (0 - x + 65535) /1;
           else return (0 - x) /1;
  
 - platform: modbus_controller          # 85 Load Power Total
   modbus_controller_id: sunsynk_esphome
   name: "SS Load Power Total"
   id: sunsynk_esphome_load_power_total
   register_type: holding
   address: 85
   unit_of_measurement: "kWh"
   accuracy_decimals: 0
   device_class: energy
   state_class: total_increasing
   filters: #GOOD
    - lambda: |-
           if (x > 32767) return (0 - x + 65535) /1;
           else return (0 - x) /1;
  
 - platform: modbus_controller
   modbus_controller_id: sunsynk_esphome
   name: "SS Total PV Power (kWh)"
   id: sunsynk_esphome_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          # 169 Grid Power
   modbus_controller_id: sunsynk_esphome
   name: "SS Grid Power"
   id: sunsynk_esphome_grid_power
   register_type: holding
   address: 169
   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          # 178 Load Power
   modbus_controller_id: sunsynk_esphome
   name: "SS Load Power"
   id: sunsynk_esphome_load_power
   register_type: holding
   address: 178
   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       # 186 PV1 Power
   modbus_controller_id: sunsynk_esphome
   name: "SS PV1 Power"
   id: sunsynk_esphome_pv1_power
   register_type: holding
   address: 186
   unit_of_measurement: "W"
   accuracy_decimals: 2
   device_class: power
   state_class: measurement
   
 - platform: modbus_controller       # 187 PV2 Power
   modbus_controller_id: sunsynk_esphome
   name: "SS PV2 Power"
   id: sunsynk_esphome_pv2_power
   register_type: holding
   address: 187
   unit_of_measurement: "W"
   accuracy_decimals: 2
   device_class: power
   state_class: measurement

 - platform: template           # PV Total Power
   name: "SS PV Power"
   id: sunsynk_esphome_pv_power
   unit_of_measurement: "W"
   accuracy_decimals: 2
   device_class: power
   state_class: measurement
   update_interval: 15s
   lambda: |-
     return (id(sunsynk_esphome_pv1_power).state + id(sunsynk_esphome_pv2_power).state);

 - platform: total_daily_energy     # PV Daily Energy
   name: 'SS PV Daily Energy'
   id: sunsynk_esphome_pv_daily_energy
   power_id: sunsynk_esphome_pv_power
   unit_of_measurement: 'kWh'
   icon: mdi:circle-slice-3
   state_class: total_increasing
   device_class: energy
   accuracy_decimals: 2
   restore: true
   filters:
      # Multiplication factor from W to kW is 0.001
      - multiply: 0.001

 - platform: modbus_controller  # 190 Battery Output
   modbus_controller_id: sunsynk_esphome
   name: "SS Battery Output Power"
   id: sunsynk_esphome_battery_output_power
   register_type: holding
   address: 190
   unit_of_measurement: "W"
   accuracy_decimals: 2
   device_class: power
   state_class: measurement
   filters: #GOOD
    - lambda: |-
           if (x > 32767) return (x - 65535) /1;
           else return (x) /1;


 - platform: modbus_controller          # 184 Battery SOC
   modbus_controller_id: sunsynk_esphome
   name: "SS Battery SOC"
   id: sunsynk_esphome_battery_soc
   register_type: holding
   address: 184
   unit_of_measurement: "%"
   accuracy_decimals: 0
   device_class: battery
   state_class: measurement
   filters: #GOOD
    - lambda: |-
           if (x > 32767) return (x - 65535) /1;
           else return (x) /1;

 - platform: modbus_controller          # 184 Battery Usable SOC
   modbus_controller_id: sunsynk_esphome
   name: "SS Battery Usable SOC"
   id: sunsynk_esphome_battery_usable_soc
   register_type: holding
   address: 184
   unit_of_measurement: "%"
   accuracy_decimals: 0
   device_class: battery
   state_class: measurement
   filters: #GOOD
   # battery normally charges to 99%, shutdown level is 20%, so subtract 19 from value and calculate as percentage divided by 80
    - lambda: |-
       
           if (x > 32767) {
              int y = ((((x - 65535) -19) /80) *100) /1; 
              if (y > 100) return 100;
              return y;
           }
           else {
              int y = (((x -19) /80) *100) /1;
              if (y > 100) return 100;
              return y;
           }
          
 - platform: modbus_controller          # 216 Battery Charging Efficiency
   modbus_controller_id: sunsynk_esphome
   name: "SS Battery Charging Efficiency"
   id: sunsynk_esphome_battery_charging_efficiency
   register_type: holding
   address: 216
   unit_of_measurement: "%"
   accuracy_decimals: 1
   device_class: battery
   state_class: measurement
   filters: #GOOD
    - lambda: |-
           if (x > 32767) return (x - 65535) /10;
           else return (x) /10;

# - platform: modbus_controller          # 013 Firmware Control Board
#   modbus_controller_id: sunsynk_esphome
#   name: "SS Firmware Control Board"
#   id: sunsynk_esphome_firmware_control_board
#   register_type: holding
#   address: 13

# - platform: modbus_controller          # 013 Firmware Comms Board
#   modbus_controller_id: sunsynk_esphome
#   name: "SS Firmware Comms Board"
#   id: sunsynk_esphome_firmware_comms_board
#   register_type: holding
#   address: 14

 - platform: modbus_controller          # 079 Grid Frequency
   modbus_controller_id: sunsynk_esphome
   name: "SS 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          # 192 Load Frequency
   modbus_controller_id: sunsynk_esphome
   name: "SS 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          # 154 Grid Inverter Voltage
   modbus_controller_id: sunsynk_esphome
   name: "SS 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         # 150 Grid Voltage
   modbus_controller_id: sunsynk_esphome
   name: "SS Grid Voltage"
   id: sunsynk_esphome_grid_voltage
   register_type: holding
   address: 150
   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         # 154 Grid Inverter Voltage
   modbus_controller_id: sunsynk_esphome
   name: "SS Grid Voltage"
   id: sunsynk_inverter_grid_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          # 183 Battery Voltage
   modbus_controller_id: sunsynk_esphome
   name: "SS 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          # 312 Battery Charge Voltage
   modbus_controller_id: sunsynk_esphome
   name: "SS Battery Charge Voltage"
   id: sunsynk_esphome_battery_charge_voltage
   register_type: holding
   address: 312
   unit_of_measurement: "V"
   accuracy_decimals: 1
   filters: #GOOD
     - lambda: |-
           x = x / -1;
           if (x > 32767) return (0 - x + 65535) /100;
           else return (0 - x) /100;
   device_class: voltage
   state_class: measurement

 - platform: modbus_controller          # 167 Grid Inverter Load
   modbus_controller_id: sunsynk_esphome
   name: "SS Grid Inverter Load"
   id: sunsynk_esphome_grid_inverter_load
   register_type: holding
   address: 167
   unit_of_measurement: "W"
   accuracy_decimals: 0
   filters: #GOOD
     - lambda: |-
           if (x > 32767) return (x - 65535) /1;
           else return (x) /1;
   device_class: power
   state_class: measurement

 - platform: modbus_controller          # 172 Grid External Power
   modbus_controller_id: sunsynk_esphome
   name: "SS Grid External Power"
   id: sunsynk_esphome_grid_external_power
   register_type: holding
   address: 172
   unit_of_measurement: "W"
   accuracy_decimals: 0
   filters: #GOOD
     - lambda: |-
           if (x > 32767) return (x - 65535) /1;
           else return (x) /1;
   device_class: power
   state_class: measurement

 - platform: total_daily_energy        # Grid External Daily Energy
   name: 'SS Grid External Daily Energy'
   id: sunsynk_esphome_grid_external_daily_energy
   power_id: sunsynk_esphome_grid_external_power
   unit_of_measurement: 'kWh'
   icon: mdi:circle-slice-3
   state_class: total_increasing
   device_class: energy
   accuracy_decimals: 2
   restore: true
   filters:
      # Multiplication factor from W to kW is 0.001
      - multiply: 0.001

 - platform: modbus_controller          # 166 Aux Output Power
   modbus_controller_id: sunsynk_esphome
   name: "SS Aux Output Power"
   id: sunsynk_esphome_aux_output_power
   register_type: holding
   address: 166
   unit_of_measurement: "W"
   accuracy_decimals: 0
   filters: #GOOD
     - lambda: |-
           if (x > 32767) return (x - 65535) /1;
           else return (x) /1;
   device_class: power
   state_class: measurement

 - platform: modbus_controller          # 164 Inverter Output Current
   modbus_controller_id: sunsynk_esphome
   name: "SS Inverter Output Current"
   id: sunsynk_esphome_inverter_output_current
   register_type: holding
   address: 191
   unit_of_measurement: "A"
   accuracy_decimals: 1
   device_class: current
   state_class: measurement
   filters: #GOOD
    - lambda: |-
          if (x > 32767) return (0 - x + 65535) /100;
          else return (0 - x) /100;

 - platform: modbus_controller          # 191 Battery Output Current
   modbus_controller_id: sunsynk_esphome
   name: "SS 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
   filters: #GOOD
    - lambda: |-
          if (x > 32767) return (0 - x + 65535) /100;
          else return (0 - x) /100;

 - platform: modbus_controller          # 182 Battery Temperature
   modbus_controller_id: sunsynk_esphome
   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          # 090 DC Transformer Temperature
   modbus_controller_id: sunsynk_esphome
   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_esphome
   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          #076 Grid Import Day (Buy)
   modbus_controller_id: sunsynk_esphome
   name: "SS Grid Import Day (Buy)"
   id: sunsynk_esphome_grid_import_day
   register_type: holding
   address: 76
   unit_of_measurement: "kWh"
   accuracy_decimals: 0
   device_class: energy
   state_class: total_increasing
   filters: # GOOD
    - lambda: |-
           if (x > 32767) return (x - 65535) / 10;
           else return x /10;

 - platform: modbus_controller          # 070 Battery Charge Day
   modbus_controller_id: sunsynk_esphome
   name: "SS 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_esphome
   name: "SS 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          # 175 Inverter Output Power
   modbus_controller_id: sunsynk_esphome
   name: "SS Inverter Output Power"
   id: sunsynk_esphome_inverter_output_power
   register_type: holding
   address: 175
   unit_of_measurement: "W"
   accuracy_decimals: 1
   device_class: power
   filters: #GOOD
    - lambda: |-
           if (x > 32767) return (0 - x + 65535) /-1;
           else return (0 - x) /-1;

################################################ READ SETTINGS ################################################
 - platform: modbus_controller          # 250 Settings Timezone1
   modbus_controller_id: sunsynk_esphome
   name: "SSS 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;
          
 - platform: modbus_controller          # 251 Settings Timezone2
   modbus_controller_id: sunsynk_esphome
   name: "SSS 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;
 - platform: modbus_controller          # 252 Settings Timezone3
   modbus_controller_id: sunsynk_esphome
   name: "SSS 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;
 - platform: modbus_controller          # 253 Settings Timezone4
   modbus_controller_id: sunsynk_esphome
   name: "SSS Setting Timezone4"
   id: sunsynk_esphome_setting_timezone4
   register_type: holding
   skip_updates: ${settings_skipped_updates}
   address: 253
   filters: #GOOD
    - lambda: |-
           if (x > 32767) return (x - 65535) /1;
           else return (x) /1;
 - platform: modbus_controller          # 254 Settings Timezone5
   modbus_controller_id: sunsynk_esphome
   name: "SSS 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;
 - platform: modbus_controller          # 255 Settings Timezone6
   modbus_controller_id: sunsynk_esphome
   name: "SSS 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;

 - platform: modbus_controller          # 256 Settings Sell Mode Timezone1
   modbus_controller_id: sunsynk_esphome
   name: "SSS Setting Sell Mode Timezone1"
   id: sunsynk_esphome_setting_sellmode_timezone1
   register_type: holding
   skip_updates: ${settings_skipped_updates}
   address: 256
   filters: #GOOD
    - lambda: |-
           if (x > 32767) return (x - 65535) /1;
           else return (x) /1;
 - platform: modbus_controller          # 257 Settings Sell Mode Timezone2
   modbus_controller_id: sunsynk_esphome
   name: "SSS Setting Sell Mode Timezone2"
   id: sunsynk_esphome_setting_sellmode_timezone2
   register_type: holding
   skip_updates: ${settings_skipped_updates}
   address: 257
   filters: #GOOD
    - lambda: |-
           if (x > 32767) return (x - 65535) /1;
           else return (x) /1;
 - platform: modbus_controller          # 258 Settings Sell Mode Timezone3
   modbus_controller_id: sunsynk_esphome
   name: "SSS Setting Sell Mode Timezone3"
   id: sunsynk_esphome_setting_sellmode_timezone3
   register_type: holding
   skip_updates: ${settings_skipped_updates}
   address: 258
   filters: #GOOD
    - lambda: |-
           if (x > 32767) return (x - 65535) /1;
           else return (x) /1;
 - platform: modbus_controller          # 259 Settings Sell Mode Timezone4
   modbus_controller_id: sunsynk_esphome
   name: "SSS Setting Sell Mode Timezone4"
   id: sunsynk_esphome_setting_sellmode_timezone4
   register_type: holding
   skip_updates: ${settings_skipped_updates}
   address: 259
   filters: #GOOD
    - lambda: |-
           if (x > 32767) return (x - 65535) /1;
           else return (x) /1;
 - platform: modbus_controller          # 260 Settings Sell Mode Timezone5
   modbus_controller_id: sunsynk_esphome
   name: "SSS Setting Sell Mode Timezone5"
   id: sunsynk_esphome_setting_sellmode_timezone5
   register_type: holding
   skip_updates: ${settings_skipped_updates}
   address: 260
   filters: #GOOD
    - lambda: |-
           if (x > 32767) return (x - 65535) /1;
           else return (x) /1;
 - platform: modbus_controller          # 261 Settings Sell Mode Timezone6
   modbus_controller_id: sunsynk_esphome
   name: "SSS Setting Sell Mode Timezone6"
   id: sunsynk_esphome_setting_sellmode_timezone6
   register_type: holding
   skip_updates: ${settings_skipped_updates}
   address: 261
   filters: #GOOD
    - lambda: |-
           if (x > 32767) return (x - 65535) /1;
           else return (x) /1;
 - platform: modbus_controller          # 245 Settings Export Limit
   modbus_controller_id: sunsynk_esphome
   name: "SSS Setting Export Limit"
   id: sunsynk_esphome_setting_export_limit
   register_type: holding
   skip_updates: ${settings_skipped_updates}
   address: 245
   unit_of_measurement: "W"
   device_class: power
   state_class: measurement
   filters: #GOOD
    - lambda: |-
           if (x > 32767) return (x - 65535) /1;
           else return (x) /1;
           
 - platform: modbus_controller          # 217 Settings Battery Shutdown
   modbus_controller_id: sunsynk_esphome
   name: "SSS Setting Battery Shutdown"
   id: sunsynk_esphome_setting_battery_shutdown
   register_type: holding
   skip_updates: ${settings_skipped_updates}
   address: 217
   unit_of_measurement: "%"
   device_class: battery
   state_class: measurement
   filters: #GOOD
    - lambda: |-
           if (x > 32767) return (x - 65535) /1;
           else return (x) /1;

 - platform: modbus_controller          # 219 Settings Battery Low
   modbus_controller_id: sunsynk_esphome
   name: "SSS Setting Battery Low"
   id: sunsynk_esphome_setting_battery_low
   register_type: holding
   skip_updates: ${settings_skipped_updates}
   address: 219
   unit_of_measurement: "%"
   device_class: battery
   state_class: measurement
   filters: #GOOD
    - lambda: |-
           if (x > 32767) return (x - 65535) /1;
           else return (x) /1;

 - platform: modbus_controller          # 218 Settings Battery Restart
   modbus_controller_id: sunsynk_esphome
   name: "SSS Setting Battery Restart"
   id: sunsynk_esphome_setting_battery_restart
   register_type: holding
   skip_updates: ${settings_skipped_updates}
   address: 218
   unit_of_measurement: "%"
   device_class: battery
   state_class: measurement
   filters: #GOOD
    - lambda: |-
           if (x > 32767) return (x - 65535) /1;
           else return (x) /1;

 - platform: modbus_controller          # 210 Settings Battery Max Charge Current
   modbus_controller_id: sunsynk_esphome
   name: "SSS Setting Battery Max Charge Current"
   id: sunsynk_esphome_setting_battery_max_charge_current
   register_type: holding
   skip_updates: ${settings_skipped_updates}
   address: 210
   device_class: current
   state_class: measurement
   unit_of_measurement: "A"   
   filters: #GOOD
    - lambda: |-
           if (x > 32767) return (x - 65535) /1;
           else return (x) /1;

 - platform: modbus_controller          # 211 Settings Battery Max Discharge Current
   modbus_controller_id: sunsynk_esphome
   name: "SSS Setting Max Discharge Current"
   id: sunsynk_esphome_setting_battery_max_discharge_current
   register_type: holding
   skip_updates: ${settings_skipped_updates}
   address: 211
   device_class: current
   state_class: measurement
   unit_of_measurement: "A"   
   filters: #GOOD
    - lambda: |-
           if (x > 32767) return (x - 65535) /1;
           else return (x) /1;
           
 - platform: modbus_controller          # 230 Settings Grid Charge Current
   modbus_controller_id: sunsynk_esphome
   name: "SSS Setting Grid Charge Current"
   id: sunsynk_esphome_setting_grid_charge_current
   register_type: holding
   skip_updates: ${settings_skipped_updates}
   address: 230
   device_class: current
   state_class: measurement
   unit_of_measurement: "A"   
   filters: #GOOD
    - lambda: |-
           if (x > 32767) return (x - 65535) /1;
           else return (x) /1;     

 - platform: total_daily_energy
   name: 'SS Inverter Daily Energy'
   id: sunsynk_esphome_inverter_daily_energy
   power_id: sunsynk_esphome_inverter_output_power
   unit_of_measurement: 'kWh'
   icon: mdi:circle-slice-3
   state_class: total_increasing
   device_class: energy
   accuracy_decimals: 2
   restore: true
   filters:
      # Multiplication factor from W to kW is 0.001
      - multiply: 0.001

############################################### BINARY SENSORS ###############################################
binary_sensor:

 - platform: status
   name: Status ${device_name}

 - platform: modbus_controller          # 194 Grid Connected Status
   modbus_controller_id: sunsynk_esphome
   name: "SS Grid Connected Status"
   id: sunsynk_esphome_grid_connected_status
   register_type: holding
   address: 194



############################################### BINARY SENSORS SETTINGS ###############################################  



 - platform: modbus_controller          # 244 Settings Load Limit Enabled
   modbus_controller_id: sunsynk_esphome
   name: "SSS Setting Load Limit Enabled"
   id: sunsynk_esphome_setting_load_limit2
   register_type: holding
   skip_updates: ${settings_skipped_updates}
   address: 244


 - platform: modbus_controller          # 247 Settings Solar Export Enabled
   modbus_controller_id: sunsynk_esphome
   name: "SSS Setting Solar Export Enabled"
   id: sunsynk_esphome_setting_solar_export_enabled
   register_type: holding
   skip_updates: ${settings_skipped_updates}
   address: 247

 - platform: modbus_controller          # 232 Settings Battery Grid Charge Enabled
   modbus_controller_id: sunsynk_esphome
   name: "SSS Setting Battery Grid Charge Enabled"
   id: sunsynk_esphome_setting_battery_grid_charge_enabled
   register_type: holding
   skip_updates: ${settings_skipped_updates}
   address: 232


############################################### TEXT SENSORS SETTINGS ############################################### 
text_sensor:
 - platform: wifi_info
   ssid:
      name: SSID ${device_name}
   bssid:
      name: BSSID ${device_name}
      id: bssid_id

 - platform: modbus_controller          # 243 Settings Energy Management Model (PL)
   modbus_controller_id: sunsynk_esphome
   name: "SSS Setting Energy Management Model"
   id: sunsynk_esphome_setting_energy_management_model
   register_type: holding
   skip_updates: ${settings_skipped_updates}
   raw_encode: HEXBYTES
   address: 243
   lambda: |-
      uint16_t value = modbus_controller::word_from_hex_str(x, 0);
      switch (value) {
        case 0: return std::string("Battery Priority Mode");
        case 1: return std::string("Load First Mode");
        default: return std::string("Unknown");
      }
 - platform: modbus_controller          # 059 Overall State
   modbus_controller_id: sunsynk_esphome
   name: "SS Overall State"
   id: sunsynk_esphome_overall_state
   register_type: holding
   skip_updates: ${settings_skipped_updates}
   raw_encode: HEXBYTES
   address: 59
   lambda: |- # It is not clear what each of these states mean. TODO Fill in the string values once known
      uint16_t value = modbus_controller::word_from_hex_str(x, 0);
      switch (value) {
        case 0: return std::string("0");
        case 1: return std::string("1");
        case 2: return std::string("2");
        case 3: return std::string("3");
        case 4: return std::string("4");
        case 5: return std::string("5");
        default: return std::string("Unknown");
      }

I hope it helps!

Link to comment
Share on other sites

Here is the Github by @Klatremisfor the ESPhome for the 12K DEYE inverter whose Modbus registers are totally different to the Sunsynk 8kw & 5kw inverters.

Not sure which DEYE/Sunynk models Modbus registers are compatible, maybe something to do for someone with some spare time to work out 🙂 

 

https://github.com/klatremis/esphome-for-deye/ 

Edited by Sc00bs
Link to comment
Share on other sites

Many thanks CorneSchutte and Sc00bs for your replies.

In a short analysis, looks like your code (CorneShutte) matches my Deye 5Kw registers.

Received today the TTL-RS485 adapter, so later today is time for bricolage :)

One question:

How is it managed the registers that contain two words? for example the Total Grid Buy Power (KWh) contains two registers (78 for low word and 80 for high word) according to the Modbus doc. I understand that the final value is a combination of these two values, right?

Is this being managed by the ESPHome code somehow?

Screenshot 2023-03-02 163108.png

Link to comment
Share on other sites

Martinisonline - the ESPHome code (as originally written by sjlouw and refined by jacauc, with the update mod by slipx), only has the following for Grid Import Total (Buy) and it works fine for me:

 - platform: modbus_controller          # 78 Grid Import Total (Buy)
   modbus_controller_id: sunsynk_esphome
   name: "SS Grid Import Total (Buy)"
   id: sunsynk_esphome_grid_import_total_buy
   register_type: holding
   address: 78
   unit_of_measurement: "kWh"
   accuracy_decimals: 0
   device_class: energy
   state_class: total_increasing
   filters: #GOOD
    - lambda: |-
           x = x / -1;
           if (x > 32767) return (0 - x + 65535) /1;
           else return (0 - x) /1;

Thus this ESPHome implementation therefore does not use the 80 register as far as I can tell? See if it works for you?

For me, the code I inherited from jacauc etc worked immediately - the challenge was to identify the correct 2 wires in the Ethernet cable to connect to the TTL-RS485, but once I had done that, it simply just worked. I had recently tidied it up and put the ESP32 and TTL-RS485 in a nice case with some ventilation slots and have had no issues. 

Link to comment
Share on other sites

CorneSchutte, what I'm thinking is:

The registers have a 16bit length, which means they can handle values from 0 up to 65535. On this specific register, one unit represents 0.1KWh so the maximum value the register can record is 6.553,5 KWh. So, when this value is reached, the register goes to 0 and the "high word" or the register 80 increments.

Saying this, it will work fine until it reaches the 6,55 MWh. After that it will reset to 0 if we don't take into account the register number 80!

Maybe I'm wrong, but this is my understanding :)

Link to comment
Share on other sites

21 hours ago, CorneSchutte said:

"My" ESPHome code, which is a combination of others work before me.

But I believe the Deye registers are completely different?

esphome:
  name: "sunsynk"

preferences:
  flash_write_interval: 5min

esp32:
  board: esp32dev
  framework:
    type: arduino

#################################### GLOBALS ####################################
substitutions:
  modbus_update_interval: "3s"
  settings_skipped_updates: "10"
  query_throttle: "50ms"
  device_name: sunsynk
  friendly_name: SunSynk Link

#################################### STATIC SECTION ####################################
wifi:
  ssid: XXXX
  password: XXX
  fast_connect: true

ota:
  safe_mode: true
  reboot_timeout: 10min
  num_attempts: 5

web_server:
  port: 80

#captive_portal:

# Enable logging
#logger:
#  baud_rate: 0

# Enable Home Assistant API
api:


# https://esphome.io/components/time.html#home-assistant-time-source
time:
  - platform: homeassistant
    id: homeassistant_time

#################################### STATIC SECTION ####################################

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_esphome
   address: 0x01
   modbus_id: sunsynk_modbus
   setup_priority: -10
   update_interval: ${modbus_update_interval}
   command_throttle: ${query_throttle}

switch:
  - platform: restart
    name: "${friendly_name} Restart"

  - platform: modbus_controller      # 248 Toggle System Timer
    use_write_multiple: true
    modbus_controller_id: sunsynk_esphome
    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          # 274 Toggle Grid Charge Timezone1
    use_write_multiple: true
    modbus_controller_id: sunsynk_esphome
    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_esphome
    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_esphome
    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_esphome
    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_esphome
    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_esphome
    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_esphome
    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_esphome
    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_esphome
    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_esphome
    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_esphome
    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_esphome
    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  

sensor: 
   
 - platform: wifi_signal
   name: WiFi signal ${device_name} 
   id: wifi_s
   internal: true
   update_interval: 60s
 - platform: template
   name: Wifi ${device_name}
   unit_of_measurement: '%'
   accuracy_decimals: 0
   icon: "mdi:wifi"
   lambda: |-
        if (id(wifi_s).state < -92.0)
          return 1.0;
        if (id(wifi_s).state > -21.0)
          return 100.0;
        else
          return round(( -0.0154 * id(wifi_s).state * id(wifi_s).state ) - ( 0.3794 * id(wifi_s).state ) + 98.182 );
   update_interval: 60s
 - platform: uptime
   filters:
      - lambda: return x / 3600;
   unit_of_measurement: hours
   name: ${device_name} Uptime

 - platform: modbus_controller          #72 Battery Charge Total
   modbus_controller_id: sunsynk_esphome
   name: "SS Battery Charge Total"
   id: sunsynk_esphome_battery_charge_total
   register_type: holding
   address: 72
   unit_of_measurement: "kWh"
   accuracy_decimals: 1
   device_class: energy
   state_class: total_increasing
   filters:
    - lambda: |-
           x = x / -1;
           if (x > 32767) return (0 - x + 65535) /10;
           else return (0 - x) /10;
 - platform: modbus_controller          #74 Battery Discharge Total
   modbus_controller_id: sunsynk_esphome
   name: "SS Battery Discharge Total"
   id: sunsynk_esphome_battery_discharge_total
   register_type: holding
   address: 74
   unit_of_measurement: "kWh"
   accuracy_decimals: 0
   device_class: energy
   state_class: total_increasing
   filters:
    - lambda: |-
           if (x > 32767) return (x - 65535) /10;
           else return (x) /10;

 - platform: modbus_controller          # 81 Grid Export Total (Sell)
   modbus_controller_id: sunsynk_esphome
   name: "SS Grid Export Total (Sell)"
   id: sunsynk_esphome_grid_export_total_sell
   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          # 78 Grid Import Total (Buy)
   modbus_controller_id: sunsynk_esphome
   name: "SS Grid Import Total (Buy)"
   id: sunsynk_esphome_grid_import_total_buy
   register_type: holding
   address: 78
   unit_of_measurement: "kWh"
   accuracy_decimals: 0
   device_class: energy
   state_class: total_increasing
   filters: #GOOD
    - lambda: |-
           x = x / -1;
           if (x > 32767) return (0 - x + 65535) /1;
           else return (0 - x) /1;
  
 - platform: modbus_controller          # 85 Load Power Total
   modbus_controller_id: sunsynk_esphome
   name: "SS Load Power Total"
   id: sunsynk_esphome_load_power_total
   register_type: holding
   address: 85
   unit_of_measurement: "kWh"
   accuracy_decimals: 0
   device_class: energy
   state_class: total_increasing
   filters: #GOOD
    - lambda: |-
           if (x > 32767) return (0 - x + 65535) /1;
           else return (0 - x) /1;
  
 - platform: modbus_controller
   modbus_controller_id: sunsynk_esphome
   name: "SS Total PV Power (kWh)"
   id: sunsynk_esphome_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          # 169 Grid Power
   modbus_controller_id: sunsynk_esphome
   name: "SS Grid Power"
   id: sunsynk_esphome_grid_power
   register_type: holding
   address: 169
   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          # 178 Load Power
   modbus_controller_id: sunsynk_esphome
   name: "SS Load Power"
   id: sunsynk_esphome_load_power
   register_type: holding
   address: 178
   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       # 186 PV1 Power
   modbus_controller_id: sunsynk_esphome
   name: "SS PV1 Power"
   id: sunsynk_esphome_pv1_power
   register_type: holding
   address: 186
   unit_of_measurement: "W"
   accuracy_decimals: 2
   device_class: power
   state_class: measurement
   
 - platform: modbus_controller       # 187 PV2 Power
   modbus_controller_id: sunsynk_esphome
   name: "SS PV2 Power"
   id: sunsynk_esphome_pv2_power
   register_type: holding
   address: 187
   unit_of_measurement: "W"
   accuracy_decimals: 2
   device_class: power
   state_class: measurement

 - platform: template           # PV Total Power
   name: "SS PV Power"
   id: sunsynk_esphome_pv_power
   unit_of_measurement: "W"
   accuracy_decimals: 2
   device_class: power
   state_class: measurement
   update_interval: 15s
   lambda: |-
     return (id(sunsynk_esphome_pv1_power).state + id(sunsynk_esphome_pv2_power).state);

 - platform: total_daily_energy     # PV Daily Energy
   name: 'SS PV Daily Energy'
   id: sunsynk_esphome_pv_daily_energy
   power_id: sunsynk_esphome_pv_power
   unit_of_measurement: 'kWh'
   icon: mdi:circle-slice-3
   state_class: total_increasing
   device_class: energy
   accuracy_decimals: 2
   restore: true
   filters:
      # Multiplication factor from W to kW is 0.001
      - multiply: 0.001

 - platform: modbus_controller  # 190 Battery Output
   modbus_controller_id: sunsynk_esphome
   name: "SS Battery Output Power"
   id: sunsynk_esphome_battery_output_power
   register_type: holding
   address: 190
   unit_of_measurement: "W"
   accuracy_decimals: 2
   device_class: power
   state_class: measurement
   filters: #GOOD
    - lambda: |-
           if (x > 32767) return (x - 65535) /1;
           else return (x) /1;


 - platform: modbus_controller          # 184 Battery SOC
   modbus_controller_id: sunsynk_esphome
   name: "SS Battery SOC"
   id: sunsynk_esphome_battery_soc
   register_type: holding
   address: 184
   unit_of_measurement: "%"
   accuracy_decimals: 0
   device_class: battery
   state_class: measurement
   filters: #GOOD
    - lambda: |-
           if (x > 32767) return (x - 65535) /1;
           else return (x) /1;

 - platform: modbus_controller          # 184 Battery Usable SOC
   modbus_controller_id: sunsynk_esphome
   name: "SS Battery Usable SOC"
   id: sunsynk_esphome_battery_usable_soc
   register_type: holding
   address: 184
   unit_of_measurement: "%"
   accuracy_decimals: 0
   device_class: battery
   state_class: measurement
   filters: #GOOD
   # battery normally charges to 99%, shutdown level is 20%, so subtract 19 from value and calculate as percentage divided by 80
    - lambda: |-
       
           if (x > 32767) {
              int y = ((((x - 65535) -19) /80) *100) /1; 
              if (y > 100) return 100;
              return y;
           }
           else {
              int y = (((x -19) /80) *100) /1;
              if (y > 100) return 100;
              return y;
           }
          
 - platform: modbus_controller          # 216 Battery Charging Efficiency
   modbus_controller_id: sunsynk_esphome
   name: "SS Battery Charging Efficiency"
   id: sunsynk_esphome_battery_charging_efficiency
   register_type: holding
   address: 216
   unit_of_measurement: "%"
   accuracy_decimals: 1
   device_class: battery
   state_class: measurement
   filters: #GOOD
    - lambda: |-
           if (x > 32767) return (x - 65535) /10;
           else return (x) /10;

# - platform: modbus_controller          # 013 Firmware Control Board
#   modbus_controller_id: sunsynk_esphome
#   name: "SS Firmware Control Board"
#   id: sunsynk_esphome_firmware_control_board
#   register_type: holding
#   address: 13

# - platform: modbus_controller          # 013 Firmware Comms Board
#   modbus_controller_id: sunsynk_esphome
#   name: "SS Firmware Comms Board"
#   id: sunsynk_esphome_firmware_comms_board
#   register_type: holding
#   address: 14

 - platform: modbus_controller          # 079 Grid Frequency
   modbus_controller_id: sunsynk_esphome
   name: "SS 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          # 192 Load Frequency
   modbus_controller_id: sunsynk_esphome
   name: "SS 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          # 154 Grid Inverter Voltage
   modbus_controller_id: sunsynk_esphome
   name: "SS 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         # 150 Grid Voltage
   modbus_controller_id: sunsynk_esphome
   name: "SS Grid Voltage"
   id: sunsynk_esphome_grid_voltage
   register_type: holding
   address: 150
   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         # 154 Grid Inverter Voltage
   modbus_controller_id: sunsynk_esphome
   name: "SS Grid Voltage"
   id: sunsynk_inverter_grid_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          # 183 Battery Voltage
   modbus_controller_id: sunsynk_esphome
   name: "SS 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          # 312 Battery Charge Voltage
   modbus_controller_id: sunsynk_esphome
   name: "SS Battery Charge Voltage"
   id: sunsynk_esphome_battery_charge_voltage
   register_type: holding
   address: 312
   unit_of_measurement: "V"
   accuracy_decimals: 1
   filters: #GOOD
     - lambda: |-
           x = x / -1;
           if (x > 32767) return (0 - x + 65535) /100;
           else return (0 - x) /100;
   device_class: voltage
   state_class: measurement

 - platform: modbus_controller          # 167 Grid Inverter Load
   modbus_controller_id: sunsynk_esphome
   name: "SS Grid Inverter Load"
   id: sunsynk_esphome_grid_inverter_load
   register_type: holding
   address: 167
   unit_of_measurement: "W"
   accuracy_decimals: 0
   filters: #GOOD
     - lambda: |-
           if (x > 32767) return (x - 65535) /1;
           else return (x) /1;
   device_class: power
   state_class: measurement

 - platform: modbus_controller          # 172 Grid External Power
   modbus_controller_id: sunsynk_esphome
   name: "SS Grid External Power"
   id: sunsynk_esphome_grid_external_power
   register_type: holding
   address: 172
   unit_of_measurement: "W"
   accuracy_decimals: 0
   filters: #GOOD
     - lambda: |-
           if (x > 32767) return (x - 65535) /1;
           else return (x) /1;
   device_class: power
   state_class: measurement

 - platform: total_daily_energy        # Grid External Daily Energy
   name: 'SS Grid External Daily Energy'
   id: sunsynk_esphome_grid_external_daily_energy
   power_id: sunsynk_esphome_grid_external_power
   unit_of_measurement: 'kWh'
   icon: mdi:circle-slice-3
   state_class: total_increasing
   device_class: energy
   accuracy_decimals: 2
   restore: true
   filters:
      # Multiplication factor from W to kW is 0.001
      - multiply: 0.001

 - platform: modbus_controller          # 166 Aux Output Power
   modbus_controller_id: sunsynk_esphome
   name: "SS Aux Output Power"
   id: sunsynk_esphome_aux_output_power
   register_type: holding
   address: 166
   unit_of_measurement: "W"
   accuracy_decimals: 0
   filters: #GOOD
     - lambda: |-
           if (x > 32767) return (x - 65535) /1;
           else return (x) /1;
   device_class: power
   state_class: measurement

 - platform: modbus_controller          # 164 Inverter Output Current
   modbus_controller_id: sunsynk_esphome
   name: "SS Inverter Output Current"
   id: sunsynk_esphome_inverter_output_current
   register_type: holding
   address: 191
   unit_of_measurement: "A"
   accuracy_decimals: 1
   device_class: current
   state_class: measurement
   filters: #GOOD
    - lambda: |-
          if (x > 32767) return (0 - x + 65535) /100;
          else return (0 - x) /100;

 - platform: modbus_controller          # 191 Battery Output Current
   modbus_controller_id: sunsynk_esphome
   name: "SS 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
   filters: #GOOD
    - lambda: |-
          if (x > 32767) return (0 - x + 65535) /100;
          else return (0 - x) /100;

 - platform: modbus_controller          # 182 Battery Temperature
   modbus_controller_id: sunsynk_esphome
   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          # 090 DC Transformer Temperature
   modbus_controller_id: sunsynk_esphome
   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_esphome
   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          #076 Grid Import Day (Buy)
   modbus_controller_id: sunsynk_esphome
   name: "SS Grid Import Day (Buy)"
   id: sunsynk_esphome_grid_import_day
   register_type: holding
   address: 76
   unit_of_measurement: "kWh"
   accuracy_decimals: 0
   device_class: energy
   state_class: total_increasing
   filters: # GOOD
    - lambda: |-
           if (x > 32767) return (x - 65535) / 10;
           else return x /10;

 - platform: modbus_controller          # 070 Battery Charge Day
   modbus_controller_id: sunsynk_esphome
   name: "SS 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_esphome
   name: "SS 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          # 175 Inverter Output Power
   modbus_controller_id: sunsynk_esphome
   name: "SS Inverter Output Power"
   id: sunsynk_esphome_inverter_output_power
   register_type: holding
   address: 175
   unit_of_measurement: "W"
   accuracy_decimals: 1
   device_class: power
   filters: #GOOD
    - lambda: |-
           if (x > 32767) return (0 - x + 65535) /-1;
           else return (0 - x) /-1;

################################################ READ SETTINGS ################################################
 - platform: modbus_controller          # 250 Settings Timezone1
   modbus_controller_id: sunsynk_esphome
   name: "SSS 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;
          
 - platform: modbus_controller          # 251 Settings Timezone2
   modbus_controller_id: sunsynk_esphome
   name: "SSS 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;
 - platform: modbus_controller          # 252 Settings Timezone3
   modbus_controller_id: sunsynk_esphome
   name: "SSS 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;
 - platform: modbus_controller          # 253 Settings Timezone4
   modbus_controller_id: sunsynk_esphome
   name: "SSS Setting Timezone4"
   id: sunsynk_esphome_setting_timezone4
   register_type: holding
   skip_updates: ${settings_skipped_updates}
   address: 253
   filters: #GOOD
    - lambda: |-
           if (x > 32767) return (x - 65535) /1;
           else return (x) /1;
 - platform: modbus_controller          # 254 Settings Timezone5
   modbus_controller_id: sunsynk_esphome
   name: "SSS 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;
 - platform: modbus_controller          # 255 Settings Timezone6
   modbus_controller_id: sunsynk_esphome
   name: "SSS 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;

 - platform: modbus_controller          # 256 Settings Sell Mode Timezone1
   modbus_controller_id: sunsynk_esphome
   name: "SSS Setting Sell Mode Timezone1"
   id: sunsynk_esphome_setting_sellmode_timezone1
   register_type: holding
   skip_updates: ${settings_skipped_updates}
   address: 256
   filters: #GOOD
    - lambda: |-
           if (x > 32767) return (x - 65535) /1;
           else return (x) /1;
 - platform: modbus_controller          # 257 Settings Sell Mode Timezone2
   modbus_controller_id: sunsynk_esphome
   name: "SSS Setting Sell Mode Timezone2"
   id: sunsynk_esphome_setting_sellmode_timezone2
   register_type: holding
   skip_updates: ${settings_skipped_updates}
   address: 257
   filters: #GOOD
    - lambda: |-
           if (x > 32767) return (x - 65535) /1;
           else return (x) /1;
 - platform: modbus_controller          # 258 Settings Sell Mode Timezone3
   modbus_controller_id: sunsynk_esphome
   name: "SSS Setting Sell Mode Timezone3"
   id: sunsynk_esphome_setting_sellmode_timezone3
   register_type: holding
   skip_updates: ${settings_skipped_updates}
   address: 258
   filters: #GOOD
    - lambda: |-
           if (x > 32767) return (x - 65535) /1;
           else return (x) /1;
 - platform: modbus_controller          # 259 Settings Sell Mode Timezone4
   modbus_controller_id: sunsynk_esphome
   name: "SSS Setting Sell Mode Timezone4"
   id: sunsynk_esphome_setting_sellmode_timezone4
   register_type: holding
   skip_updates: ${settings_skipped_updates}
   address: 259
   filters: #GOOD
    - lambda: |-
           if (x > 32767) return (x - 65535) /1;
           else return (x) /1;
 - platform: modbus_controller          # 260 Settings Sell Mode Timezone5
   modbus_controller_id: sunsynk_esphome
   name: "SSS Setting Sell Mode Timezone5"
   id: sunsynk_esphome_setting_sellmode_timezone5
   register_type: holding
   skip_updates: ${settings_skipped_updates}
   address: 260
   filters: #GOOD
    - lambda: |-
           if (x > 32767) return (x - 65535) /1;
           else return (x) /1;
 - platform: modbus_controller          # 261 Settings Sell Mode Timezone6
   modbus_controller_id: sunsynk_esphome
   name: "SSS Setting Sell Mode Timezone6"
   id: sunsynk_esphome_setting_sellmode_timezone6
   register_type: holding
   skip_updates: ${settings_skipped_updates}
   address: 261
   filters: #GOOD
    - lambda: |-
           if (x > 32767) return (x - 65535) /1;
           else return (x) /1;
 - platform: modbus_controller          # 245 Settings Export Limit
   modbus_controller_id: sunsynk_esphome
   name: "SSS Setting Export Limit"
   id: sunsynk_esphome_setting_export_limit
   register_type: holding
   skip_updates: ${settings_skipped_updates}
   address: 245
   unit_of_measurement: "W"
   device_class: power
   state_class: measurement
   filters: #GOOD
    - lambda: |-
           if (x > 32767) return (x - 65535) /1;
           else return (x) /1;
           
 - platform: modbus_controller          # 217 Settings Battery Shutdown
   modbus_controller_id: sunsynk_esphome
   name: "SSS Setting Battery Shutdown"
   id: sunsynk_esphome_setting_battery_shutdown
   register_type: holding
   skip_updates: ${settings_skipped_updates}
   address: 217
   unit_of_measurement: "%"
   device_class: battery
   state_class: measurement
   filters: #GOOD
    - lambda: |-
           if (x > 32767) return (x - 65535) /1;
           else return (x) /1;

 - platform: modbus_controller          # 219 Settings Battery Low
   modbus_controller_id: sunsynk_esphome
   name: "SSS Setting Battery Low"
   id: sunsynk_esphome_setting_battery_low
   register_type: holding
   skip_updates: ${settings_skipped_updates}
   address: 219
   unit_of_measurement: "%"
   device_class: battery
   state_class: measurement
   filters: #GOOD
    - lambda: |-
           if (x > 32767) return (x - 65535) /1;
           else return (x) /1;

 - platform: modbus_controller          # 218 Settings Battery Restart
   modbus_controller_id: sunsynk_esphome
   name: "SSS Setting Battery Restart"
   id: sunsynk_esphome_setting_battery_restart
   register_type: holding
   skip_updates: ${settings_skipped_updates}
   address: 218
   unit_of_measurement: "%"
   device_class: battery
   state_class: measurement
   filters: #GOOD
    - lambda: |-
           if (x > 32767) return (x - 65535) /1;
           else return (x) /1;

 - platform: modbus_controller          # 210 Settings Battery Max Charge Current
   modbus_controller_id: sunsynk_esphome
   name: "SSS Setting Battery Max Charge Current"
   id: sunsynk_esphome_setting_battery_max_charge_current
   register_type: holding
   skip_updates: ${settings_skipped_updates}
   address: 210
   device_class: current
   state_class: measurement
   unit_of_measurement: "A"   
   filters: #GOOD
    - lambda: |-
           if (x > 32767) return (x - 65535) /1;
           else return (x) /1;

 - platform: modbus_controller          # 211 Settings Battery Max Discharge Current
   modbus_controller_id: sunsynk_esphome
   name: "SSS Setting Max Discharge Current"
   id: sunsynk_esphome_setting_battery_max_discharge_current
   register_type: holding
   skip_updates: ${settings_skipped_updates}
   address: 211
   device_class: current
   state_class: measurement
   unit_of_measurement: "A"   
   filters: #GOOD
    - lambda: |-
           if (x > 32767) return (x - 65535) /1;
           else return (x) /1;
           
 - platform: modbus_controller          # 230 Settings Grid Charge Current
   modbus_controller_id: sunsynk_esphome
   name: "SSS Setting Grid Charge Current"
   id: sunsynk_esphome_setting_grid_charge_current
   register_type: holding
   skip_updates: ${settings_skipped_updates}
   address: 230
   device_class: current
   state_class: measurement
   unit_of_measurement: "A"   
   filters: #GOOD
    - lambda: |-
           if (x > 32767) return (x - 65535) /1;
           else return (x) /1;     

 - platform: total_daily_energy
   name: 'SS Inverter Daily Energy'
   id: sunsynk_esphome_inverter_daily_energy
   power_id: sunsynk_esphome_inverter_output_power
   unit_of_measurement: 'kWh'
   icon: mdi:circle-slice-3
   state_class: total_increasing
   device_class: energy
   accuracy_decimals: 2
   restore: true
   filters:
      # Multiplication factor from W to kW is 0.001
      - multiply: 0.001

############################################### BINARY SENSORS ###############################################
binary_sensor:

 - platform: status
   name: Status ${device_name}

 - platform: modbus_controller          # 194 Grid Connected Status
   modbus_controller_id: sunsynk_esphome
   name: "SS Grid Connected Status"
   id: sunsynk_esphome_grid_connected_status
   register_type: holding
   address: 194



############################################### BINARY SENSORS SETTINGS ###############################################  



 - platform: modbus_controller          # 244 Settings Load Limit Enabled
   modbus_controller_id: sunsynk_esphome
   name: "SSS Setting Load Limit Enabled"
   id: sunsynk_esphome_setting_load_limit2
   register_type: holding
   skip_updates: ${settings_skipped_updates}
   address: 244


 - platform: modbus_controller          # 247 Settings Solar Export Enabled
   modbus_controller_id: sunsynk_esphome
   name: "SSS Setting Solar Export Enabled"
   id: sunsynk_esphome_setting_solar_export_enabled
   register_type: holding
   skip_updates: ${settings_skipped_updates}
   address: 247

 - platform: modbus_controller          # 232 Settings Battery Grid Charge Enabled
   modbus_controller_id: sunsynk_esphome
   name: "SSS Setting Battery Grid Charge Enabled"
   id: sunsynk_esphome_setting_battery_grid_charge_enabled
   register_type: holding
   skip_updates: ${settings_skipped_updates}
   address: 232


############################################### TEXT SENSORS SETTINGS ############################################### 
text_sensor:
 - platform: wifi_info
   ssid:
      name: SSID ${device_name}
   bssid:
      name: BSSID ${device_name}
      id: bssid_id

 - platform: modbus_controller          # 243 Settings Energy Management Model (PL)
   modbus_controller_id: sunsynk_esphome
   name: "SSS Setting Energy Management Model"
   id: sunsynk_esphome_setting_energy_management_model
   register_type: holding
   skip_updates: ${settings_skipped_updates}
   raw_encode: HEXBYTES
   address: 243
   lambda: |-
      uint16_t value = modbus_controller::word_from_hex_str(x, 0);
      switch (value) {
        case 0: return std::string("Battery Priority Mode");
        case 1: return std::string("Load First Mode");
        default: return std::string("Unknown");
      }
 - platform: modbus_controller          # 059 Overall State
   modbus_controller_id: sunsynk_esphome
   name: "SS Overall State"
   id: sunsynk_esphome_overall_state
   register_type: holding
   skip_updates: ${settings_skipped_updates}
   raw_encode: HEXBYTES
   address: 59
   lambda: |- # It is not clear what each of these states mean. TODO Fill in the string values once known
      uint16_t value = modbus_controller::word_from_hex_str(x, 0);
      switch (value) {
        case 0: return std::string("0");
        case 1: return std::string("1");
        case 2: return std::string("2");
        case 3: return std::string("3");
        case 4: return std::string("4");
        case 5: return std::string("5");
        default: return std::string("Unknown");
      }

I hope it helps!

I was playing with some text sensors to get the timezone to display as 02:00 as opposed to 200 etc. You can try them if it helps

 

text_sensor:
  - platform: template
    name: "Program1_test"
    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: "Program2_test"
    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);

image.png.1510cd4cd9bed228a0fb2124ed0f379b.png

Edited by slipx
Link to comment
Share on other sites

On 2023/02/24 at 5:06 PM, Rynoster said:

Thought I would also contribute with something small. Not as impressive as what some of the others here but a contribution nonetheless.

The GUI for Sunsynk System Mode, or lack thereof, has really been annoying me, so I put this together. It needed to be easy to read to quickly understand what's going on, and also easy for the wife to change if needed.

It requires the lovelace-layout-card to work. For my purposes, it's also a separate view.

image.thumb.png.38cc7e274ced573b274df00fe62bcac3.png

views:
  - theme: Backend-selected
    title: Grid layout
    type: custom:grid-layout
    layout:
      grid-template-columns: 3fr 2fr 2fr 3fr
      grid-template-rows: auto
      grid-template-areas: |
        ". header header ."
        ". system priority ."
        ". prog1 prog2 ."
        ". prog3 prog4 ."
        ". prog5 prog6 ."
      mediaquery:
        '(max-width: 800px)':
          grid-template-columns: auto
          grid-template-areas: |
            "header"
            "system"
            "priority"
            "prog1"
            "prog2"
            "prog3"
            "prog4"
            "prog5"
            "prog6"
    badges: []
    cards:
      - type: entities
        entities:
          - entity: select.system_mode
        show_header_toggle: false
        view_layout:
          grid-area: system
      - type: vertical-stack
        cards:
          - type: custom:mushroom-template-card
            primary: Program 1
            secondary: >-
              {{ states("select.prog1_time") }} - {{ states("select.prog2_time")
              }}
            icon: mdi:timer
            multiline_secondary: false
            badge_icon: mdi:lightning-bolt
            icon_color: blue
            badge_color: green
            fill_container: false
          - type: horizontal-stack
            cards:
              - type: entities
                entities:
                  - entity: select.prog1_time
              - type: entities
                entities:
                  - entity: select.prog1_charge
          - type: entities
            entities:
              - type: custom:slider-entity-row
                entity: number.prog1_power
                name: Power
                grow: true
              - type: custom:slider-entity-row
                entity: number.prog1_capacity
                name: Battery SOC
        view_layout:
          grid-area: prog1
      - type: vertical-stack
        cards:
          - type: custom:mushroom-template-card
            primary: Program 2
            secondary: >-
              {{ states("select.prog2_time") }} - {{ states("select.prog3_time")
              }}
            icon: mdi:timer
            multiline_secondary: false
            badge_icon: mdi:lightning-bolt
            icon_color: blue
            badge_color: green
            fill_container: false
          - type: horizontal-stack
            cards:
              - type: entities
                entities:
                  - entity: select.prog2_time
              - type: entities
                entities:
                  - entity: select.prog2_charge
          - type: entities
            entities:
              - type: custom:slider-entity-row
                entity: number.prog2_power
                name: Power
                grow: true
              - type: custom:slider-entity-row
                entity: number.prog2_capacity
                name: Battery SOC
        view_layout:
          grid-area: prog2
      - type: vertical-stack
        cards:
          - type: custom:mushroom-template-card
            primary: Program 3
            secondary: >-
              {{ states("select.prog3_time") }} - {{ states("select.prog4_time")
              }}
            icon: mdi:timer
            multiline_secondary: false
            badge_icon: mdi:lightning-bolt
            icon_color: blue
            badge_color: green
            fill_container: false
          - type: horizontal-stack
            cards:
              - type: entities
                entities:
                  - entity: select.prog3_time
              - type: entities
                entities:
                  - entity: select.prog3_charge
          - type: entities
            entities:
              - type: custom:slider-entity-row
                entity: number.prog3_power
                name: Power
                grow: true
              - type: custom:slider-entity-row
                entity: number.prog3_capacity
                name: Battery SOC
        view_layout:
          grid-area: prog3
      - type: vertical-stack
        cards:
          - type: custom:mushroom-template-card
            primary: Program 4
            secondary: >-
              {{ states("select.prog4_time") }} - {{ states("select.prog5_time")
              }}
            icon: mdi:timer
            multiline_secondary: false
            badge_icon: mdi:lightning-bolt
            icon_color: blue
            badge_color: green
            fill_container: false
          - type: horizontal-stack
            cards:
              - type: entities
                entities:
                  - entity: select.prog4_time
              - type: entities
                entities:
                  - entity: select.prog4_charge
          - type: entities
            entities:
              - type: custom:slider-entity-row
                entity: number.prog4_power
                name: Power
                grow: true
              - type: custom:slider-entity-row
                entity: number.prog4_capacity
                name: Battery SOC
        view_layout:
          grid-area: prog4
      - type: vertical-stack
        cards:
          - type: custom:mushroom-template-card
            primary: Program 5
            secondary: >-
              {{ states("select.prog5_time") }} - {{ states("select.prog6_time")
              }}
            icon: mdi:timer
            multiline_secondary: false
            badge_icon: mdi:lightning-bolt
            icon_color: blue
            badge_color: green
            fill_container: false
          - type: horizontal-stack
            cards:
              - type: entities
                entities:
                  - entity: select.prog5_time
              - type: entities
                entities:
                  - entity: select.prog5_charge
          - type: entities
            entities:
              - type: custom:slider-entity-row
                entity: number.prog5_power
                name: Power
                grow: true
              - type: custom:slider-entity-row
                entity: number.prog5_capacity
                name: Battery SOC
        view_layout:
          grid-area: prog5
      - type: vertical-stack
        cards:
          - type: custom:mushroom-template-card
            primary: Program 6
            secondary: >-
              {{ states("select.prog6_time") }} - {{ states("select.prog1_time")
              }}
            icon: mdi:timer
            multiline_secondary: false
            badge_icon: mdi:lightning-bolt
            icon_color: blue
            badge_color: green
            fill_container: false
          - type: horizontal-stack
            cards:
              - type: entities
                entities:
                  - entity: select.prog6_time
              - type: entities
                entities:
                  - entity: select.prog6_charge
          - type: entities
            entities:
              - type: custom:slider-entity-row
                entity: number.prog6_power
                name: Power
                grow: true
              - type: custom:slider-entity-row
                entity: number.prog6_capacity
                name: Battery SOC
        view_layout:
          grid-area: prog6
      - type: custom:mushroom-title-card
        title: Sunsynk System Mode
        alignment: center
        view_layout:
          grid-area: header
      - type: entities
        entities:
          - entity: select.priority_mode
        view_layout:
          grid-area: priority

 

Hi 

Did you make any further modifications to you dashboard? I did try to add it but I get the error below and I dod have all the mushroom card installed and also the loveloace-layout-card, can you share the code if you did? image.png.7a8bfacfcfdf9db89b5737bf17008d12.png

 

Link to comment
Share on other sites

On 2022/11/03 at 11:19 AM, slipx said:

I am getting some weird spikes on  "172 Grid External Power" and "169 Grid Power" sensors. 

image.png.798c5b55cc811bf94113d00ac5aecc1e.png

Trying the following to filter them out which seems to be working:

 - platform: modbus_controller # 169 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
   filters:
    - lambda: |-
          float MAX_DIFFERENCE = 8000.0;  // adjust this!
          static float last_value_t = NAN;
          static int count_missed_t = 0;
          if (count_missed_t == 3) last_value_t = x;
          if (isnan(last_value_t) || std::abs(x - last_value_t) < MAX_DIFFERENCE) {
            count_missed_t = 0;
            return last_value_t = x;
          } else {
            count_missed_t += 1;
            return last_value_t;
            }

 

Hello,

I notice a similar behavior and the issue was the way the variables were defined. There are some power values that are SIGNED, and other are UNSIGNED. Make sure the signed (the ones that can be positive or negative) are properly defined as SIGNED (value_type: S_WORD).

Link to comment
Share on other sites

7 hours ago, martinisonline said:

Hello,

I notice a similar behavior and the issue was the way the variables were defined. There are some power values that are SIGNED, and other are UNSIGNED. Make sure the signed (the ones that can be positive or negative) are properly defined as SIGNED (value_type: S_WORD).

Does anyone have a list of all data types for all registers? The Sunsynk word document leaves a lot for the imagination 

Link to comment
Share on other sites

Hi @jacauc

There are the two Modbus register files that I have

sunsynk_modbus which looks like an extraction from a manual as it looks like it starts at 2.6

I also have a Chinese document that I translated with Google Translate. I think that it is v117 of  the document which was released in 2021 so there may actually be a v118 out by now but haven't seen it as yet.

 

sunsynk_modbus.pdf Modbus118 Translated-compressed.pdf

Link to comment
Share on other sites

On 2022/12/19 at 1:37 AM, slipx said:

How about a small dot that changes colour

 

image.png.b4e7b6562806e72a3a9f8c9703f6f2c7.png

Hi @slipx

Thanks for the great job you've done with this card!

I took it one step further and made the battery icon and lightning bolt smart.

image.png.411bf367b54122ecdb317c2560eaf876.png

When the battery is charging the lightning bolt appears. The bars in the battery changes based on the current SoC of the battery.

I achieved this by overlaying three battery icons and only showing the relevant one (same way as you did with the status indicator).

Link to comment
Share on other sites

Just a question for anyone who has solar-assistant integrated into home assistant via MQTT.

How many entities do you have? I think i may be missing a few

did you enable allow setting changes on the solar assistant config page for MQTT?

 

I guess what i'm asking is how to you get the prog1 time settings like the ones below 

image.png.4d98b52be8b8b04e62ad5212c8ecb53d.png

image.png.b408fac470860636511823ede291b1f0.png

I don't have that option, I only seem to have this option below which says Capacity point

image.png.cc4a0c3d07fb42ac8177fe8f538aab0f.png

 

 

 

mqtt.jpg

Edited by McAllstar
Link to comment
Share on other sites

12 hours ago, jacauc said:

Thanks @Sc00bs. I've seen those before but unfortunately it's not very clear to decipher the data types and whether signed/unsigned. 

@jacauc I sent an email to DEYE asking if they had a newer Modbus document and received a response from them saying that the V118 document is the latest version

 

Link to comment
Share on other sites

On 2023/03/10 at 12:52 PM, McAllstar said:

Hi 

Did you make any further modifications to you dashboard? I did try to add it but I get the error below and I dod have all the mushroom card installed and also the loveloace-layout-card, can you share the code if you did? image.png.7a8bfacfcfdf9db89b5737bf17008d12.png

 

Having the same problem 😞 

Link to comment
Share on other sites

52 minutes ago, Sc00bs said:

Having the same problem 😞 

I think i kinda figured it out.

You need to create a new view by editing one of your dashboards and then select the + icon

image.png.b43027435a42446c1840fab3a07499af.png

then i you need to select the 3 dots in the top right and select "Edit in YAML"

image.thumb.png.7c4d3cc80e23b9b6b6d7065583744ac1.png

then i think you need to past this part of his code. After that then you can select "add card" and use the rest of his code. you need to modify the entities according to your entity names. That's where my problem comes in I'm using solar-assistant and my entity names don't match his and I'm missing the timer and prod entities. 

views:
  - theme: Backend-selected
    title: Grid layout
    type: custom:grid-layout
    layout:
      grid-template-columns: 3fr 2fr 2fr 3fr
      grid-template-rows: auto
      grid-template-areas: |
        ". header header ."
        ". system priority ."
        ". capacity point 1 prog2 ."
        ". prog3 prog4 ."
        ". prog5 prog6 ."
      mediaquery:
        '(max-width: 800px)':
          grid-template-columns: auto
          grid-template-areas: |
            "header"
            "system"
            "priority"
            "prog1"
            "prog2"
            "prog3"
            "prog4"
            "prog5"
            "prog6"
    badges: []

 

Link to comment
Share on other sites

11 hours ago, JDSym said:

Hi @slipx

Thanks for the great job you've done with this card!

I took it one step further and made the battery icon and lightning bolt smart.

image.png.411bf367b54122ecdb317c2560eaf876.png

When the battery is charging the lightning bolt appears. The bars in the battery changes based on the current SoC of the battery.

I achieved this by overlaying three battery icons and only showing the relevant one (same way as you did with the status indicator).

I've made some updates to the card to include dynamic animations. It will now animate power flow based on defined conditions i.e. positive/negative battery power, zero power etc.  I didn't want to have circles moving all over the place so not all paths are animated but you can modify to suite your needs. Note the moving circle is hidden if power is 0. Here is the link to the GitHub repo

https://github.com/slipx06/Sunsynk-Home-Assistant-Power-Flow-Card

 

image.png.bfc84a029c0e8e947836e2ba51c43517.png

Link to comment
Share on other sites

1 hour ago, slipx said:

I've made some updates to the card to include dynamic animations. It will now animate power flow based on defined conditions i.e. positive/negative battery power, zero power etc.  I didn't want to have circles moving all over the place so not all paths are animated but you can modify to suite your needs. Note the moving circle is hidden if power is 0. Here is the link to the GitHub repo

https://github.com/slipx06/Sunsynk-Home-Assistant-Power-Flow-Card

 

image.png.bfc84a029c0e8e947836e2ba51c43517.png

Brilliant!

What program do you use to edit the SVG? I've been using Inkscape, and it works quite well. The one disadvantage is that it adds a lot of unnecessary code needed by the program.

Link to comment
Share on other sites

4 hours ago, slipx said:

Notepad...😄

Impressive 😁

I would suggest showing the absolute values of the readings since the direction of the dot shows the direction of current flow and makes the negative sign in the readings redundant.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...