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.

SunSynk Logger Integration into Home Assistant

Featured Replies

  • Replies 948
  • Views 131.8k
  • Created
  • Last Reply

Top Posters In This Topic

Most Popular Posts

  • randomfool
    randomfool

    I am making good progress on converting slip06x excellent dashboard to work with Gary's brilliant work on gathering the data from the latest Sunsynk inverters remotely. Will publish the dashboard

  • @Gary Waterworth   Did a quick YouTube video on how to install your software and to get the data into HASS, no cards or anything so very basic.  Please let me know what you guys think of my first

  • randomfool
    randomfool

    Ok here goes; caveats to begin with - I am no HA expert, in fact I only discovered HA a few weeks ago through Gary's post and his subsequent links to slip06x dashboard, so my ability to provide "suppo

Posted Images

42 minutes ago, -cK- said:

drop my the energyMode one as well to test I'm getting an error if I try to edit it to the same float setting.

{% if (state_attr('sensor.sunsynk_settings', 'energyMode') | float) == 1  %}
on
{% else %}
off
{% endif %}

ok found the problem, needed to remove the : that was in the original line I tried converting

-edit-

For ease of reference:

  - sensor:
      - name: "Current Use Timer 248"
        state: >
          {% if (state_attr('sensor.sunsynk_settings', 'peakAndVallery') | float) == 1  %}
            on
          {% else %}
            off
          {% endif %}
  - sensor:
      - name: "Energy Mode 243"
        state: >
          {% if (state_attr('sensor.sunsynk_settings', 'energyMode') | float) == 1  %}
            on
          {% else %}
            off
          {% endif %}

image.png.93cf1449bbeff797dde93f647ff5353c.png

image.png.6220d25c27e8d59eaf26f2684684db0d.png

Edited by -cK-
Additional info provided

@slipx & @-cK- Excellent work on the cards guys,  just a suggestion to add a feature if you're open to it/ in the mood:  implement additional info like rate of charge kWh (x%/h) rate of discharge (y%/h) additionally a display of 'approximate hours to full charge' with displaying the time at full charge assuming at constant rate (would be way more technical to also implement expected/ predicted solar correction). So that i can easily see at current charge rate expected full charge will be at 3pm vs 8pm aka indicating i should intervene if it's after 5pm... with a symbol changing colour etc..

1 hour ago, SteveRCT said:

@slipx & @-cK- Excellent work on the cards guys,  just a suggestion to add a feature if you're open to it/ in the mood:  implement additional info like rate of charge kWh (x%/h) rate of discharge (y%/h) additionally a display of 'approximate hours to full charge' with displaying the time at full charge assuming at constant rate (would be way more technical to also implement expected/ predicted solar correction). So that i can easily see at current charge rate expected full charge will be at 3pm vs 8pm aka indicating i should intervene if it's after 5pm... with a symbol changing colour etc..

Have a look at the latest release. It includes the time to full charge.

image.png.cd36a4970729168b0ce22f4f27d8bbf0.png

@slipx The battery shutdown SOC is done on a static value but I was wondering could one link it the timer SOC when it is discharging and the timer is set to on?

So probably an oversimplification but the logic would be something down the line of:

Check time (now), determine the timeslot to pull soc from

(unless there is another way to see which timeslot is currently active in the setting attributes)

Then:

If grid is online calculation is based on the timeslot SOC, if grid is offline it is based of the set shutdown SOC of XX.

Was thinking it could be a nice option to see how long you will be able run on your battery till you hit your SOC and go over to grid and when the power is off you get the full runtime to shutdown calculation.  Will be much easier than trying to explain to the none tech savvy folk in the house how to calculate battery runtime when discharging during high peak usage 😅

Perhaps even set it as an option to enable or disable this method 🤷‍♂️

Just a thought

It sounds complicated and will require some thought. The timeslot is reported as a string so you need to convert it to a date format. It also requires another 12 sensors, one for each time slot and timeslot SOC. My initial thoughts are it falls outside of the scope of this card.

