Reading Data from Solaredge inverters via Modbus TCP

I created this Thing for the Modbus TCP Slave:

UID: modbus:tcp:SE5000TCP
label: SolarEdge Modbus TCP Slave
thingTypeUID: modbus:tcp
configuration:
  rtuEncoded: false
  timeBetweenTransactionsMillis: 1000
  connectMaxTries: 3
  reconnectAfterMillis: 500
  port: 1502
  timeBetweenReconnectMillis: 1000
  host: solaredge
  connectTimeoutMillis: 10000
  id: 1
  enableDiscovery: true

This went instantly online. Then the scan discovered my inverter and my smart meter. I accepted them:

Their channels show up for further configuration.

The SolarEdge monitoring is still working. One restriction is that Modbus allows only one client at a time and has a session timeout limit of 2 minutes. So concurrent access from both Things and the SolarEdge solution can produce access errors. I tried to reduce this risc by setting long and different access intervals for my things.

It looks as if the battery is still missing. I did not look at that open issue yet.

This is all only 2 days old, so further issues might raise.

Regards Christoph

1 Like

Thanks,
this has been working! Over Ethernet… No WiFi anymore.
As I read on another forums - they ended support for Modbus TCP over WiFi with latest firmware.
New reply from SolarEdge support:

the escalation has been returned from our Tier2.
Unfortunately also our Tier2 told me that Modbus over TCP can be done through LAN or RS485 only.
There is not possible to have it over Wi-Fi and if there is some way how to do it we do not support it.
Thank you for your understanding.

So now on, Ethernet only. Maybe we should start to send some more tickets to SE support :face_with_hand_over_mouth:

They may have security concerns, remembering they sell to commercial users too and have liability.

2 Likes

Hi tkuehne, are you still alive ?
My SE inverter was starting now and I’m interested in reading the optimizers. Before starting with this stuff here, I want to know, if your method still is valid.

BR
maksimilian

Yes, reports of my death are greatly exaggerated to quote Mark Twain ;). The method still works. You need to have a wired connection (Ethernet cable) to the inverter according the latest posts above.

However, the data set will not show you any data about individual optimizers (see Sunspec technical documentation). You will be able to read production data from the inverter and if you have a Modbus Smartmeter connected to the inverter, you will also be able to read the grid feed-in data from the Smartmeter.

Follow the other threads about this, and use the Modbus V2 binding, would be my recommendation.

For my own installation, I have switched from reading the data directly from OpenHAB, to a component called MBMD (Link) to connect to the inverter via Modbus and publish the data to MQTT. OpenHAB is then subscribing to the MQTT data. Works perfectly and allows other devices to subscribe to MQTT and get the data as well.

Best,

Thomas

Thank’s for your resurrection, Thomas :slightly_smiling_face: Sorry for disturbing your deathlike. I was misunderstanding this thread. It was clear to me not finding optimizer data in modbus registers. The only method I have knowledge of is that of bruehl. But I don’t know if it still is working because of possibly meanwhile coded communication between inverter and SE.

BR

Hi Thomas hi community,
The SE inverters come with an really powerfull implementated power control feature via modbus TCP which allows you to control the whole inverter.
There’s a description out in the net (Technical Note – Power Control Protocol for SolarEdge Inverters).
The base register for controlling the inverter is F000. You can directly change almost all parameters including the charge behaviour of a connected battery (in my case LG Resu), which is a really great benefit.
As most of you know the one tricky problem on SE inverters is that you can’t access all data (inverter data, meter data and the power control registers) in one sequence. Does anybody think there’s a chance to get the modbus binding updated that it will be possible to read/write all possible registers of an SE inverter?

Thanks a lot

Max

I’m glad I put my main switch in the garage then! Lots of spare Cat6 around too.

1 Like

I think i recently read about Wifi support in a recent SolarEdge firmware. If someone needs this, you should review the release notes.

As MaxEn wrote it is tricky to read the values and align them (Inverter and meter values). I don’t think a Modbus update can fix this, but I’m not an expert. If someone has methods to align the values, I’m happy to hear them.
In my case, I read the values every 5 Seconds (inverter and meter). If the AC-Power changes quickly because of clouds, the meter values are not aligned so my calculation about available PV-Power are not correct for a few moments. This is especially the case on days where the conditions/cloudiness change often.

