SMA Solar WebConnect

I don’t know much about it. But i use sunnyportal.com to look online. And local I just go to my ipadres.

I have a Sunny Boy 3.0 1AV-40 and I live in Belgium. I use HA on my synology

Thanks for the reply. That probably explains it then. My inverter is about 5 years old, you have one of the newest models with the network interface built in… They obviously have changed the interface.

Sorry i can’t help you with the problem. That was the only problem I’ve got :slight_smile:

Hi. Did you solve this in the meantime? I have the same problem.

1 Like

I have been unable to connect to my 5000TL-21 with the additional WebConnect module.

Spoke to SMA Australia, and apparently this model will only connect with Sunny Portal or Sunny Explorer - no internal web interface.

I wonder if this is the same issue a few others have encountered. Using Sunny Explorer I could connect via bluetooth and see that the WebConnect module had an IP and was happily sending data to Sunny Portal - but could not access via browser on the LAN.

Yes, yours is the older model also, does not support http connections.

for old Sma inverters with web connect you can enable modbus over tcp…
i have these set in configuration.yaml:

modbus:
  - type: tcp
    host: {ip_of_inverter}
    port: 502

sensor:
  - platform: modbus
    scan_interval: 60   #time in seconds for getting values
    registers:
    - name: SMA_Power_AC
      unit_of_measurement: W
      slave: 3
      register: 30775
      count: 2
      data_type: int
    - name: PV Daily Yield
      unit_of_measurement: kWh
      slave: 3
      register: 30517
      scale: 0.001
      precision: 3
      count: 4
      data_type: uint
    - name: PV Total Production
      unit_of_measurement: MWh
      slave: 3
      register: 30513
      scale: 0.000001
      precision: 3
      count: 4
    - name: Grid Voltage
      unit_of_measurement: V
      slave: 3 
      register: 30783
      count: 2
      scale: 0.01
      precision: 2
      data_type: uint
    - name: Grid frequency
      unit_of_measurement: Hz
      slave: 3 
      register: 30803
      count: 2
      scale: 0.01
      precision: 2
      data_type: uint
    - name: SMA_temp
      unit_of_measurement: °C
      slave: 3
      register: 30953
      count: 2
      scale: 0.1
      precision: 1
      data_type: int
    - name: SMA_status
      slave: 3
      register: 30201
      count: 2
    - name: SMA_grid
      slave: 3
      register: 30217
      count: 2
    - name: Insulation
      slave: 3
      register: 30225
      count: 2
      scale: 0.001
      unit_of_measurement: kOhms
    - name: SMA_Residual_current
      slave: 3
      register: 31247
      count: 2
      scale: 1
      unit_of_measurement: mA
    - name: Apparent Power
      unit_of_measurement: VA
      slave: 3
      register: 30813
      scale: 1
      precision: 0
      count: 2
      data_type: int
    - name: Reactive Power
      unit_of_measurement: VAr
      slave: 3
      register: 30805
      scale: 1
      precision: 0
      count: 2
      data_type: int
      
  - platform: template
    sensors:
      modbus_sma_pv_power:
        entity_id: sensor.sma_power_ac
        friendly_name: 'Power Output'
        value_template: >-
            {% if states('sensor.sma_power_ac')|float < 0 or states('sensor.sma_power_ac')|float > 10000 %}
              0
            {% else %}
              {{ states('sensor.sma_power_ac') }}
            {% endif %}
        unit_of_measurement: "W"
        icon_template: mdi:flash-circle
      modbus_sma_pv_apparent_power:
        entity_id: sensor.apparent_power
        friendly_name: 'Apparent Power'
        value_template: >-
            {% if states('sensor.apparent_power')|float < 0 or states('sensor.apparent_power')|float > 10000 %}
              0
            {% else %}
              {{ states('sensor.apparent_power') }}
            {% endif %}
        unit_of_measurement: "VA"
        icon_template: mdi:flash-circle
      modbus_sma_pv_reactive_power:
        entity_id: sensor.reactive_power
        friendly_name: 'Reactive Power'
        value_template: >-
            {% if states('sensor.reactive_power')|float < 0 or states('sensor.reactive_power')|float > 10000 %}
              0
            {% else %}
              {{ states('sensor.reactive_power') }}
            {% endif %}
        unit_of_measurement: "VAr"
        icon_template: mdi:flash-circle
      modbus_sma_pv_residual:
        entity_id: sensor.sma_residual_current
        friendly_name: 'Residual Current'
        value_template: >-
            {% if states('sensor.sma_residual_current')|float < 0 or states('sensor.sma_residual_current')|float > 10000 %}
              0
            {% else %}
              {{ states('sensor.sma_residual_current') }}
            {% endif %}
        unit_of_measurement: "mA"
        icon_template: mdi:flash-circle
      modbus_sma_temperature:
        entity_id: sensor.sma_temp
        friendly_name: 'Inverter Temp'
        value_template: >-
            {% if states('sensor.sma_temp')|float < 0 or states('sensor.sma_temp')|float > 100 %}
              0
            {% else %}
              {{ states('sensor.sma_temp') }}
            {% endif %}
        unit_of_measurement: "°C"
      modbus_grid_frequency:
        entity_id: sensor.grid_frequency
        friendly_name: 'Grid Frequency'
        value_template: >-
            {% if states('sensor.grid_frequency')|float < 30 or states('sensor.grid_frequency')|float > 100 %}
              Not Measured
            {% else %}
              {{ states('sensor.grid_frequency') }}
            {% endif %}
        unit_of_measurement: "Hz"
      modbus_grid_voltage:
        entity_id: sensor.grid_voltage
        friendly_name: 'Grid Voltage'
        value_template: >-
            {% if states('sensor.grid_voltage')|float < 180 or states('sensor.grid_voltage')|float > 300 %}
              Not Measured
            {% else %}
              {{ states('sensor.grid_voltage') }}
            {% endif %}
        unit_of_measurement: "V"
      modbus_inverter_status:
        entity_id: sensor.sma_status
        friendly_name: 'Inverter Status'
        value_template: >-
            {% if is_state('sensor.sma_status', '307' ) %}
              OK
            {% elif is_state('sensor.sma_status', '303' ) %}
              Off
            {% elif is_state('sensor.sma_status', '455' ) %}
              Warning
            {% elif is_state('sensor.sma_status', '35' ) %}
              Fault
            {% endif %}
      modbus_grid_contactor:
        entity_id: sensor.sma_grid
        friendly_name: 'Grid contactor'
        value_template: >-
            {% if is_state('sensor.sma_grid', '51' ) %}
              Closed
            {% else %}
              Open
            {% endif %} 