BTW I just released v1.5.0 of the card that includes the optional addition of remaining solar forecast for the day. I've also included the actual time that the battery will be fully charged or shutdown SOC reached based on the suggestion of @SteveRCT 

image.png.ede6aced2842a5834063ec5e5137d0c9.png

 

@slipx

I've been fiddling with it a bit using your old card sensor template as a testing ground and this is what I've come up with so far that will change the calculation based on the current time slot SOC.  Might be of assistance but if this falls outside of the scope of the card I understand.

image.thumb.png.727ef822e931720cf81d26177fa6864d.png

      battery_cap:
        friendly_name: "Battery Capacity"
        value_template: >
          {% set now = strptime(as_timestamp(now()) | timestamp_custom('%H:%M'), '%H:%M') %}
          {% set sellTime1 = strptime(state_attr('sensor.sunsynk_settings', 'sellTime1'), '%H:%M') %}
          {% set sellTime2 = strptime(state_attr('sensor.sunsynk_settings', 'sellTime2'), '%H:%M') %}
          {% set sellTime3 = strptime(state_attr('sensor.sunsynk_settings', 'sellTime3'), '%H:%M') %}
          {% set sellTime4 = strptime(state_attr('sensor.sunsynk_settings', 'sellTime4'), '%H:%M') %}
          {% set sellTime5 = strptime(state_attr('sensor.sunsynk_settings', 'sellTime5'), '%H:%M') %}
          {% set sellTime6 = strptime(state_attr('sensor.sunsynk_settings', 'sellTime6'), '%H:%M') %}
          {% if now >= sellTime1 and now < sellTime2 %}
            {{ state_attr('sensor.sunsynk_settings', 'cap1') | float }}
          {% elif now >= sellTime2 and now < sellTime3 %}
            {{ state_attr('sensor.sunsynk_settings', 'cap2') | float }}
          {% elif now >= sellTime3 and now < sellTime4 %}
            {{ state_attr('sensor.sunsynk_settings', 'cap3') | float }}
          {% elif now >= sellTime4 and now < sellTime5 %}
            {{ state_attr('sensor.sunsynk_settings', 'cap4') | float }}
          {% elif now >= sellTime5 and now < sellTime6 %}
            {{ state_attr('sensor.sunsynk_settings', 'cap5') | float }}
          {% elif now >= sellTime6 or now < sellTime1 %}
            {{ state_attr('sensor.sunsynk_settings', 'cap6') | float }}
          {% else %}
            0
          {% endif %}
      soc_battery_time_left:
        friendly_name: "Battery Depletion Seconds"
        unit_of_measurement: Seconds
        value_template: >
          {% set state = states('sensor.sunsynk_battery_power') | int %}
          {% set cap = states('sensor.battery_cap') | float %}
          {% if state == 0 %}
            {{ ((((states('sensor.sunsynk_battery_soc') | float - cap) / 100) * 10240) / 1 * 60 * 60) | int }}
          {% else %}
            {{ ((((states('sensor.sunsynk_battery_soc') | float - cap) / 100) * 10240) / (states('sensor.sunsynk_battery_power') | float) * 60 * 60) | int }}
          {% endif %}
      soc_battery_time_left_friendly:
        friendly_name: "Battery Depletion Time"
        value_template: >
          {% set state = states('sensor.sunsynk_battery_power') | int %}
          {% if state > 0 -%}
           {%- set time = states('sensor.soc_battery_time_left') | int %}
           {%- set minutes = ((time % 3600) // 60) %}
           {%- set minutes = '{} minutes'.format(minutes) if minutes > 0 else '' %}
           {%- set hours = ((time % 86400) // 3600) %}
           {%- set hours = '{} hours, '.format(hours) if hours > 0 else '' %}
           {%- set days = (time // 86400) %}
           {%- set days = '{} day, '.format(days) if days > 0 else '' %}
           {{ 'Less than 1 minute' if time < 60 else days + hours + minutes }}
          {%- else -%}
           {{ 'Running on solar power' }}
          {%- endif %}

 

Edited by -cK-
Typo

Made a small alteration to the above to first check the grid status so to return the "shutdown" value (in my code this is a fixed value but this could be modified I believe to pull the shutdown value that one set in the card parameters perhaps).

So when the power is out it will base the calculation on the shutdown % and not the SOC limits

image.png.5168a61cf5d4f11845b564ae34728fb2.png

image.png.8cf9a0f276a67d3305d4dc883f6f1a5f.png

      battery_cap:
        friendly_name: "Battery Capacity"
        value_template: >
          {% set grid_online = states('sensor.sunsynk_grid_online') | float %}
          {% if grid_online | float == 0 %}
            20
          {% else %}
            {% set now = strptime(as_timestamp(now()) | timestamp_custom('%H:%M'), '%H:%M') %}
            {% set sellTime1 = strptime(state_attr('sensor.sunsynk_settings', 'sellTime1'), '%H:%M') %}
            {% set sellTime2 = strptime(state_attr('sensor.sunsynk_settings', 'sellTime2'), '%H:%M') %}
            {% set sellTime3 = strptime(state_attr('sensor.sunsynk_settings', 'sellTime3'), '%H:%M') %}
            {% set sellTime4 = strptime(state_attr('sensor.sunsynk_settings', 'sellTime4'), '%H:%M') %}
            {% set sellTime5 = strptime(state_attr('sensor.sunsynk_settings', 'sellTime5'), '%H:%M') %}
            {% set sellTime6 = strptime(state_attr('sensor.sunsynk_settings', 'sellTime6'), '%H:%M') %}
            {% if now >= sellTime1 and now < sellTime2 %}
              {{ state_attr('sensor.sunsynk_settings', 'cap1') | float }}
            {% elif now >= sellTime2 and now < sellTime3 %}
              {{ state_attr('sensor.sunsynk_settings', 'cap2') | float }}
            {% elif now >= sellTime3 and now < sellTime4 %}
              {{ state_attr('sensor.sunsynk_settings', 'cap3') | float }}
            {% elif now >= sellTime4 and now < sellTime5 %}
              {{ state_attr('sensor.sunsynk_settings', 'cap4') | float }}
            {% elif now >= sellTime5 and now < sellTime6 %}
              {{ state_attr('sensor.sunsynk_settings', 'cap5') | float }}
            {% elif now >= sellTime6 or now < sellTime1 %}
              {{ state_attr('sensor.sunsynk_settings', 'cap6') | float }}
            {% else %}
              0
            {% endif %}
          {% endif %}

 

Edited by -cK-
Additional information

2 hours ago, Jacques Jambo said:

Hi thanks so much for this! its working like a charm.

One thing, I have 16kw inverter and i was wondering if there is any way to get the 3rd string displaying.

Thanks again

Jacques

Yes, just change mppts:three under solar

Edited by spotity

I've done some more work on the markdown card and sensors to try and do the same on the charging side to give myself an estimated time it will take to reach my current timeslot SOC when charging and when the SOC is reached it should then give me the time to reach 100%. 

Well that is in theory what I'm trying to do but will have to test this out tomorrow to see if it is working as intended.  Not sure how useful this will be for others but for me it is just an aid to get a quick idea of the state of charging/discharging  without having to do all these calculations in my head.

If it work and I've ironed out all the little issues I still have with it I'll post the updated templates.

@slipx

Any reason you opted to have the shutdown value as a fixed input value instead of pulling it from the sensor data?

I've used this in my updated sensors to pull the value instead of having it as a fixed value:

{{ (states.sensor.sunsynk_settings.attributes.batteryShutdownCap) | float }}

So it will auto adjusts if you change the shutdown settings (not that you do it often but one less thing to remember to change if you change settings) 🤷‍♂️

---Edit---

Just a few screenshots from my testing and debugging of the code thus far:

SOC = 25 (So it give you runtime to a full charge)

image.png.915dc79dfc9947dcd8857bb235a98ef6.png

SOC = 35 (So it give me the runtime to reach the SOC and when the SOC is reached it goes to 100)

image.png.865c7626136e27c2a4ba1931dbd5d506.png

Battery above the current SOC so it give me the time until it will reach the SOC of 25 (note the slipx's card will be to shutdown value which is actually nice to have both times up at the same time)

image.png.270debeafeb89efe7528ab0915640e75.png

and when the power is out it will give you the runtime to shutdown value

image.png.b9609bda8420df08ec6a96dffb5b9cfa.png

@slipx considering how many variables there are to keep track of maybe it should be an optional "addon" to the card instead of being integrated into the card.  Something people can rather choose to copy to their config file and then just setup the markdown card together with your card if they want to use is.  Once I'm happy everything is working the way I want it I'll post all of the code so that you can evaluate for yourself.  Like you said perhaps outside of the scope of the cards itself and a bit of a niche use case. 😉

 

Edited by -cK-
Additional information

16 hours ago, -cK- said:

Any reason you opted to have the shutdown value as a fixed input value instead of pulling it from the sensor data?

I've used this in my updated sensors to pull the value instead of having it as a fixed value:

The original thinking was you could manually adjust this based on on other variables and your own energy management preferences. It's referenced as shutdown SOC but its just working out the time to discharge to the target. Ii may not be actual shutdown SOC i.e. a specific time slot SOC you want to monitor.

16 hours ago, -cK- said:

considering how many variables there are to keep track of maybe it should be an optional "addon" to the card instead of being integrated into the card.

I like the idea of an optional add-on. 

2 hours ago, slipx said:

I like the idea of an optional add-on. 

Cool I'm gonna run this for another day or so just to make sure I didn't miss any weird random scenrio I didn't think of that will make it freak out.

 

@slipx Think I've got all the major bugs ironed out so here is the code for that add-on:

Template sensors needed in the configuration file:

#####
#####
##### Sunsynk-Power-Flow-Card: Add-On
##### Markdown Sensors Template
#####
#####

      battery_cap:
        friendly_name: "Battery Capacity"
        value_template: >
          {% set grid_online = states('sensor.sunsynk_grid_online') | float %}
          {% if grid_online | float == 0 %}
            {{ (states.sensor.sunsynk_settings.attributes.batteryShutdownCap) | float }}
          {% else %}
            {% set now = strptime(as_timestamp(now()) | timestamp_custom('%H:%M'), '%H:%M') %}
            {% set sellTime1 = strptime(state_attr('sensor.sunsynk_settings', 'sellTime1'), '%H:%M') %}
            {% set sellTime2 = strptime(state_attr('sensor.sunsynk_settings', 'sellTime2'), '%H:%M') %}
            {% set sellTime3 = strptime(state_attr('sensor.sunsynk_settings', 'sellTime3'), '%H:%M') %}
            {% set sellTime4 = strptime(state_attr('sensor.sunsynk_settings', 'sellTime4'), '%H:%M') %}
            {% set sellTime5 = strptime(state_attr('sensor.sunsynk_settings', 'sellTime5'), '%H:%M') %}
            {% set sellTime6 = strptime(state_attr('sensor.sunsynk_settings', 'sellTime6'), '%H:%M') %}
            {% if now >= sellTime1 and now < sellTime2 %}
              {{ state_attr('sensor.sunsynk_settings', 'cap1') | float }}
            {% elif now >= sellTime2 and now < sellTime3 %}
              {{ state_attr('sensor.sunsynk_settings', 'cap2') | float }}
            {% elif now >= sellTime3 and now < sellTime4 %}
              {{ state_attr('sensor.sunsynk_settings', 'cap3') | float }}
            {% elif now >= sellTime4 and now < sellTime5 %}
              {{ state_attr('sensor.sunsynk_settings', 'cap4') | float }}
            {% elif now >= sellTime5 and now < sellTime6 %}
              {{ state_attr('sensor.sunsynk_settings', 'cap5') | float }}
            {% elif now >= sellTime6 or now < sellTime1 %}
              {{ state_attr('sensor.sunsynk_settings', 'cap6') | float }}
            {% else %}
              {{ (states.sensor.sunsynk_settings.attributes.batteryShutdownCap) | float }}
            {% endif %}
          {% endif %}
      soc_battery_time_left:
        friendly_name: "Battery Depletion Seconds"
        unit_of_measurement: Seconds
        value_template: >
          {% set state = states('sensor.sunsynk_battery_power') | int %}
          {% set cap = states('sensor.battery_cap') | float %}
          {% if state == 0 %}
            {{ ((((states('sensor.sunsynk_battery_soc') | float - cap) / 100) * 10240) / 1 * 60 * 60) | int }}
          {% else %}
            {{ ((((states('sensor.sunsynk_battery_soc') | float - cap) / 100) * 10240) / (states('sensor.sunsynk_battery_power') | float) * 60 * 60) | int }}
          {% endif %}
      soc_battery_time_left_friendly:
        friendly_name: "Battery Depletion Time"
        value_template: >
          {% set state = states('sensor.sunsynk_battery_power') | int %}
          {% if state > 0 -%}
           {%- set time = states('sensor.soc_battery_time_left') | int %}
           {%- set minutes = ((time % 3600) // 60) %}
           {%- set minutes = '{} min'.format(minutes) if minutes > 0 else '' %}
           {%- set hours = ((time % 86400) // 3600) %}
           {%- set hours = '{} hrs, '.format(hours) if hours > 0 else '' %}
           {%- set days = (time // 86400) %}
           {%- set days = '{} day, '.format(days) if days > 0 else '' %}
           {{ 'Floating' if time < 60 else days + hours + minutes }}
          {%- else -%}
           {{ 'Charging' }}
          {%- endif %}
      battery_charging_time_left:
        friendly_name: "Battery Charging Time Left"
        unit_of_measurement: Seconds
        value_template: >
          {% set power = states('sensor.sunsynk_battery_power') | float %}
          {% set soc = states('sensor.sunsynk_battery_soc') | float %}
          {% set cap = states('sensor.battery_cap') | float %}

          {% if power < 0 %}
            {% if soc < cap %}
              {{ ((((cap - soc) / 100) * 10240) / (-power) * 60 * 60) | int }}
            {% else %}
              {{ ((((100 - soc) / 100) * 10240) / (-power) * 60 * 60) | int }}
            {% endif %}
          {% else %}
            0
          {% endif %}
      battery_charging_time_left_friendly:
        friendly_name: "Battery Charging Time"
        value_template: >
          {% set state = states('sensor.sunsynk_battery_power') | int %}
          {% if state < 0 -%}
           {%- set time = states('sensor.battery_charging_time_left') | int %}
           {%- set minutes = ((time % 3600) // 60) %}
           {%- set minutes = '{} min'.format(minutes) if minutes > 0 else '' %}
           {%- set hours = ((time % 86400) // 3600) %}
           {%- set hours = '{} hrs, '.format(hours) if hours > 0 else '' %}
           {%- set days = (time // 86400) %}
           {%- set days = '{} day, '.format(days) if days > 0 else '' %}
           {{ 'Floating' if time < 60 else days + hours + minutes }}
          {%- else -%}
           {{ 'Discharging' }}
          {%- endif %}
      markdown_battery_charge_time_left:
        friendly_name: "Markdown Battery Charging Time"
        value_template: >
          {% if states('sensor.sunsynk_battery_soc') | float < states('sensor.battery_cap') | float %}
           {{ states('sensor.battery_cap') | float | round(0) }}
          {% else %}
           100
           {% endif %}
      markdown_discharge_time:
        friendly_name: "Markdown Discharge Time"
        value_template: >
          {% set now = as_timestamp(now()) %}
          {% set add = states('sensor.soc_battery_time_left') | int %}
          {% set future_time = now + add %}
           {{ future_time | timestamp_custom('%H:%M') }}
      markdown_charge_time:
        friendly_name: "Markdown Charging Time"
        value_template: >
          {% set now = as_timestamp(now()) %}
          {% set add = states('sensor.battery_charging_time_left') | int %}
          {% set future_time = now + add %}
           {{ future_time | timestamp_custom('%H:%M') }}
      battery_status:
        value_template: "{{ 'positive' if states('sensor.sunsynk_battery_power')|float > 0 else 'negative' }}"
        friendly_name: "Battery Status"

10240 is the battery size (2x5.12kW batteries so adjust this value accordingly to your setup) 

Then I have the different markdown cards setup as conditional cards below the Sunsynk Power Flow Card:

  - type: conditional
    conditions:
      - entity: sensor.battery_status
        state: positive
    card:
      type: markdown
      content: "<table width=\"100%\"  border=0>\n  <tbody> \n  <tr>\n    <td align=\"center\">\n    <b>Discharge to {{ states('sensor.battery_cap') | float | round(0)}}% :\n   {{ states('sensor.soc_battery_time_left_friendly') }} @ {{  states('sensor.markdown_discharge_time') }}</b> \n  \t</td>\n  </tr>\n  </tbody>\n</table>"
  - type: conditional
    conditions:
      - entity: sensor.battery_status
        state: negative
    card:
      type: markdown
      content: "<table width=\"100%\"  border=0>\n  <tbody> \n  <tr>\n    <td align=\"center\">\n    <b>Charge to {{ states('sensor.markdown_battery_charge_time_left') | float | round(0)}}% : \n   {{ states('sensor.battery_charging_time_left_friendly') }} @ {{  states('sensor.markdown_charge_time') }}</b> \n  \t</td>\n  </tr>\n  </tbody>\n</table>"
  - type: conditional
    conditions:
      - entity: sensor.battery_status
        state: unavailable
    card:
      type: markdown
      content: "<table width=\"100%\"  border=0>\n  <tbody> \n  <tr>\n    <td align=\"center\">\n    <b>Houston, we have a Problem</b> \n  \t</td>\n  </tr>\n  </tbody>\n</table>\n"

Think that is everything needed for this add-on to work.  Note that I'm using Gary's integration to pull the inverter data so not sure what the sensors would be on the other integrations like Solarman etc. sorry.

Edited by -cK-
Typo

1 hour ago, Jacques Jambo said:

Hi where exactly do you do this?

Still havent figured it out

Edit the dashboard 

image.png.e2e8a5e19b7f066ea12823cece14ea23.png

 

Select edit on the card
image.png.a25b5d3e90484287cc37bd4ad5af0fbb.png

Change the attribute MPPT under solar to three

image.thumb.png.4dbd40ad7447c7f93c9515c6971f52a3.png

Hi ok I have figure most of this out.

Got the flow card working finally.

But it seems the sunsynk integration is not pulling any data from pv 3.

I noticed on the phone app only the first 2 strings show up but the desktop version shows all 3 strings.

 

5 minutes ago, Jacques Jambo said:

Hi ok I have figure most of this out.

Got the flow card working finally.

But it seems the sunsynk integration is not pulling any data from pv 3.

I noticed on the phone app only the first 2 strings show up but the desktop version shows all 3 strings.

 

Probably need to include the mppt in your template sensors, currently only 2 in the template, current one should look similar to this, add the 3rd one for voltage and current. 

 

  - sensor:
      - name: "Sunsynk PV1 186"
        state: >
          {{state_attr('sensor.sunsynk_input', 'pv1')|float(0)|round(0)}}
  - sensor:
      - name: "Sunsynk PV2 187"
        state: >
          {{state_attr('sensor.sunsynk_input', 'pv2')|float(0)|round(0)}}
  - sensor:
      - name: "Sunsynk PV1 Voltage 109"
        state: >
          {{state_attr('sensor.sunsynk_input', 'pvIV_0_vpv')|float(0)|round(1)}}
  - sensor:
      - name: "Sunsynk PV1 Current 110"
        state: >
          {{state_attr('sensor.sunsynk_input', 'pvIV_0_ipv')|float(0)|round(1)}}
  - sensor:
      - name: "Sunsynk PV2 Voltage 111"
        state: >
          {{state_attr('sensor.sunsynk_input', 'pvIV_1_vpv')|float(0)|round(1)}}
  - sensor:
      - name: "Sunsynk PV2 Current 112"
        state: >
          {{state_attr('sensor.sunsynk_input', 'pvIV_1_ipv')|float(0)|round(1)}}

 

Edited by spotity

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.