Skip to content
View in the app

A better way to browse. Learn more.

Power Forum - Renewable Energy Discussion

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

Home Assistant Sunsynk Power Flow Card and Dashboard

Featured Replies

7 minutes ago, IggyP said:

Just installed new HA update and got message that solcast repository was removed:

image.png.7e21cfb87604914df24e02345fe72908.png

Yup - the dev of that plugin got irritated by all the stupid requests made by some.

Anyway, someone else forked (https://github.com/BJReplay/ha-solcast-solar) it so you can remove the plugin and then follow the steps below.

(All API settings and entities should still be there and no other changes required from you side)

Manually in HACS
Follow the link here
Use the custom repo link https://github.com/BJReplay/ha-solcast-solar
Select the category type integration
Then once it's there (still in HACS) click the INSTALL button
Then go to the HA Devices and Services and add a new Solcast Integration

  • Replies 588
  • Views 125.4k
  • Created
  • Last Reply

Top Posters In This Topic

Most Popular Posts

  • thank you @slipx, I've been using the power flow card for a while now but didn't know about the animations. now thanks your examples I've implemented the animations. I use a generator on my AUX port

  • I've made  a small update to the Dashboard. The load shedding card shows remaining time based on battery SOC and battery power. You will need to create some template sensors as discussed here and prov

  • Here's a slight contribution to the goodness on this thread which lives on my main HA screen: type: custom:bar-card entities: - entity: sensor.load_shedding_area_eskde_4_sandownext10cityofj

Posted Images

1 minute ago, Muttley said:

Yup - the dev of that plugin got irritated by all the stupid requests made by some.

Anyway, someone else forked (https://github.com/BJReplay/ha-solcast-solar) it so you can remove the plugin and then follow the steps below.

(All API settings and entities should still be there and no other changes required from you side)

Manually in HACS
Follow the link here
Use the custom repo link https://github.com/BJReplay/ha-solcast-solar
Select the category type integration
Then once it's there (still in HACS) click the INSTALL button
Then go to the HA Devices and Services and add a new Solcast Integration

Thanks for quick reply Muttley, 

will have a closer look to this.

22 hours ago, IggyP said:

Hi Scoobs, 

I just did, will check tomorrow if this solved this issue. 

Hi Scoobs, 
Switched off DC and hit Power button. 

After restart Inverter shows still right solar power values but ESP is still sending e.g. 600W instead of 6000W.

Don't know what esle to do to get this sorted.

Regards

Iggy

  • Author
27 minutes ago, IggyP said:

Hi Scoobs, 
Switched off DC and hit Power button. 

After restart Inverter shows still right solar power values but ESP is still sending e.g. 600W instead of 6000W.

Don't know what esle to do to get this sorted.

Regards

Iggy

If it’s consistently out by a factor of 10 then that’s a quick fix.

24 minutes ago, slipx said:

If it’s consistently out by a factor of 10 then that’s a quick fix.

Hi Slipx if you can tell me how and where to fix that would be great 😉 

Regards

Iggy

On 2024/06/05 at 10:11 PM, Muttley said:

Yup - the dev of that plugin got irritated by all the stupid requests made by some.

Anyway, someone else forked (https://github.com/BJReplay/ha-solcast-solar) it so you can remove the plugin and then follow the steps below.

(All API settings and entities should still be there and no other changes required from you side)

Manually in HACS
Follow the link here
Use the custom repo link https://github.com/BJReplay/ha-solcast-solar
Select the category type integration
Then once it's there (still in HACS) click the INSTALL button
Then go to the HA Devices and Services and add a new Solcast Integration

can add looks like the new developers repo has been added to the store, busy with this now.

G

17 hours ago, IggyP said:

Hi Slipx if you can tell me how and where to fix that would be great 😉 

Regards

Iggy

Edited because I had a look at the inverter itself.

 

@slipx

I had a closer look to the values showing in Dashboard and on the inverter itself.

When I compare the dispaly values of the inverter vs Solar power shown in Dashboard it is exacltey factor 10. 

e.g. Inverter shows 3380W and Solar power in Dashboard is showing 338W. 

 

 

Edited by IggyP

  • Author

@IggyP You can modify your ESP home config:

  - platform: modbus_controller            # 672 PV1 Power
    modbus_controller_id: sunsynk
    name: "${friendly_name} PV1 Power"
    id: sunsynk_esphome_pv1_power
    register_type: holding
    address: 672
    unit_of_measurement: "W"
    accuracy_decimals: 0
    device_class: power
    state_class: measurement
    filters:
      - multiply: 10

  - platform: modbus_controller            # 673 PV2 Power
    modbus_controller_id: sunsynk
    name: "${friendly_name} PV2 Power"
    id: sunsynk_esphome_pv2_power
    register_type: holding
    address: 673
    unit_of_measurement: "W"
    accuracy_decimals: 0
    device_class: power
    state_class: measurement
    value_type: U_WORD
    filters:
      - multiply: 10

 

Edited by slipx

20 hours ago, slipx said:

@IggyP You can modify your ESP home config:

  - platform: modbus_controller            # 672 PV1 Power
    modbus_controller_id: sunsynk
    name: "${friendly_name} PV1 Power"
    id: sunsynk_esphome_pv1_power
    register_type: holding
    address: 672
    unit_of_measurement: "W"
    accuracy_decimals: 0
    device_class: power
    state_class: measurement
    filters:
      - multiply: 10

  - platform: modbus_controller            # 673 PV2 Power
    modbus_controller_id: sunsynk
    name: "${friendly_name} PV2 Power"
    id: sunsynk_esphome_pv2_power
    register_type: holding
    address: 673
    unit_of_measurement: "W"
    accuracy_decimals: 0
    device_class: power
    state_class: measurement
    value_type: U_WORD
    filters:
      - multiply: 10

 

Hi Slipx, 

Thanks you very much! I changed the settings in ESP Home and now it is working perfectly.

Think I'll have some additional questions later on regarding changing the layout of dashboard, like how to get load shedding removed without breaking the whole dashboard and so on. I'm not that good in programming layout.

 

Regards

Iggy

image.thumb.png.2ff568b3c60d8bd3477c7fcccda34a92.png

@slipx SOLVED: When I dropped the code in here I noticed that there was a *2 in the code, e.g.,     data_generator: |
      return entity.attributes.detailedForecast.map((entry) => {
            return [new Date(entry.period_start), entry.pv_estimate*2];
          });

Not sure where that came from. Sorry for the bother. Here is how it looks now -

image.thumb.png.4bfcd35fc03868e5e9cfc777745e14c5.png

--- ORIGINAL QUESTION (BASED ON MY OWN ID10T ERROR)---

@slipx Firstly, thanks for all your amazing work. I have a question about the solar forecast graphic. I can't figure out why the forecast in the graph is so high. It is working at expected in the HA Energy Dashboard. See examples below. Your code is showing what looks like x2 value of what is in the HA Energy Dashboard. Any help resolving this would be greatly appreciated. And apologies if I missed a similar post here. I did look.

image.thumb.png.d5f12c50ca4071f52f51eb437db17e08.png

VS

image.thumb.png.a0290ea6be1b8732ca8d7d62ce4c2871.png

 

HERE IS THE CODE FOR YOUR GRAPH , FYI:

type: custom:apexcharts-card
header:
  show: true
  standard_format: true
  show_states: true
  colorize_states: true
apex_config:
  chart:
    height: 350px
  tooltip:
    enabled: true
    shared: true
    followCursor: true
graph_span: 4d
now:
  show: true
  label: Now
span:
  start: day
  offset: '-1day'
all_series_config:
  type: area
  opacity: 0.3
  stroke_width: 1
series:
  - entity: sensor.solar_assistant_battery_state_of_charge
    name: Battery
    float_precision: 0
    type: line
    color: '#f06292'
    opacity: 0.6
    yaxis_id: capacity
    extend_to: now
    show:
      legend_value: true
      in_header: false
    group_by:
      func: last
      duration: 5m
  - entity: sensor.solar_assistant_pv_power
    name: Solar Power
    float_precision: 3
    color: '#ff9800'
    yaxis_id: kWh
    unit: kW
    transform: return x/1000;
    extend_to: now
    show:
      legend_value: true
      in_header: false
    group_by:
      func: avg
      duration: 5m
  - entity: sensor.solcast_pv_forecast_forecast_today
    name: Solar Forecast (D1)
    extend_to: false
    color: grey
    opacity: 0.3
    stroke_width: 0
    yaxis_id: kWh
    show:
      legend_value: false
      in_header: false
    data_generator: |
      return entity.attributes.detailedForecast.map((entry) => {
            return [new Date(entry.period_start), entry.pv_estimate*2];
          });
  - entity: sensor.solcast_pv_forecast_forecast_tomorrow
    name: Solar Forecast (D2)
    float_precision: 3
    extend_to: false
    color: grey
    opacity: 0.3
    stroke_width: 0
    yaxis_id: kWh
    show:
      legend_value: false
      in_header: false
    data_generator: |
      return entity.attributes.detailedForecast.map((entry) => {
            return [new Date(entry.period_start), entry.pv_estimate*2];
          });
  - entity: sensor.solcast_pv_forecast_forecast_day_3
    name: Solar Forecast (D3)
    float_precision: 3
    extend_to: false
    color: grey
    opacity: 0.3
    stroke_width: 0
    yaxis_id: kWh
    show:
      legend_value: false
      in_header: false
    data_generator: |
      return entity.attributes.detailedForecast.map((entry) => {
            return [new Date(entry.period_start), entry.pv_estimate*2];
          });
  - entity: sensor.solcast_pv_forecast_forecast_today
    yaxis_id: header_only
    name: Solar Forecast (D1)
    color: grey
    show:
      legend_value: true
      in_header: true
      in_chart: false
  - entity: sensor.solcast_pv_forecast_forecast_remaining_today
    yaxis_id: header_only
    name: Forecast (D1 Remaining)
    color: grey
    show:
      legend_value: true
      in_header: true
      in_chart: false
  - entity: sensor.solcast_pv_forecast_forecast_tomorrow
    yaxis_id: header_only
    name: Forecast (D2)
    color: grey
    show:
      legend_value: true
      in_header: true
      in_chart: false
  - entity: sensor.solcast_pv_forecast_forecast_day_3
    yaxis_id: header_only
    name: Solar Forecast (D3)
    color: grey
    show:
      legend_value: true
      in_header: true
      in_chart: false
  - entity: sensor.solcast_pv_forecast_api_last_polled
    yaxis_id: header_only
    name: Forecast (Last Update)
    color: grey
    unit: ' min.'
    transform: return ((Date.now()) - (new Date(x).getTime())) / 60 / 60 / 24
    show:
      legend_value: true
      in_header: true
      in_chart: false
yaxis:
  - id: capacity
    show: true
    opposite: true
    decimals: 0
    max: 100
    min: 0
    apex_config:
      tickAmount: 5
  - id: kWh
    show: true
    min: 0
    apex_config:
      tickAmount: 5
  - id: header_only
    show: false
 

 

Edited by rgt.dnl
Solved query

  • Author
On 2024/05/08 at 7:59 AM, RoganDawes said:

Hate when that happens! 😂

Working perfectly, thanks so much!

While I’m being demanding (not really, it’s just a suggestion for a really low impact quality of life feature), it would be neat to be able to show the timer programs as a graph, with the time/hours along x, and desired SoC as y, with lines between the data points, along with the current day’s SoC readings (or maybe the last 24 hours?) to show how much wiggle room there is between desired and actual.

While I’m dreaming, being able to drag the desired SoC up and down the hour axis could be a nice interface for making changes. You probably don’t want to be able to change the time for the point, just because it would be too easy to change one when you mean only to change the other.

In reality, I don’t think people need to change this often enough to be worth investing any significant time. Just dreaming. 😂

Hi @RoganDawes

I finally got around to graphing this. Its not interactive but does allow you to visualize what you were describing. The time slots are the blue bars and their corresponding capacity (SOC) setting. I've overlayed current SOC and Solar. Since my first slot starts at 1:00am I've shifted the plot over an hour (time_offset). You would need to adjust this setting. There is also a function that generates the program times. It assumes your sensors are named accordingly

sensor.ss_prog${start}_time
sensor.ss_prog${end}_time
number.sunsynk_prog${cap}_capacity

With the variables start, end and cap. Calling the function '({vars}) => vars.compute({start: 1, end: 2, cap: 1})' results in:

sensor.ss_prog1_time 
sensor.ss_prog2_time
number.sunsynk_prog1_capacity

image.png.102fd9926df108c1f6225794547a17d3.png

type: custom:plotly-graph
hours_to_show: current_day
title: System Timer
time_offset: 1h
refresh_interval: auto
fn: |
  $fn({hass, vars}) => {
    vars.compute = ({start, end, cap}) =>{
      const startTimeString = hass.states[`sensor.ss_prog${start}_time`].state;
      const endTimeString = hass.states[`sensor.ss_prog${end}_time`].state;
      const capacity = parseFloat(hass.states[`number.sunsynk_prog${cap}_capacity`].state);

      const now = new Date();
      const [startHours, startMinutes] = startTimeString.split(':').map(Number);
      const [endHours, endMinutes] = endTimeString.split(':').map(Number);

      const startTime = new Date(now.getFullYear(), now.getMonth(), now.getDate(), startHours, startMinutes);
      let endTime = new Date(now.getFullYear(), now.getMonth(), now.getDate(), endHours, endMinutes);
      
      if (endTime < startTime) {
        endTime.setDate(endTime.getDate() + 1);
      }

      return { xs: [startTime, endTime], ys: [capacity, capacity] };
    }
  }
entities:
  - entity: sensor.sunsynk_battery_soc
    name: |
      $fn ({ ys,meta }) =>
        "SOC" + "🔋" + "(" +ys[ys.length - 1]+"%)"
    line:
      color: red
      shape: spline
      width: 1
    fill: tozeroy
    fillcolor: rgba(255,0,0, 0.3)
    show_value: true
    texttemplate: '%{y}'
  - entity: sensor.sunsynk_solar_power
    name: |
      $fn ({ ys,meta }) =>
        "Solar" + "🔆" + "(" +ys[ys.length - 1]+"W)"
    line:
      color: rgb(255, 155, 48)
      shape: spline
      width: 1
    fill: tozeroy
    fillcolor: rgba(255, 155, 48, 0.3)
    yaxis: y2
    show_value: false
    showlegend: true
  - entity: number.sunsynk_prog1_capacity
    line:
      color: rgb(30,144,255)
      width: 1
    fill: tozeroy
    fillcolor: rgba(30,144,255, 0.6)
    showlegend: false
    filters:
      - fn: '({vars}) => vars.compute({start: 1, end: 2, cap: 1})'
  - entity: number.sunsynk_prog2_capacity
    line:
      color: rgb(30,144,255)
      width: 1
    fill: tozeroy
    fillcolor: rgba(30,144,255, 0.9)
    showlegend: false
    filters:
      - fn: '({vars}) => vars.compute({start: 2, end: 3, cap: 2})'
  - entity: number.sunsynk_prog3_capacity
    line:
      color: rgb(30,144,255)
      width: 1
    fill: tozeroy
    fillcolor: rgba(30,144,255, 0.7)
    showlegend: false
    filters:
      - fn: '({vars}) => vars.compute({start: 3, end: 4, cap: 3})'
  - entity: number.sunsynk_prog4_capacity
    line:
      color: rgb(30,144,255)
      width: 1
    fill: tozeroy
    fillcolor: rgba(30,144,255, 0.9)
    showlegend: false
    show_value: false
    filters:
      - fn: '({vars}) => vars.compute({start: 4, end: 5, cap: 4})'
  - entity: number.sunsynk_prog5_capacity
    line:
      color: rgb(30,144,255)
      width: 1
    fill: tozeroy
    fillcolor: rgba(30,144,255, 0.7)
    showlegend: false
    filters:
      - fn: '({vars}) => vars.compute({start: 5, end: 6, cap: 5})'
  - entity: number.sunsynk_prog6_capacity
    line:
      color: rgb(30,144,255)
      width: 1
    fill: tozeroy
    fillcolor: rgba(30,144,255, 0.9)
    showlegend: false
    filters:
      - fn: '({vars}) => vars.compute({start: 6, end: 1, cap: 6})'
layout:
  showlegend: true
  yaxis:
    nticks: 20
    range:
      - 0
      - 105
    fixedrange: true
  yaxis2:
    range:
      - 0
      - 6600
    fixedrange: true
  xaxis:
    nticks: 9
    tickangle: 0
config:
  scrollZoom: false

 

 

1 hour ago, slipx said:

Hi @RoganDawes

I finally got around to graphing this. Its not interactive but does allow you to visualize what you were describing. The time slots are the blue bars and their corresponding capacity (SOC) setting. I've overlayed current SOC and Solar. Since my first slot starts at 1:00am I've shifted the plot over an hour (time_offset). You would need to adjust this setting. There is also a function that generates the program times. It assumes your sensors are named accordingly.

image.png.102fd9926df108c1f6225794547a17d3.png

Wow! That's impressive! I had in mind a line graph rather than a bar graph for the SoC levels, which, with a line graph for actual SoC, would allow you to visualise how close you are to crossing the lines.

Very cool, though!

  • Author
20 minutes ago, RoganDawes said:

Wow! That's impressive! I had in mind a line graph rather than a bar graph for the SoC levels, which, with a line graph for actual SoC, would allow you to visualise how close you are to crossing the lines.

Very cool, though!

In that case we would need to combine all the data points into a single array as one entity. Here is the updated code

image.png.d0ee6e155033e5993fe1399c8491acb0.png

type: custom:plotly-graph
hours_to_show: current_day
title: System Timer
time_offset: 1h
refresh_interval: auto
fn: |
  $fn({hass, vars}) => {
    vars.computeAll = () => {
      const timeSlots = [
        {start: 1, end: 2, cap: 1},
        {start: 2, end: 3, cap: 2},
        {start: 3, end: 4, cap: 3},
        {start: 4, end: 5, cap: 4},
        {start: 5, end: 6, cap: 5},
        {start: 6, end: 1, cap: 6}
      ];

      const now = new Date();
      const xs = [];
      const ys = [];

      timeSlots.forEach(({start, end, cap}) => {
        const startTimeString = hass.states[`sensor.ss_prog${start}_time`].state;
        const endTimeString = hass.states[`sensor.ss_prog${end}_time`].state;
        const capacity = parseFloat(hass.states[`number.sunsynk_prog${cap}_capacity`].state);

        const [startHours, startMinutes] = startTimeString.split(':').map(Number);
        const [endHours, endMinutes] = endTimeString.split(':').map(Number);

        const startTime = new Date(now.getFullYear(), now.getMonth(), now.getDate(), startHours, startMinutes);
        let endTime = new Date(now.getFullYear(), now.getMonth(), now.getDate(), endHours, endMinutes);

        if (endTime < startTime) {
          endTime.setDate(endTime.getDate() + 1);
        }

        xs.push(startTime, endTime);
        ys.push(capacity, capacity);
      });

      return { xs, ys };
    }
  }
entities:
  - entity: sensor.sunsynk_battery_soc
    name: |
      $fn ({ ys,meta }) =>
        "SOC" + "🔋" + "(" +ys[ys.length - 1]+"%)"
    line:
      color: red
      shape: spline
      width: 1
    fill: tozeroy
    fillcolor: rgba(255,0,0, 0.3)
    show_value: true
    texttemplate: '%{y}'
  - entity: sensor.sunsynk_solar_power
    name: |
      $fn ({ ys,meta }) =>
        "Solar" + "🔆" + "(" +ys[ys.length - 1]+"W)"
    line:
      color: rgb(255, 155, 48)
      shape: spline
      width: 1
    fill: tozeroy
    fillcolor: rgba(255, 155, 48, 0.3)
    yaxis: y2
    show_value: false
    showlegend: true
  - entity: sensor.sunsynk_combined_capacity
    name: |
      $fn ({ ys, meta }) =>
        "Prog Capacity"
    line:
      color: rgb(30, 144, 255)
      width: 2
    fillcolor: rgba(30, 144, 255, 0.6)
    show_value: true
    unit_of_measurement: '%'
    filters:
      - fn: ({ vars }) => vars.computeAll()
layout:
  showlegend: true
  yaxis:
    nticks: 20
    range:
      - 0
      - 105
    fixedrange: true
  yaxis2:
    range:
      - 0
      - 6600
    fixedrange: true
  xaxis:
    nticks: 9
    tickangle: 0
config:
  scrollZoom: false

 

1 hour ago, slipx said:

In that case we would need to combine all the data points into a single array as one entity. Here is the updated code

image.png.d0ee6e155033e5993fe1399c8491acb0.png

 

I meant that the lines should not be horizontal or vertical only 🙂 So that the lines would approximate either the charging or discharging slope. Thinking about it, though, it might not be as simple as it sounds, as it might depend on whether the inverter is charging or discharging as to whether the minimum SoC should be shown at the start or end of the period . . . in which case, horizontal lines probably does make more sense.

10 hours ago, slipx said:

@rgt.dnl glad you sorted it out. Btw I've moved over to the Open Meteo solar forecast https://github.com/rany2/ha-open-meteo-solar-forecast. It allows for more api calls and you can add multiple arrays. I've also moved the graph to plotly. The code is on the GitHub.

 

image.thumb.png.3541ed908e45ecca34e8deb8c64491c2.png

@slipx trying out you new graph with open meteo but getting the following errors - Can you help?

image.thumb.png.d7b754a707ed5408826052e807991a20.png

  • Author

@rgt.dnl I created my own template sensor that sums the data from two arrays and adjusted how the attributes are created. If you are using the default integration sensor then replace the filters for each entity in the graph 

filters:
      - fn: |
          ({meta}) => ({
             xs: meta.wh_period.map(({ start }) => new Date(start)),
             ys: meta.wh_period.map(({ value }) => value),
          })

with

filters:
      - fn: |
          ({meta}) => {
            const entries = Object.entries(meta.wh_period); 
            const xs = entries.map(([start, _]) => new Date(start));
            const ys = entries.map(([_, value]) => value);
            
            return { xs, ys };
          }

I've updated the code on GitHub 

Edited by slipx

  • Author
7 hours ago, Muttley said:

Hey @slipx

Wondering if you could let me know which option/s I should chose for solar forecast with open-meteo?

image.thumb.png.1768021a5c32beff15b7e99cbebb62b3.png

Current settings are giving an output W/m2....

 

HI. I use it without an API key so did not chose any options.

  • 4 weeks later...

Hi 

Can someone please share what entity do you use for grid connected status on a Sunsynk inverter. That's the only one I am still struggling with.

Much appreciated 

18 hours ago, Zeus-JKR said:

Hi 

Can someone please share what entity do you use for grid connected status on a Sunsynk inverter. That's the only one I am still struggling with.

Much appreciated 

binary_sensor.grid_connected_status

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...

Account

Navigation

Search

Search

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.