Solaredge inverter via Modbus TCP 2

Alright, so you have two problems at once now.

The box that you know works with generic Modbus does not work with Sunspec. Leave that for a minute, you know you can go back to generic.

The other box does not work with Sunpec, but is unknown about generic Modbus.
Try that out.- get some confidence in your id numbers and topology.

It looks to me like Sunspec feature needs enabling on these boxes, though it is not clear to me if that needs doing only on "Leader"or also on “Follower” boxes.

Sorry to say, but I have the same issues using the “genric” modbus configuration. The Bridge with ID=2 always has SocketTimeoutException. Thus no difference (even though checking all parameters twice).

I think I will add a separate netwok cable to the second inverter with own IP address and Modbus over IP activation. All other scenarios are not working for me.

Thanks to all who supported me.

Hi @shotte,

I think I cannot give you more hints on this as I have only one inverter and one meter connected to the inverter by RS485.

Possibly it is this, basically:

Potentially it is a SunSpec limitation.

Maybe you can ask the SolarEdge support on this?
I had luck with several more detailed questions where I got answers by the support team.

Jonathan

Excellent work here - thx. What I’m still missing is - what has already been requested above: Support of solarstore. I have a Solaredge inverter with a BYD Battery and I can easily read the battery state with python:

#!/usr/bin/python
import sys
import os
import time
import getopt
import socket
#import ConfigParser
import struct
import binascii

ipaddress = str(sys.argv[1])
from pymodbus.client.sync import ModbusTcpClient

client = ModbusTcpClient(ipaddress, port=502)

rr = client.read_holding_registers(62836, 2, unit=1)
raw = struct.pack('>HH', rr.getRegister(1), rr.getRegister(0))
storagepower = int(struct.unpack('>f', raw)[0])

print("speicherleistung: {0} W".format(storagepower))

rr = client.read_holding_registers(62852, 2, unit=1)
raw = struct.pack('>HH', rr.getRegister(1), rr.getRegister(0))
soc = int(struct.unpack('>f', raw)[0])

print("Ladestand: {0}%".format(soc))

So it looks like I would just have to read the register 62836 with the openhab Modbus
plugin, too. But all my tries faulted right now. I don’t get any readings. This is what I’ve tried:

    Bridge poller BatteryRegisters [ start=62836, length=2, refresh=5000, type="holding" ] {
        Thing data I_Battery            [ readStart="62836", readValueType="int16"] 
    }

I already tried with 2836 or 22836 with no success. Maybe the type=“holding” has to be adjusted to point the unspecified 60xxx area?

Does somebody know how to achieve the same python readings using openhab Modbus?

You are reading two registers in python and combining them. However, in openHAB you seem to read only one register as integer…as is, you would not get the same results. You probably want to use float32_swap or float32 readValueType

What I can tell pymodbus has same numbering convention than the binding, l.e. Addresses start as zero. So 62836 should be OK.

What do you mean when you say "all my tries faulted right now "? Give us the error message and it is easier to help

1 Like

Thanks for the questions. That led me to double check my whole configuration. And it turns out that simply my item was not correctly configured.

So for all others, this is how you can get your BYD Battery State from your Solaredge inverter:

Things-Config:

    Bridge poller BatteryRegisters [ start=62836, length=18, refresh=5000, type="holding" ] {
        Thing data I_Battery            [ readStart="62836", readValueType="float32_swap"]     // Batterieleistung
        Thing data I_Battery_SOC        [ readStart="62852", readValueType="float32_swap"]     // Batterie Ladestand
    }

Item-Config:

Number:Power    SE2k_I_Battery          "PV Battery Leistung [%.2f W]"  <energy>        (gSE2K) {channel="modbus:data:SolarEdgeConverter:BatteryRegisters:I_Battery:number", autoupdate="false"}
Number          SE2k_I_Battery_SOC      "PV Battery Akkustand [%d %%]"  <energy>        (gSE2K) {channel="modbus:data:SolarEdgeConverter:BatteryRegisters:I_Battery_SOC:number", autoupdate="false"}

I’m not quite sure if the conversion with float32_swap is correct. But at least right now it looks ok.

Hi @dhermanns ,

I have a little different configiuration. My battery is connected via 4K SolarEdger inverter an I get the information using this (last lines are commented out due to lack on information):