Hi there

I am the author of thesolaredge binding. As the cloud API has become quite unreliable (data updated only once in 5-10minutes) I am currently considering a change to the modbus binding. I was able to get the basic setup working but compared to my solaredge binding there are some metrics missing, e.g.

  • battery SOC
  • battery charge / discharge rate

most other values can be retrieved via some simple calculations but without battery data I will never know if the inverter drains the battery or if all the power comes from current production. Any hint on how to get battery data? I have a SE5000H with Tesla Powerwall connected via StorEdge unit. This seems to be a rare setup…

Thanks

Hello Alex,

Unfortunately, I don’t have any experience with battery systems. I would assume that one should be able to read such data from the BMS if it exposes those values somehow. That type of solution would be specific to each battery model, i guess.

Other than that, my next bet would be to look at the sunspec definition for the StorEdge and see if it implements those readings via modbus.

If both won’t work, then I have no idea, really.

Best,

Thomas

Solaredge is another sad story about inverter vendors unwilling to provide local access so good luck.
When you google you’ll see any Home Automation system dev seems to be fighting with this, have not seen a good solution to date.

There’s registers in the following link but seems it does not work for the hybrid models.

Battery control

I’m selling a commercial energy management system based on openHAB (if you want to try the free demo let me know, you can extract the openHAB config from there) and I’ve also tried to control battery.
But I have no Solaredge system to test against. So if anyone on this thread is willing to try this out and refine I’d be grateful.

Below is the essence you’ll need for that, extracted from this source. There’s a link to the Solaredge Power Control documentation over there, too.

Bridge modbus:tcp:SolarEdgeBatteryInverter "SolarEdge SE inverter" [ host="%IP", port=502, id=%MBID, timeBetweenTransactionsMilli=60, timeBetweenReconnectMillis=0, connectMaxTries=3, reconn
ectAfterMillis=0, connectTimeoutMillis=5000 ] {

    // E004 (F704) 1 R/W Storage Control Mode Uint16 0-4 N/A                    4 = externe Batt.steuerung
    // E005 (F705) 1 R/W Storage AC Charge Policy Uint16 0-3 N/A
    // E006 (F706) 2 R/W Storage AC Charge Limit Float32 0-Max_Float KWh or %
    // E008 (F708) 2 R/W Storage Backup Reserved Setting Float32 0-100 %
    // E00A (F70A) 1 R/W Storage Charge/Discharge Default Mode Uint16 0-7 N/A   0 = off, 3,4 = sharge/discharge, 7 = max. self consumption (default)
    // E00B (F70B) 2 R/W Remote Control Command Timeout Uint32 0-86400(24h) Sec
    // E00D (F70D) 1 R/W Remote Control Command Mode Uint16 0-7 N/A
    // E00E (F70E) 2 R/W Remote Control Charge Limit Float32 0- Battery Max Power W
    // E010 (F710) 2 R/W Remote Control Command Discharge Limit Float32 0- Battery Max Power W

    Bridge poller SolarEdge-battery "SolarEdge battery control poller" [ start=57348, length=50, refresh=5000, type="holding" ] {
        Thing data SEStorageControlMode                 [ readStart="57348", readValueType="int16", writeStart="57348", writeValueType="int16" ]                // 0xE004
        Thing data SEStorageChargeDischargeDefaultMode  [ readStart="57354", readValueType="int16", writeStart="57354", writeValueType="int16" ]                // 0xE00A
        Thing data SERemoteControlCommandTimeout        [ readStart="57355", readValueType="int32_swap", writeStart="57355", writeValueType="int32_swap" ]      // 0xE00B
        Thing data SERemoteControlCommandMode           [ readStart="57357", readValueType="int16", writeStart="57357", writeValueType="int16" ]                // 0xE00D
        Thing data SERemoteControlChargeLimit           [ readStart="57358", readValueType="float32_swap", writeStart="57358", writeValueType="float32_swap" ]  // 0xE00E
        Thing data SERemoteControlDischargeLimit        [ readStart="57360", readValueType="float32_swap", writeStart="57360", writeValueType="float32_swap" ]  // 0xE010
    }



// Storage Control Mode E004 muss (statisch!)auf 4 (=remote = externe Batterie-Steuerung) gesetzt sein
// => bei Initialisierung in rule setzen

// In solaredge.rules :
// Bei EMSModus := 2:
// PVRemoteControlTimeout setzen mit festem Wert 300(sec)?
// PVRemoteControlMode setzen mit 3/4 (charge/discharge)
// PVCharge[Discharge]Limit setzen

// Bei EMSModus := 0:
// PVChargeMode := 7 (max. self consumption)
}