5 Likes

and lovelace a vertical stack which hides most of the values when inverter is not connected to grid:

cards:
  - entities:
      - entity: sensor.modbus_inverter_status
      - entity: sensor.modbus_grid_contactor
    show_header_toggle: false
    title: PV Inverter
    type: entities
  - card:
      entities:
        - entity: sensor.modbus_sma_pv_power
        - entity: sensor.modbus_sma_pv_apparent_power
        - entity: sensor.modbus_sma_pv_reactive_power
        - entity: sensor.pv_daily_yield
        - entity: sensor.pv_total_production
        - entity: sensor.modbus_sma_temperature
        - entity: sensor.modbus_grid_voltage
        - entity: sensor.modbus_grid_frequency
        - entity: sensor.insulation
        - entity: sensor.modbus_sma_pv_residual
      show_header_toggle: false
      type: entities
    conditions:
      - entity: sensor.sma_grid
        state: '51'
    type: conditional
type: vertical-stack

4 Likes

Thanks for sharing mamra.

But i’ve tried to connect via the modbus, i can’t reach my device.
Error:

Connection to (192.168.1.175, 502) failed: timed out

code from configuration.yaml:

modbus:

  • type: tcp
    host: 192.168.1.175
    port: 502

I’m sure that the right IP from my SMA STP 6000TL, because i can read it from my local Sunny Explored connected trough speedwire.

Any idea’s?

Found it…

In the Sunny portal i had to turn on tcp server.

Hello MatijnB,

We bought an second hand inverter with an Webconnect unit. I cant connect by http and my modbus isn’t working to. Can you explain me where you turned on the tcp server?

log into the inverter as an installer, and change the settings under device parameters

I can’t login to an HTTP web interface,
but if i look in the Sunny Explorer there isn’t an option to turn it on. The only option i am seeing is Webconnect : on/off

I am using the SB 3000TLST-21 408 in combination with an SWDM-10 connected to my router.

I have also a WebConnect with only the “SMA Portal”. I don’t have the right to enable Mobius so I looked on how to extract the data directly from SMA Portal as my feed to there is working fine.

I have this under test right now. This is a python script to be executed under “AppDaemon” integration.
Don’t forget to replace xxxxxx & yyyyyy with your credential.