Bridge modbus:tcp:SE4K "PV Bridge ID1" [ host="x.y.z", port=502, id=1, timeBetweenTransactionsMillis=60, timeBetweenReconnectMillis=0, connectMaxTries=3, reconnectAfterMillis=0, connectTimeoutMillis=5000, enableDiscovery=true ]
{
    Bridge poller RegistersBattery  [ start=62784, length=120, refresh=5000, type="holding" ] {
        Thing data B_Battery_ID                     [ readStart="62785", readValueType="uint16" ]       // 
        Thing data B_RatedEnergy                    [ readStart="62787", readValueType="float32" ]      // 
        Thing data B_MaxChargeContinuesPower        [ readStart="62789", readValueType="float32" ]      // 
        Thing data B_MaxDischargeContinuesPower     [ readStart="62791", readValueType="float32" ]      // 
        Thing data B_MaxChargePeakPower             [ readStart="62793", readValueType="float32" ]      // 
        Thing data B_MaxDischargePeakPower          [ readStart="62795", readValueType="float32" ]      // 
        // next 32 registers are reserved
        Thing data B_AverageTemperature             [ readStart="62829", readValueType="float32" ]      // 
        Thing data B_MaxTemperature                 [ readStart="62831", readValueType="float32" ]      // 
        Thing data B_InstantaneousVoltage           [ readStart="62833", readValueType="float32" ]      // 
        Thing data B_InstantaneousCurrent           [ readStart="62835", readValueType="float32" ]      // 
        Thing data B_InstantaneousPower             [ readStart="62837", readValueType="float32" ]      // 
        Thing data B_LifetimeExportEnergyCounter    [ readStart="62839", readValueType="uint64" ]       // 
        Thing data B_LifetimeImportEnergyCounter    [ readStart="62843", readValueType="uint64" ]       // 
        Thing data B_MaxEnergy                      [ readStart="62847", readValueType="float32" ]      // 
        Thing data B_AvailableEnergy                [ readStart="62849", readValueType="float32" ]      // 
        Thing data B_StateOfHealth                  [ readStart="62851", readValueType="float32" ]      // 
        Thing data B_StateOfEnergy                  [ readStart="62853", readValueType="float32" ]      // 
        Thing data B_Status                         [ readStart="62855", readValueType="float32" ]      // 
        Thing data B_StatusInternal                 [ readStart="62857", readValueType="float32" ]      // 
//      Thing data B_EventsLog0                     [ readStart="62859.0", readValueType="uint16" ]     // 
//      Thing data B_EventsLog1                     [ readStart="62859.1", readValueType="uint16" ]     // 
//      Thing data B_EventsLog2                     [ readStart="62859.2", readValueType="uint16" ]     // 
//      Thing data B_EventsLog3                     [ readStart="62859.3", readValueType="uint16" ]     // 
//      Thing data B_EventsLog4                     [ readStart="62859.4", readValueType="uint16" ]     // 
//      Thing data B_EventsLog5                     [ readStart="62859.5", readValueType="uint16" ]     // 
//      Thing data B_EventsLog6                     [ readStart="62859.6", readValueType="uint16" ]     // 
//      Thing data B_EventsLog7                     [ readStart="62859.7", readValueType="uint16" ]     // 
    }
}

Maybe it helps :wink:

Hi all
Sorry for rising up this thread. But I have one question regarding this implementation.

I set up a SolarEdge and Energy Meter using Modbus Sunspec. (Coming from a Kostal, which was much better and much more modern regarding the interfaces etc. and the OH Binding is great.)
It works ok so far, with one exeption.

How do you prevent the “timeouts” respectively the poller things go offline because of the two different modbus poller (Inverter and energy meter block)? If they read nearly at the same time, one of them is blocked and goes offline.
It seems that the two pollers do not need the same amount of time to read and thus at some point they try to read at nearly the same time.
Is there a possibility to arrange the two pollers which have to connect to the same modbus tcp slave (Inverter)?

There is timeBetweenTransactionsMillis parameter in the tcp thing to control silent period between different requests to the same host. Modbus - Bindings | openHAB thing

Default is 60ms but perhaps it is too short time for the device to recover.

Would that work out?

EDIT: @rossko57 has also written great write-up of different parameters and considerations in Modbus performance management in openHAB 2

1 Like

Hi ssalonen

Thank you for this.
I will try to set a higher value and report back.

Update
I used 200ms instead of 60 and 2 connection tries instead of 1 and it seems to be better.
However the log still states many errors but there are MUCH less.
It seems the Solaredge is really slow, so maybe I have to go higher than 200ms to prevent the errors in the logfile…

Update2
Still no more things going offline, thats the good message.
But still some connection errors in the logfile, even if I only use one Thing(Poller).It happens especially a lot more frequently during night but sometimes also during day:

2021-12-28 05:57:51.252 [WARN ] [rt.modbus.internal.ModbusManagerImpl] - Try 1 out of 10 failed when executing request (ModbusReadRequestBlueprint [slaveId=1, functionCode=READ_MULTIPLE_REGISTERS, start=40069, length=50, maxTries=10]). Will try again soon. Error was I/O error, so reseting the connection. Error details: net.wimpi.modbus.ModbusIOException I/O exception: SocketException Connection reset [operation ID 135e1e47-19f2-4674-9c38-a0ebe6be752a]

2021-12-28 05:57:51.258 [WARN ] [ing.ModbusSlaveConnectionFactoryImpl] - connect try 1/2 error: Connection refused (Connection refused). Connection TCPMasterConnection [m_Socket=Socket[unconnected], m_Timeout=3000, m_Connected=false, m_Address=/“InverterIP”, m_Port=1502, m_ModbusTransport=null, m_ConnectTimeoutMillis=10000, rtuEncoded=false]. Endpoint ModbusIPSlaveEndpoint [address=“InverterIP”, port=1502]

Anyone else seeing this Warnings using Modbus with SolarEdge?
I’m also using Modbus for my Stiebel Eltron Heating and there I do not have any warnings. However, I perform a less frequent reading. 90s vs. 5s on SolarEdge.

1 Like

Hi,

my solaredge single phase inverter (SE5000H) works fine, but my logfile is full of events. I tried to change the log-level of modbus binding with “log:set WARN org.openhab.binding.modbus”.

The changed log-level is in log4j.xml:

		<Logger level="WARN" name="org.openhab.binding.modbus"/>
		<Logger level="WARN" name="org.openhab.core.io.transport.modbus"/>

but my logfile is still full of INFO messages:

2022-03-25 19:32:40.862 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'SinglePhaseInverter_ACFrequencyValue' changed from 50.011 Hz to 50.013 Hz
2022-03-25 19:32:40.869 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'SinglePhaseInverter_ACVoltage' changed from 230.9 V to 231.1 V
2022-03-25 19:33:00.957 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'SinglePhaseInverter_HeatSinkTemperature' changed from 22.88 °C to 22.86 °C
2022-03-25 19:33:00.985 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'SinglePhaseInverter_ACFrequencyValue' changed from 50.013 Hz to 50.011 Hz
2022-03-25 19:33:00.986 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'SinglePhaseInverter_ACVoltage' changed from 231.1 V to 230.8 V
2022-03-25 19:33:21.045 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'SinglePhaseInverter_HeatSinkTemperature' changed from 22.86 °C to 22.84 °C
2022-03-25 19:33:21.074 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'SinglePhaseInverter_ACFrequencyValue' changed from 50.011 Hz to 50.003 Hz
2022-03-25 19:33:21.077 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'SinglePhaseInverter_ACVoltage' changed from 230.8 V to 231.2 V

Any idea how to control that?

Hi @Barnecke,

the INFO messages are the standard openhab.event.ItemStateChangedEvent log entries.

I have set up an additional filter in the log4j.xml for preventing the logs to be spammed by high frequency readouts of the power values (solaredge inverter and meter, grid meter):

Add this to your log4j.xml in the section <Appenders> and replace the property regex by your needs (Item names or parts of the Items names)

<!-- Rolling file appender -->
		<RollingFile fileName="${sys:openhab.logdir}/openhab.log" filePattern="${sys:openhab.logdir}/openhab.log.%i.gz" name="LOGFILE">
			<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%-5.5p] [%-36.36c] - %m%n"/>
			<!--<RegexFilter onMatch="DENY" onMismatch="ACCEPT" regex=".*(SolarEdgeSE2200Inverter_|SolarEdgeWattNodeMeter_|SE2KM_|StromzahlerEMHSmartMeter_).*"/>-->
			<RegexFilter onMatch="DENY" onMismatch="ACCEPT" regex=".*(SolarEdgeSE2200Inverter_|SolarEdgeWattNodeMeter_|SE2KM_|StromzahlerEMHSmartMeter_|RaspiSysteminfo_|OpenHABianPiSysInfo_).*"/>
			<Policies>
				<OnStartupTriggeringPolicy/>
				<SizeBasedTriggeringPolicy size="16 MB"/>
			</Policies>
			<DefaultRolloverStrategy max="7"/>
		</RollingFile>

		<!-- Event log appender -->
		<RollingRandomAccessFile fileName="${sys:openhab.logdir}/events.log" filePattern="${sys:openhab.logdir}/events.log.%i.gz" name="EVENT">
			<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%-5.5p] [%-36.36c] - %m%n"/>
			<!--<RegexFilter onMatch="DENY" onMismatch="ACCEPT" regex=".*(SolarEdgeSE2200Inverter_|SolarEdgeWattNodeMeter_|SE2KM_|StromzahlerEMHSmartMeter_).*"/>-->
			<RegexFilter onMatch="DENY" onMismatch="ACCEPT" regex=".*(SolarEdgeSE2200Inverter_|SolarEdgeWattNodeMeter_|SE2KM_|StromzahlerEMHSmartMeter_|RaspiSysteminfo_|OpenHABianPiSysInfo_).*"/>
			<Policies>
				<OnStartupTriggeringPolicy/>
				<SizeBasedTriggeringPolicy size="16 MB"/>
			</Policies>
			<DefaultRolloverStrategy max="7"/>
		</RollingRandomAccessFile>