Thanks! This was really useful.

Using your information especially the linked specification I was able to read the missing data:

battery SOC (percent)
byttery current power (W) - charge/discharge rate
battery status - idle, charging, discharging, etc

Can you share your .things and .items please ?

things

Bridge      modbus:tcp:solaredge                               "Solaredge Modbus"                                                       [ host="solaredge.lan", port=502, id=1, enableDiscovery=true ]
{
    Bridge      poller battery                                     "SolarEdge Battery"                                                      [ start=57664, length=90, refresh=15000, type="holding" ] //0xE140 - 0xE19A
    {
        Thing       data batteryTemperature                            "SolarEdge Battery Temperature"                                          [ readStart="57708", readValueType="float32_swap" ]   // 0xE16C
        Thing       data batteryPower                                  "SolarEdge Battery Current Power"                                        [ readStart="57716", readValueType="float32_swap" ]   // 0xE174
        Thing       data batteryLifetimeExport                         "SolarEdge Battery Lifetime Export"                                      [ readStart="57718", readValueType="int64_swap" ]     // 0xE176
        Thing       data batteryLifetimeImport                         "SolarEdge Battery Lifetime Import"                                      [ readStart="57722", readValueType="int64_swap" ]     // 0xE17A
        Thing       data batteryMaxEnergy                              "SolarEdge Battery Max Energy"                                           [ readStart="57726", readValueType="float32_swap" ]   // 0xE17E
        Thing       data batteryAvailableEnergy                        "SolarEdge Battery Available Energy"                                     [ readStart="57728", readValueType="float32_swap" ]   // 0xE180
        Thing       data batterySOH                                    "SolarEdge Battery SOH"                                                  [ readStart="57730", readValueType="float32_swap" ]   // 0xE182
        Thing       data batterySOE                                    "SolarEdge Battery SOC"                                                  [ readStart="57732", readValueType="float32_swap" ]   // 0xE184
        Thing       data batteryStatus                                 "SolarEdge Battery Status"                                               [ readStart="57734", readValueType="int32_swap" ]     // 0xE186
    }
}
Thing       modbus:inverter-single-phase:solaredge:se5000h     "SolarEdge SE5000H"                    (modbus:tcp:solaredge)            [ address=40069, length=52, refresh=15 ]
Thing       modbus:meter-wye-phase:solaredge:meter             "SolarEdge Meter"                      (modbus:tcp:solaredge)            [ address=40188, length=107, refresh=15 ]

items