Probably still some debugging needed (I don’t know yet how long I can keep active my session, I try a check every 5 min and a logon once per hour.

from bs4 import BeautifulSoup
import requests
import json
import time
from datetime import datetime
import appdaemon.plugins.hass.hassapi as hass

class sma_bridge(hass.Hass):

    def initialize(self):
        self.log("Initialize sma_bridge")    

        self._loginskip = 0

        self._handler5 = None
        self.run_at_sunset( self.sunset, offset = -30 * 60)
        self.run_at_sunrise(self.sunrise, offset =   30 * 60)
        
        if self.sun_up():
            self.sunrise("")
        else:
            self.set_state("sensor.sma_power",state = 0)

        self.log("End sma_bridge")

    def sunrise(self, kwargs):
        self.log("sma_bridge: Sunrise")
        tickstart = datetime.now()
        if self._handler5 == None:
            self._handler5 = self.run_every(self.run_every_c, tickstart, 5 * 60)
    
    def sunset(self,kwargs):
        self.log("sma_bridge: Sunset")
        if self._handler5 != None:
            self.cancel_timer(self._handler5)
            self._handler5 = None
        self.set_state("sensor.sma_power",state = 0)

    def run_every_c(self, kwargs):
        myj = self.getSMAData()

        power = str(myj["PV"])

        if power.isnumeric():

            old_state = self.get_state(entity="sensor.sma_power")

            if old_state != power:
                self.set_state("sensor.sma_power",state = power, attributes = myj)
        else:
            self._session = None


    # For login: logout https://www.sunnyportal.com/Templates/Start.aspx?logout=true
    # To Fetch data: https://www.sunnyportal.com/Dashboard
    # Example 1: {"__type":"LiveDataUI","Timestamp":{"__type":"DateTime","DateTime":"2020-04-10T09:27:00","Kind":"Unspecified"},"PV":2688,"FeedIn":null,"GridConsumption":null,"DirectConsumption":null,"SelfConsumption":null,"SelfSupply":null,"TotalConsumption":null,"DirectConsumptionQuote":null,"SelfConsumptionQuote":null,"AutarkyQuote":null,"BatteryIn":null,"BatteryOut":null,"BatteryChargeStatus":null,"OperationHealth":{"__type":"StateOfHealth","Ok":1,"Warning":0,"Error":0,"Unknown":0},"BatteryStateOfHealth":null,"ModuleTemperature":null,"EnvironmentTemperature":null,"WindSpeed":null,"Insolation":null,"BatteryMode":null,"InfoMessages":[],"WarningMessages":[],"ErrorMessages":[],"Info":{}}
    # Example 2: {"__type":"LiveDataUI","Timestamp":{"__type":"DateTime","DateTime":"2020-04-10T09:47:04","Kind":"Unspecified"},"PV":null,"FeedIn":null,"GridConsumption":null,"DirectConsumption":null,"SelfConsumption":null,"SelfSupply":null,"TotalConsumption":null,"DirectConsumptionQuote":null,"SelfConsumptionQuote":null,"AutarkyQuote":null,"BatteryIn":null,"BatteryOut":null,"BatteryChargeStatus":null,"OperationHealth":null,"BatteryStateOfHealth":null,"ModuleTemperature":null,"EnvironmentTemperature":null,"WindSpeed":null,"Insolation":null,"BatteryMode":null,"InfoMessages":[],"WarningMessages":[],"ErrorMessages":[],"Info":{}}

    #############################
    #
    #       SMA Portal 
    #
    #############################
    def _Login(self):

        if self._loginskip > 0 and self._session != None:
            self._loginskip -=1
            
        else:
            self._loginskip = 12

            session = requests.session()
            url ="https://www.sunnyportal.com/Templates/Start.aspx?logout=true&ReturnUrl=%2fFixedPages%2fDashboard.aspx"

            response = session.get(url)
            myhtml = response.content
            soup = BeautifulSoup(myhtml,'html.parser')

            x = soup.find("input", {"id" : "__VIEWSTATE"} )
            viewstate = x['value']

            x = soup.find("input", {"id" : "__VIEWSTATEGENERATOR"} )
            viewstategenerator = x['value']

            parameters= {
                '__EVENTTARGET':'',
                '__EVENTARGUMENT':'',
                '__VIEWSTATE':viewstate,
                '__VIEWSTATEGENERATOR':viewstategenerator,
                'ctl00$ContentPlaceHolder1$Logincontrol1$txtUserName':'[email protected]',
                'ctl00$ContentPlaceHolder1$Logincontrol1$txtPassword':'yyyyyyyyyyyyyyyyy',
                'ctl00$ContentPlaceHolder1$Logincontrol1$LoginBtn':'Login',
                'ctl00$ContentPlaceHolder1$Logincontrol1$RedirectURL':'',
                'ctl00$ContentPlaceHolder1$Logincontrol1$RedirectPlant':'',
                'ctl00$ContentPlaceHolder1$Logincontrol1$RedirectPage':'',
                'ctl00$ContentPlaceHolder1$Logincontrol1$RedirectDevice':'',
                'ctl00$ContentPlaceHolder1$Logincontrol1$RedirectOther':'',
                'ctl00$ContentPlaceHolder1$Logincontrol1$PlantIdentifier':'',
                'ctl00$ContentPlaceHolder1$Logincontrol1$ServiceAccess':'true',
                'ctl00$ContentPlaceHolder1$Logincontrol1$MemorizePassword':'on',
                'ClientScreenWidth':2048,
                'ClientScreenHeight':1152,
                'ClientScreenAvailWidth':2048,
                'ClientScreenAvailHeight':1112,
                'ClientWindowInnerWidth':2048,
                'ClientWindowInnerHeight':1010,
                'ClientBrowserVersion':65,
                'ctl00$ContentPlaceHolder1$hiddenLanguage':'en-us'
                }

            myheaders = {
                'Accept': '*/*',
                'Accept-Encoding': 'gzip, deflate, br',
                'Accept-Language': 'en-US,en;q=0.9,fr;q=0.8',
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36',
                'X-Requested-With': 'XMLHttpRequest'
                }

            response = session.post(url,parameters,headers=myheaders)

            if response.status_code == 200:
                self.log ("SMA Logon :" + str(response.status_code))
                self._session = session
            else:
                self.log("Error SMA Login:" + str(response.status_code))
                self._session = None

        return self._session

    def getSMAData(self):
        session = self._Login()
        url="https://www.sunnyportal.com/Dashboard"
        myheaders = {
            'Accept': '*/*',
            'Accept-Encoding': 'gzip, deflate, br',
            'Accept-Language': 'en-US,en;q=0.9,fr;q=0.8',
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36',
            'X-Requested-With': 'XMLHttpRequest'
            }
        
        response = session.get(url,headers=myheaders)
        if response.status_code == 200:
            myhtml = response.content
            myj = json.loads(myhtml)
            self.log("getSMAData:" + str(myj))
        else:
            self.log ("Error SMA getSMAData:" + myhtml)
            myj = {"PV": "Error"}
        return myj

i know it’s been a while since you posted your config. but i implemented it today, and it is working fine for all values, exept for PV Daly Yield

name: PV Daily Yield
unit_of_measurement: kWh
slave: 3
register: 30517
scale: 0.001
precision: 3
count: 4
data_type: uint

image
the PV total production is totaly correct, but the daily yield should be around 0.361kWh but is showing something completely different. could it be a wrong register? is there a way to find our the correct register?

i’m completely new at modbus. but you code works fine, except for that value

i anyone could help me out… thanks.

What model of inverter do you have? Download from sma site >support >downloads under your inverter range the excel file of modbus… Check there what register is the daily yield
Also check the total production register. It seems low

Andreas, thank you for your reaction. the total production is oké, the solar panels have been installed a few days ago, so that explains the low value…

i have a Sunny Boy 3.0, SB3.0-1AV-41 575.
i found the list you mean, in html format. https://files.sma.de/downloads/MODBUS-HTML_SBxx-1AV-41-V11.zip

my current register in my config file is:

    - name: PV Daily Yield
      unit_of_measurement: kWh
      slave: 3
      register: 30517
      scale: 0.001
      precision: 3
      count: 4
      data_type: uint

so the register number seems correct.

do i have to change other register values, if i would like to try register 30537.
do i have to do anything with “Number of contiguous SMA registers” = 2 and “Data type SMA” = U32

do i have to change something to “data_type: uint”

Sma registers == count so you have to Change to 2.

thanks but doesn"t seem to work, i’ll have te look into it a bit more.
when i try count 2, i have this:

    - name: PV Dagelijkse opbrengs
      unit_of_measurement: kWh
      slave: 3
      register: 30535
      count: 2
      scale: 0.01
      precision: 2
      data_type: uint

but i just keep getting -0,001kw

Weird…

your settings seem correct:
u16 ( count 1) or 32 ( count 2) or 64 (count 4) are for unsigned words
FIX0 is decimal number with no decimal space
data type is uint (unsigned integer)

try again register 30517:

    - name: PV Daily Yield
      unit_of_measurement: kWh
      slave: 3
      register: 30517
      scale: 0.001
      precision: 3
      count: 4
      data_type: uint

if that doesn’t work try sunspec registers at slave:126