Cheers
Jonathan

Hi @Levin1,

I also have the connection problems sometimes. But it is very sporadically and I was not able to find any type of time scheme or if there are some events driving the connection errors. I think, the occurences are not more than 4-5 times a week.

My settings are:

Bridge:

UID: modbus:tcp:solaredgebridge
label: SolarEdge Modbus TCP Bridge
thingTypeUID: modbus:tcp
configuration:
  rtuEncoded: false
  timeBetweenTransactionsMillis: 60
  connectMaxTries: 1
  reconnectAfterMillis: 0
  port: 502
  timeBetweenReconnectMillis: 0
  host: 192.168.x.y
  connectTimeoutMillis: 10000
  id: 1
  enableDiscovery: true
location: HWR

Inverter:

UID: modbus:inverter-single-phase:solaredgeinverter:40069
label: SolarEdge  SE2200 Inverter
thingTypeUID: modbus:inverter-single-phase
configuration:
  length: 61
  refresh: 5
  maxTries: 3
  address: 40000
bridgeUID: modbus:tcp:solaredgebridge

Meter:

UID: modbus:meter-wye-phase:solaredgemeter
label: SolarEdge WattNode Meter
thingTypeUID: modbus:meter-wye-phase
configuration:
  length: 61
  refresh: 5
  maxTries: 3
  address: 40000
bridgeUID: modbus:tcp:solaredgebridge

I will not change the settings, as I can live with the sporadic connection errors.

Cheers
Jonathan

You are hammering the Modbus as fast as it will go, That means to re-read the data very 5 milliseconds.

Luckily, the binding is smart enough to discard duplicate queued read-polls, or else your system would collapse with a huge queue of polls awaiting bus access.
It’s probably managing to read every 50mS or so.
I’d say from your useful log snippet that the target device is only changing its data every 20 seconds or so, so there’s no point reading it more often than that.

I reckon you do about ten million read polls in that time, so that’s a pretty good error rate.

Hi @rossko57,

This is simply not true as the Sunspec addon of the Modbus binding defines the refresh parameter of the Things in seconds (see documentation here: SunSpec - Bindings | openHAB)

I am reading the data every 5 seconds and the values are changing a bit more often I think. But 5 seconds is a good value to observe and track energy data.

Cheers
Jonathan

Quite right - I had missed the sunspec type Thing. I’m wrong.

Thanks, good solution. I though I can control it with debug-level, but this works.

This is interesting because your config looks almost default.
With default values my Inverter/Meter things went offline again and again.

Different to you I have a three phase inverter.
And I start reading at 40069 for 50 entries, but that should not make the difference.

But maybe more important, I used the delta connected Meter and I have to read another Modbus Block for live usage (40188, length 105). Why are you reading the same values for the meter as for your inverter?

Hello, from about two weeks my connection with solaredge inverter isnt working anymore.

2022-06-27 13:37:23.551 [WARN ] [ing.ModbusSlaveConnectionFactoryImpl] - connect try 1/3 error: Połączenie odrzucone (Connection refused). Connection TCPMasterConnection [m_Socket=Socket[unconnected], m_Timeout=3000, m_Connected=false, m_Address=/192.168.31.47, m_Port=1502, m_ModbusTransport=null, m_ConnectTimeoutMillis=5000, rtuEncoded=false]. Endpoint ModbusIPSlaveEndpoint [address=192.168.31.47, port=1502]

Maybe someone have same problem and got solution??

Hi,
I got this error when inverter is not connected to network or internet.

Did you get actual information in solaredge app?

Try to restart inverter.

good luck