Number:Power            SE_TOTAL_POWER           "Total Real Power [%.2f kW]"                             <energy>                                             { unit="kW", channel="modbus:meter-wye-phase:solaredge:meter:acGeneral#ac-total-real-power" }
Number:Power            SE_P1_POWER              "Phase 1 Real Power [%.2f kW]"                           <energy>                                             { unit="kW", channel="modbus:meter-wye-phase:solaredge:meter:acPhaseA#ac-real-power" }
Number:Power            SE_P2_POWER              "Phase 2 Real Power [%.2f kW]"                           <energy>                                             { unit="kW", channel="modbus:meter-wye-phase:solaredge:meter:acPhaseB#ac-real-power" }
Number:Power            SE_P3_POWER              "Phase 3 Real Power [%.2f kW]"                           <energy>                                             { unit="kW", channel="modbus:meter-wye-phase:solaredge:meter:acPhaseC#ac-real-power" }
Number:Energy           SE_LT_IMPORT             "Lifetime Import [%.1f kWh]"                             <carbondioxide>                                      { unit="kWh", channel="modbus:meter-wye-phase:solaredge:meter:acGeneral#ac-total-imported-real-energy" }
Number:Energy           SE_LT_EXPORT             "Lifetime Export [%.1f kWh]"                             <piggybank>                                          { unit="kWh", channel="modbus:meter-wye-phase:solaredge:meter:acGeneral#ac-total-exported-real-energy" }
Number                  SE_BATT_TEMP             "Battery Temperature [%d °C]"                                                                                 { channel="modbus:data:solaredge:battery:batteryTemperature:number" }
Number                  SE_BATT_CHARGE_DISCHARGE "Battery Current Power [JS(transformToKW.js):%s]"                                                             { channel="modbus:data:solaredge:battery:batteryPower:number" }
Number                  SE_BATT_LT_EXPORT        "Battery Lifetime Export [JS(transformToKWh.js):%s]"                                                          { channel="modbus:data:solaredge:battery:batteryLifetimeExport:number" }
Number                  SE_BATT_LT_IMPORT        "Battery Lifetime Import [JS(transformToKWh.js):%s]"                                                          { channel="modbus:data:solaredge:battery:batteryLifetimeImport:number" }
Number                  SE_BATT_MAX_ENERGY       "Battery Max Energy"                                                                                          { channel="modbus:data:solaredge:battery:batteryMaxEnergy:number" }
Number                  SE_BATT_CURR_ENERGY      "Battery Available Energy"                                                                                    { channel="modbus:data:solaredge:battery:batteryAvailableEnergy:number" }
Number                  SE_BATT_SOH              "Battery SOH [%d %%]"                                                                                         { channel="modbus:data:solaredge:battery:batterySOH:number" }
Number                  SE_BATT_BATT_LEVEL       "Battery SOC [%d %%]"                                    <battery>                                            { channel="modbus:data:solaredge:battery:batterySOE:number" }
Number                  SE_BATT_STATUS           "Battery Status [MAP(solarEdgeBatteryStatus.map):%s]"                                                         { channel="modbus:data:solaredge:battery:batteryStatus:number" }

transformToKW

// Wrap everything in a function (no global variable pollution)
// variable "input" contains data string passed by binding
(function(inputData) {
    // convert from Wh to kWh
    return Math.round( parseFloat(inputData) / 10 ) / 100 + " kW";
})(input)

transformToKWh

// Wrap everything in a function (no global variable pollution)
// variable "input" contains data string passed by binding
(function(inputData) {
    // convert from Wh to kWh
    return Math.round( parseFloat(inputData) / 1000 ) + " kWh";
})(input)

I found out that at least for my TESLA some datapoints do not return useful data:

  • Battery Max Energy
  • Battery Available Energy
  • Battery SOH

but you’re using a hybrid right?
Linked sources said it would not work with those but it does?
Also you should use unit metadata rather than convert in transforms

No it is a classic Se5000h inverter with an external StorEdge unit.

I thought that unit metadata only applies to channels which implement UoM. The modbus binding does not support UoM.

why do they call it …h when it is not a hybrid🙄

Unit metadata applies to UoM items not channels.

I’m trying to get a value for power generation. Should be simple, shouldn’t it ?
I’m however struggling with the meaning of modbus registers.
There’s I_DC_Power and I_AC_Power, can anyone explain what they mean and their difference ?
Is it before or after DC-AC conversion ? Is battery (dis)chargeload included in either of these ?
(since I don’t own an SE inverter, I don’t know if batteries are DC or AC coupled).

I_DC_Power 40083/4 is NEGATIVE at times. I guess they’re counting self consumption.
But since SE via portal provides “clean” values of 0 generation at night, where do they calculate this loss from ?
I have not found any modbus register that explicitly tells me the pure power generation value of the panels, let alone per string - anyone ?

Hi Markus,

as far as I know, I_DC_Power is the total power on the DC side coming in from the modules (Solaredge only ever has a single string, to the best of my knowledge). This should be the DC generator of the inverter only. I don’t have a battery on my Solaredge system, but I would expect that all related values for power flow to and from the battery would be on separate registers.

I_AC_Power is the AC Power that the inverter is currently generating. Once again, the numbers of how much of that goes into the batteries or is fed into the grid should be in separate registers (i.e. the Feed-in values of the grid connection would be read from the WattNode Solaredge Meter via different registers).

Per panel production/energy is available only via the Solaredge App, but afaik, Solaredge does not provide any way to read this via Modbus registers under the SunSpec specification.

Best,

Tom