Reading Data from Solaredge inverters via Modbus TCP

Hi folks,

I did some work to read data from a Solaredge solar power plant inverter and wanted to share my solution, because the inverter connection is a little tricky and requires quite a bit of post processing,

Description:
Solaredge is company that manufactures amongst other things a solar power plant inverter family. These devices offer a local logging interface that delivers some operations data to logging devices via a standardized data model, which is called “Sunspec”. Some other inverters also use this (i.e. Fronius), so it might be possible to adapt the solution to other inverters too,
In recent inverter models, Modbus TCP was added as a communication option, which is quite convenient since it would not require any additional hardware such as a RS485 interface and can be used directly to integrate the data into OpenHAB using the Modbus binding.

Note:

  • If you do not need realtime data from your inverter, there is now a Solaredge binding which reads data via the Solaredge monitoring API. This might be easier to integrate for you.
  • This was written before the Modbus V2 binding was available. Most of the code will still work, but the items definitions need to be changed if you want to use the V2 binding. Use the 1.x Modbus binding for it to work out of the box. (Use PaperUI, go to Configuration -> System -> enable the switch for “Include 1.x legacy bindings” and find the Modbus v1.x binding to install from the add-ons subsection.)
  • The Modbus TCP logging works in parallel to any logging that the inverter might be doing towards the Solaredge monitoring portal.
  • Modbus TCP needs to be enbaled in the inverter, and you need to configure the TCP port that the inverter should listen to connection requests on (usually TCP-Port 502)
  • Please see the documentation on the inverter (available from Solaredge.com) on how to enable this, You need a device with a CPU version >3.xxx for Modbus TCP support. The relevant document is called “Technical Note - SunSpec Logging in solaredge inverters”, and the most recent version that I found is dated July 2016.
  • The inverter only waits for two minutes for a Modbus TCP client to connect, after that it doesn’t accept TCP connections. I found that if your connection has dropped, the only way to get it back would be to restart te inverter (or go into the inverter config menu, disable Modbus TCP and re-enable it).
  • the inverter only allows one TCP connection at a time. This means that we will need to configure exactly one Modbus TCP slave in the Modbus binding and extract all items from the values it reads in one go. This is a bit nasty, since the inverter has int16, uint16 and uint32 values. A slave definition can only be one type, so my config uses uint16 to read the whole parameter block and converts the values accordingly. For the Modbus meter (see below) I use a second slave definition.
  • This also means that you cannot have more than one Modbus TCP logger (i.e. openHAB and solarLog in parallel wouldn’t work). It can however work in parallel with the Solaredge monitoring portal.
  • In Germany, you need to limit your export to the grid to 70% of the installed peak power of your solar power plant. Often times, one would install a consumption meter (cheapest option is an S0 meter) to take into account the current power consumption of your home, so that the inverter can produce more power so that: production - consumption < installed peak power * 70%. Note that you can not read the consumption measured by your S0 meter via the solaredge inverter, even though these values are available from the Solaredge monitoring portal.
  • However, Solaredge offers a Modbus Meter (i.e. SE-WNC-3Y-400-MB), which connects to the inverter via RS385 Modbus and can measure quite a bit more data (export+import, and per-phase values). You can read data from this meter via the inverter, giving you the full picture of production, consumption and export+import. The meter is quite fast, so you can read data every few seconds (with tuning probably sill faster). This is useful if you want to use that data to control other consumers in your smart home to dynamically use the available excess power (i.e. charging your electric vehicle with exactly the available solar energy). I use this to control my Heatpump and generate warm water if there is power available, see: Use excess Photovoltaics Production intelligently (Building a time based "hysteresis")

Setup:
As described, I have an inverter and the modbus meter. The modbus meter is connected to the inverter via RS485. It uses Modbus ID 2. The inverter has Modbus ID 1. The inverter is hooked up the the network via Ethernet.
First, we need to configure the Modbus binding to read data from the inverter. For a standard OH2 installation, this would be done in the file /etc/openhab2/services/modbus.cfg:

poll=10000

tcp.se9k.connection=192.168.199.122:502:60:0:0:3:500
tcp.se9k.id=1
tcp.se9k.type=holding
tcp.se9k.start=69
tcp.se9k.length=50
tcp.se9k.valuetype=uint16

tcp.se9km.connection=192.168.199.122:502:500:200:200:3:500
tcp.se9km.id=1
tcp.se9km.type=holding
tcp.se9km.start=188
tcp.se9km.length=107
tcp.se9km.valuetype=uint16

The inverter also supplies the data it reads from the meter via modbus, so the TCP slave definition to read the meter values also needs to be configured for Modbus ID 1. If you don’t have a modbus meter, remove the tcp.se9km items from your config.

Next, to setup the item definitions. The first set of items holds the values directly read from the inverter (forgive the german captions, I hope the names are somewhat self-explanatory):

Group se9kint “Wechselrichter PV-Anlage (int-Werte)”
Group se9k “Wechselrichter PV-Anlage”
Number se9k_DID_int “WR Typ (int) [%d]” (se9kint) {modbus=“se9k:0”}

// Amps acrosss all phases
Number se9k_Amps_int “WR Stromerzeugung gesamt (int) [%d A]” (se9kint) { modbus=“se9k:2” }

// Amps Phase A,B,C and scaling factor
Number se9k_AmpA_int “WR Stromerzeugung Ph.A (int) [%d A]” (se9kint) { modbus=“se9k:3” }
Number se9k_AmpB_int “WR Stromerzeugung Ph.B (int) [%d A]” (se9kint) { modbus=“se9k:4” }
Number se9k_AmpC_int “WR Stromerzeugung Ph.C (int) [%d A]” (se9kint) { modbus=“se9k:5” }
Number se9k_AmpSF_int “WR Skalierungsfaktor Strom (int) [%d]” (se9kint) { modbus=“se9k:6” }

// Voltage for Phases A,B,C and scaling factor
Number se9k_VoltA_int “WR Spannung Phase A (int) [%d V]” (se9kint) { modbus=“se9k:10” }
Number se9k_VoltB_int “WR Spannung Phase B (int) [%d V]” (se9kint) { modbus=“se9k:11” }
Number se9k_VoltC_int “WR Spannung Phase C (int) [%d V]” (se9kint) { modbus=“se9k:12” }
Number se9k_VoltSF_int “WR Skalierungsfaktor Spannung (int) [%d]” (se9kint) { modbus=“se9k:13” }

// Power and SF
Number se9k_Watt_int “WR Leistung Erzeugung (int) [%d W]” (se9kint) { modbus=“se9k:14” }
Number se9k_WattSF_int “WR Skalierungsfaktor Leistung (int) [%d]” (se9kint) { modbus=“se9k:15” }

// Frequency and SF
Number se9k_Hz_int “WR Netzfrequenz (int) [%d Hz]” (se9kint) { modbus=“se9k:16” }
Number se9k_HzSF_int “WR Skalierungsfaktor Netzfrequ. (int) [%d]” (se9kint) { modbus=“se9k:17” }

// Apparent Power and SF
Number se9k_VA_int “WR Scheinleistung gesamt (int) [%d VA]” (se9kint) { modbus=“se9k:18” }
Number se9k_VASF_int “WR Skalierungsfaktor Scheinleistung (int) [%d]” (se9kint) { modbus=“se9k:19” }

// Reactive Power and SF
Number se9k_VAR_int “WR Reaktive Leistung gesamt (int) [%d VA]” (se9kint) { modbus=“se9k:20” }
Number se9k_VARSF_int “WR Skalierungsfaktor reaktive Leistung (int) [%d]” (se9kint) { modbus=“se9k:21” }

// Power factor
Number se9k_PF_int “WR Leistungsfaktor (int) [%d cos phi]” (se9kint) { modbus=“se9k:22” }
Number se9k_PFSF_int “WR Skalierungsfaktor Leistungsfaktor (int) [%d]” (se9kint) { modbus=“se9k:23” }

// Lifetime generated energy
Number se9k_Wh1_int “WR Erzeugungszaehler Byte1 (int) [%d Wh]” (se9kint) { modbus=“se9k:24” }
Number se9k_Wh2_int “WR Erzeugungszaehler Byte2 (int) [%d Wh]” (se9kint) { modbus=“se9k:25” }
Number se9k_WhSF_int “WR Skalierungsfaktor Zaehler (int) [%d]” (se9kint) { modbus=“se9k:26” }

// DC side current
Number se9k_DCA_int “WR Strom DC Seite (int) [%d A]” (se9kint) { modbus=“se9k:27” }
Number se9k_DCASF_int “WR Skalierungsfaktor DC Strom (int) [%d]” (se9kint) { modbus=“se9k:28” }

// DC side voltage
Number se9k_DCV_int “WR Spannung DC Seite (int) [%d V]” (se9kint) { modbus=“se9k:29” }
Number se9k_DCVSF_int “WR Skalierungsfaktor DC Spannung (int) [%d]” (se9kint) { modbus=“se9k:30” }

// DC side power
Number se9k_DCW_int “WR Leistung DC Seite (int) [%d W]” (se9kint) { modbus=“se9k:31” }
Number se9k_DCWSF_int “WR Skalierungsfaktor DC Leistung (int) [%d]” (se9kint) { modbus=“se9k:32” }

// Temp Heat sink
Number se9k_THS_int “WR Temperatur Kuehlkorper (int) [%d C]” (se9kint) { modbus=“se9k:34” }
Number se9k_THSSF_int “WR Skalierungsfaktor Kuehlkoerper (int) [%d]” (se9kint) { modbus=“se9k:37” }

// Operating state
Number se9k_Status_int “WR Status (int) [%d]” (se9kint) { modbus=“se9k:38” }
Number se9k_Status_Vendor_int “WR Status Vendor (int) [%d]” (se9kint) { modbus=“se9k:39” }

Here you can already see why we need a bit of post-processing. The sunpec format stores integer values and scale factors, so to get to the actual floating point values, you need to convert them like so:
Value_float = Value_int * 10^scale factor
Also, some items are int16 (i.e. -32768 to 32768), while we instructed the modbus slave to read them all as uint16 (0…65536). Other items are uint 32, so we need to get the float value by multiplying the first byte by 65536, adding the second byte and apply the scale factor.
The second set of items therefore holds all the Float values and we will populate them via some rules:

// Se9K inverter Float values
String se9k_DID “WR Typ [%s]” (se9k)
// Amps acrosss all phases
Number se9k_Amps “WR Stromerzeugung gesamt [%.2f A]” (se9k)
// Amps Phase A,B,C
Number se9k_AmpA “WR Stromerzeugung Ph.A [%.2f A]” (se9k)
Number se9k_AmpB “WR Stromerzeugung Ph.B [%.2f A]” (se9k)
Number se9k_AmpC “WR Stromerzeugung Ph.C [%.2f A]” (se9k)
// Voltage for Phases A,B,C
Number se9k_VoltA “WR Spannung Phase A [%.1f V]” (se9k)
Number se9k_VoltB “WR Spannung Phase B [%.1f V]” (se9k)
Number se9k_VoltC “WR Spannung Phase C [%.1f V]” (se9k)
// Power
Number se9k_Watt “Erzeugungsleistung Photovolaik [%.2f W]” (se9k)
// Frequency
Number se9k_Hz “WR Netzfrequenz [%.2f Hz]” (se9k)
// Apparent Power
Number se9k_VA “WR Scheinleistung gesamt [%.2f VA]” (se9k)
// Reacive Power
Number se9k_VAR “WR reaktive Leistung gesamt [%.2f VA]” (se9k)
// Power factor
Number se9k_PF “WR Leistungsfaktor [%.1f cos phi]” (se9k)
// Lifetime generated energy
Number se9k_kWh “WR Erzeugungszaehler [%.3f kWh]” (se9k)
// the follwing two items allow you to display some derived values, i.e. the energy produced in the current year.
Number se9k_kWh_Jahr “WR Erzeugung seit Jahresanfang [%.3f kWh]” (se9k)
Number se9k_kWh_Jahr_Offset “WR Offset Erzeugungaehler zum 1.1. [%.3f kWh]” (se9k)
// DC side current
Number se9k_DCA “WR Strom DC Seite [%.2f A]” (se9k)
// DC side voltage
Number se9k_DCV “WR Spannung DC Seite [%.2f V]” (se9k)
// DC side power
Number se9k_DCW “WR Leistung DC Seite [%.2f W]” (se9k)
// Temp Heat sink
Number se9k_THS “WR Temperatur Kuehlkorper [%.2f C]” (se9k)
// Status
String se9k_Status “Status [%s]” (se9k)
String se9k_Status_Vendor “Status Vendor [%s]” (se9k)

There are the items you need if you have just the inverter. If you have a Modbus meter in addition, these are the Integer item definitions:

Group se9kmint “Stromzaehler Haus (Smartmeter PV-Anlage)”
Group se9km “Stromuzaehler Haus (Smartmeter PV-Anlage)”
// SE9k Modbus meter integer values
// Type (Map: 201 = single phase A-N , 202 = split single phase (A-B-N), 203 = Wye (A-B-C-N), 204 = Delta (A-B-C))
Number se9km_DID_int “Netztyp Modbus Meter [%d]” (se9kmint) {modbus=“se9km:0”}
// Strom
Number se9km_Amp_int “SM Strom AC (int) [%d A]” (se9kmint) {modbus=“se9km:2”}
Number se9km_AmpA_int “SM Strom Ph.A (int) [%d A]” (se9kmint) {modbus=“se9km:3”}
Number se9km_AmpB_int “SM Strom Ph.B (int) [%d A]” (se9kmint) {modbus=“se9km:4”}
Number se9km_AmpC_int “SM Strom Ph.C (int) [%d A]” (se9kmint) {modbus=“se9km:5”}
Number se9km_AmpSF_int “SM Strom Skalierungsfaktor (int) [%d]” (se9kmint) {modbus=“se9km:6”}

// Spannung
Number se9km_VoltL_int “SM Spannung AC (MW alle Phasen) (int) [%d V]” (se9kmint) {modbus=“se9km:7”}
Number se9km_VoltA_int “SM Spannung Ph.A (int) [%d A]” (se9kmint) {modbus=“se9km:8”}
Number se9km_VoltB_int “SM Spannung Ph.B (int) [%d A]” (se9kmint) {modbus=“se9km:9”}
Number se9km_VoltC_int “SM Spannung Ph.C (int) [%d A]” (se9kmint) {modbus=“se9km:10”}
Number se9km_VoltSF_int “SM Spannung Skalierungsfaktor [%d]” (se9kmint) {modbus=“se9km:15”}

// Frequenz
Number se9km_Frequenz_int “SM Netzfrequenz (int) [%d Hz]” (se9kmint) {modbus=“se9km:16”}
Number se9km_FrequenzSF_int “SM Netzfrequenz Skalierungsfaktor (int) [%d]” (se9kmint) {modbus=“se9km:17”}

// Wirkleistung
Number se9km_Watt_int “SM Wirkleistung AC (Summe alle Phasen) (int) [%d W]” (se9kmint) {modbus=“se9km:18”}
Number se9km_WattA_int “SM Wirkleistung Ph.A (int) [%d W]” (se9kmint) {modbus=“se9km:19”}
Number se9km_WattB_int “SM Wirkleistung Ph.B (int) [%d W]” (se9kmint) {modbus=“se9km:20”}
Number se9km_WattC_int “SM Wirkleistung Ph.C (int) [%d W]” (se9kmint) {modbus=“se9km:21”}
Number se9km_WattSF_int “SM Wirkleistung Skalierungsfaktor (int) [%d]” (se9kmint) {modbus=“se9km:22”}

// Scheinleistung
Number se9km_VA_int “SM Scheinleistung AC (int) (Summe alle Phasen) [%d VA]” (se9kmint) {modbus=“se9km:23”}
Number se9km_VAA_int “SM Scheinleistung Ph.A (int) [%d VA]” (se9kmint) {modbus=“se9km:24”}
Number se9km_VAB_int “SM Scheinleistung Ph.B (int) [%d VA]” (se9kmint) {modbus=“se9km:25”}
Number se9km_VAC_int “SM Scheinleistung Ph.C (int) [%d VA]” (se9kmint) {modbus=“se9km:26”}
Number se9km_VASF_int “SM Scheinleistung Skalierungsfaktor (int) [%d]” (se9kmint) {modbus=“se9km:27”}

// reaktive Leistung
Number se9km_VAR_int “SM reaktive Leistung AC (Summe alle Phasen) (int) [%d VAR]” (se9kmint) {modbus=“se9km:28”}
Number se9km_VARA_int “SM reaktive Leistung Ph.A (int) [%d VAR]” (se9kmint) {modbus=“se9km:29”}
Number se9km_VARB_int “SM reaktive Leistung Ph.B (int) [%d VAR]” (se9kmint) {modbus=“se9km:30”}
Number se9km_VARC_int “SM reaktive Leistung Ph.C (int) [%d VAR]” (se9kmint) {modbus=“se9km:31”}
Number se9km_VARSF_int “SM reaktive Leistung Skalierungsfaktor (int) [%d]” (se9kmint) {modbus=“se9km:32”}

// Leistungsfaktor
Number se9km_PF_int “SM Leistungsfaktor (MW alle Phasen) (int) [%d cos phi]” (se9kmint) {modbus=“se9km:33”}
Number se9km_PFA_int “SM Lesitungsfaktor Ph.A (int) [%d cos phi]” (se9kmint) {modbus=“se9km:34”}
Number se9km_PFB_int “SM Leistungsfaktor Ph.B (int) [%d cos phi]” (se9kmint) {modbus=“se9km:35”}
Number se9km_PFC_int “SM Lesitungsfaktor Ph.C (int) [%d cos phi]” (se9kmint) {modbus=“se9km:36”}
Number se9km_PFSF_int “SM Leistungsfaktor Skalierungsfaktor (int) [%d]” (se9kmint) {modbus=“se9km:37”}

// Zaehler Wirkleistung
Number se9km_Wh1_Exp_int “SM Einspeisezaehler Wirkenergie Byte 1 (Summe alle Phasen) (int) [%d Wh]” (se9kmint) {modbus=“se9km:38”}
Number se9km_Wh2_Exp_int “SM Einspeisezaehler Wirkenergie Byte 2 (Summe alle Phasen) (int) [%d Wh]” (se9kmint) {modbus=“se9km:39”}
Number se9km_WhA1_Exp_int “SM Einspeisezaehler Wirkenergie Ph.A Byte 1 (int) [%d Wh]” (se9kmint) {modbus=“se9km:40”}
Number se9km_WhA2_Exp_int “SM Einspeisezaehler Wirkenergie Ph.A Byte 2 (int) [%d Wh]” (se9kmint) {modbus=“se9km:41”}
Number se9km_WhB1_Exp_int “SM Einspeisezaehler Wirkenergie Ph.B Byte 1 (int) [%d Wh]” (se9kmint) {modbus=“se9km:42”}
Number se9km_WhB2_Exp_int “SM Einspeisezaehler Wirkenergie Ph.B Byte 2 (int) [%d Wh]” (se9kmint) {modbus=“se9km:43”}
Number se9km_WhC1_Exp_int “SM Einseisezaehler Wirkenergie Ph.C Byte 1 (int) [%d Wh]” (se9kmint) {modbus=“se9km:44”}
Number se9km_WhC2_Exp_int “SM Einseisezaehler Wirkenergie Ph.C Byte 2 (int) [%d Wh]” (se9kmint) {modbus=“se9km:45”}
Number se9km_Wh1_Imp_int “SM Bezugszaehler Wirkenergie Byte 1 (Summe alle Phasen) (int) [%d Wh]” (se9kmint) {modbus=“se9km:46”}
Number se9km_Wh2_Imp_int “SM Bezugszaehler Wirkenergie Byte 2 (Summe alle Phasen) (int) [%d Wh]” (se9kmint) {modbus=“se9km:47”}
Number se9km_WhA1_Imp_int “SM Bezugszaehler Wirkenergie Ph.A Byte 1 (int) [%d Wh]” (se9kmint) {modbus=“se9km:48”}
Number se9km_WhA2_Imp_int “SM Bezugszaehler Wirkenergie Ph.A Byte 2 (int) [%d Wh]” (se9kmint) {modbus=“se9km:49”}
Number se9km_WhB1_Imp_int “SM Bezugszaehler Wirkenergie Ph.B Byte 1 (int) [%d Wh]” (se9kmint) {modbus=“se9km:50”}
Number se9km_WhB2_Imp_int “SM Bezugszaehler Wirkenergie Ph.B Byte 2 (int) [%d Wh]” (se9kmint) {modbus=“se9km:51”}
Number se9km_WhC1_Imp_int “SM Bezugszaehler Wirkenergie Ph.C Byte 1 (int) [%d Wh]” (se9kmint) {modbus=“se9km:52”}
Number se9km_WhC2_Imp_int “SM Bezugszaehler Wirkenergie Ph.C Byte 2 (int) [%d Wh]” (se9kmint) {modbus=“se9km:53”}
Number se9km_WhSF_int “SM Zaehler Wirkenergie Skalierungsfaktor (int) [%d]” (se9kmint) {modbus=“se9km:54”}

// Zaehler Scheinleistung
Number se9km_VAh1_Exp_int “SM Einspeisezaehler Scheinnergie Byte 1 (Summe alle Phasen) (int) [%d VAh]” (se9kmint) {modbus=“se9km:55”}
Number se9km_VAh2_Exp_int “SM Einspeisezaehler Scheinnergie Byte 2 (Summe alle Phasen) (int) [%d VAh]” (se9kmint) {modbus=“se9km:56”}
Number se9km_VAhA1_Exp_int “SM Einspeisezaehler Scheinenergie Ph.A Byte 1 (int) [%d VAh]” (se9kmint) {modbus=“se9km:57”}
Number se9km_VAhA2_Exp_int “SM Einspeisezaehler Scheinenergie Ph.A Byte 2 (int) [%d VAh]” (se9kmint) {modbus=“se9km:58”}
Number se9km_VAhB1_Exp_int “SM Einspeisezaehler Scheinenergie Ph.B Byte 1 (int) [%d VAh]” (se9kmint) {modbus=“se9km:59”}
Number se9km_VAhB2_Exp_int “SM Einspeisezaehler Scheinenergie Ph.B Byte 2 (int) [%d VAh]” (se9kmint) {modbus=“se9km:60”}
Number se9km_VAhC1_Exp_int “SM Einseisezaehler Scheinenergie Ph.C Byte 1 (int) [%d VAh]” (se9kmint) {modbus=“se9km:61”}
Number se9km_VAhC2_Exp_int “SM Einseisezaehler Scheinenergie Ph.C Byte 2 (int) [%d VAh]” (se9kmint) {modbus=“se9km:62”}
Number se9km_VAh1_Imp_int “SM Bezugszaehler Scheinenergie Byte 1 (Summe alle Phasen) (int) [%d VAh]” (se9kmint) {modbus=“se9km:63”}
Number se9km_VAh2_Imp_int “SM Bezugszaehler Scheinenergie Byte 2 (Summe alle Phasen) (int) [%d VAh]” (se9kmint) {modbus=“se9km:64”}
Number se9km_VAhA1_Imp_int “SM Bezugszaehler Scheinenergie Ph.A Byte 1 (int) [%d VAh]” (se9kmint) {modbus=“se9km:65”}
Number se9km_VAhA2_Imp_int “SM Bezugszaehler Scheinenergie Ph.A Byte 2 (int) [%d VAh]” (se9kmint) {modbus=“se9km:66”}
Number se9km_VAhB1_Imp_int “SM Bezugszaehler Scheinenergie Ph.B Byte 1 (int) [%d VAh]” (se9kmint) {modbus=“se9km:67”}
Number se9km_VAhB2_Imp_int “SM Bezugszaehler Scheinenergie Ph.B Byte 2 (int) [%d VAh]” (se9kmint) {modbus=“se9km:68”}
Number se9km_VAhC1_Imp_int “SM Bezugszaehler Scheinenergie Ph.C Byte 1 (int) [%d VAh]” (se9kmint) {modbus=“se9km:69”}
Number se9km_VAhC2_Imp_int “SM Bezugszaehler Scheinenergie Ph.C Byte 2 (int) [%d VAh]” (se9kmint) {modbus=“se9km:70”}
Number se9km_VAhSF_int “SM Zaehler Scheinenergie Skalierungsfaktor (int) [%d]” (se9kmint) {modbus=“se9km:71”}

// Zaehler reaktive Leistung
Number se9km_VARhQ11_int “SM Bezugszaehler Q1 reaktive Energie Byte 1 (Summe alle Phasen) (int) [%d VARh]” (se9kmint) {modbus=“se9km:72”}
Number se9km_VARhQ12_int “SM Bezugszaehler Q1 reaktive Energie Byte 2 (Summe alle Phasen) (int) [%d VARh]” (se9kmint) {modbus=“se9km:73”}
Number se9km_VARhQ1A1_int “SM Bezugszaehler Q1 reaktive Energie Ph.A Byte 1 (int) [%d VARh]” (se9kmint) {modbus=“se9km:74”}
Number se9km_VARhQ1A2_int “SM Bezugszaehler Q1 reaktive Energie Ph.A Byte 2 (int) [%d VARh]” (se9kmint) {modbus=“se9km:75”}
Number se9km_VARhQ1B1_int “SM Bezugszaehler Q1 reaktive Energie Ph.B Byte 1 (int) [%d VARh]” (se9kmint) {modbus=“se9km:76”}
Number se9km_VARhQ1B2_int “SM Bezugszaehler Q1 reaktive Energie Ph.B Byte 2 (int) [%d VARh]” (se9kmint) {modbus=“se9km:77”}
Number se9km_VARhQ1C1_int “SM Bezugszaehler Q1 reaktive Energie Ph.C Byte 1 (int) [%d VARh]” (se9kmint) {modbus=“se9km:78”}
Number se9km_VARhQ1C2_int “SM Bezugszaehler Q1 reaktive Energie Ph.C Byte 2 (int) [%d VARh]” (se9kmint) {modbus=“se9km:79”}
Number se9km_VARhQ21_int “SM Bezugszaehler Q2 reaktive Energie Byte 1 (Summe alle Phasen) (int) [%d VARh]” (se9kmint) {modbus=“se9km:80”}
Number se9km_VARhQ22_int “SM Bezugszaehler Q2 reaktive Energie Byte 2 (Summe alle Phasen) (int) [%d VARh]” (se9kmint) {modbus=“se9km:81”}
Number se9km_VARhQ2A1_int “SM Bezugszaehler Q2 reaktive Energie Ph.A Byte 1 (int) [%d VARh]” (se9kmint) {modbus=“se9km:82”}
Number se9km_VARhQ2A2_int “SM Bezugszaehler Q2 reaktive Energie Ph.A Byte 2 (int) [%d VARh]” (se9kmint) {modbus=“se9km:83”}
Number se9km_VARhQ2B1_int “SM Bezugszaehler Q2 reaktive Energie Ph.B Byte 1 (int) [%d VARh]” (se9kmint) {modbus=“se9km:84”}
Number se9km_VARhQ2B2_int “SM Bezugszaehler Q2 reaktive Energie Ph.B Byte 2 (int) [%d VARh]” (se9kmint) {modbus=“se9km:85”}
Number se9km_VARhQ2C1_int “SM Bezugszaehler Q2 reaktive Energie Ph.C Byte 1 (int) [%d VARh]” (se9kmint) {modbus=“se9km:86”}
Number se9km_VARhQ2C2_int “SM Bezugszaehler Q2 reaktive Energie Ph.C Byte 2 (int) [%d VARh]” (se9kmint) {modbus=“se9km:87”}
Number se9km_VARhQ31_int “SM Einpeisezaehler Q3 reaktive Energie Byte 1 (Summe alle Phasen) (int) [%d VARh]” (se9kmint) {modbus=“se9km:88”}
Number se9km_VARhQ32_int “SM Einpeisezaehler Q3 reaktive Energie Byte 2 (Summe alle Phasen) (int) [%d VARh]” (se9kmint) {modbus=“se9km:89”}
Number se9km_VARhQ3A1_int “SM Einpeisezaehler Q3 reaktive Energie Ph.A Byte 1 (int) [%d VARh]” (se9kmint) {modbus=“se9km:90”}
Number se9km_VARhQ3A2_int “SM Einpeisezaehler Q3 reaktive Energie Ph.A Byte 2 (int) [%d VARh]” (se9kmint) {modbus=“se9km:91”}
Number se9km_VARhQ3B1_int “SM Einpeisezaehler Q3 reaktive Energie Ph.B Byte 1 (int) [%d VARh]” (se9kmint) {modbus=“se9km:92”}
Number se9km_VARhQ3B2_int “SM Einpeisezaehler Q3 reaktive Energie Ph.B Byte 2 (int) [%d VARh]” (se9kmint) {modbus=“se9km:93”}
Number se9km_VARhQ3C1_int “SM Einpeisezaehler Q3 reaktive Energie Ph.C Byte 1 (int) [%d VARh]” (se9kmint) {modbus=“se9km:94”}
Number se9km_VARhQ3C2_int “SM Einpeisezaehler Q3 reaktive Energie Ph.C Byte 2 (int) [%d VARh]” (se9kmint) {modbus=“se9km:95”}
Number se9km_VARhQ41_int “SM Einpeisezaehler Q4 reaktive Energie Byte 1 (Summe alle Phasen) (int) [%d VARh]” (se9kmint) {modbus=“se9km:96”}
Number se9km_VARhQ42_int “SM Einpeisezaehler Q4 reaktive Energie Byte 2 (Summe alle Phasen) (int) [%d VARh]” (se9kmint) {modbus=“se9km:97”}
Number se9km_VARhQ4A1_int “SM Einpeisezaehler Q4 reaktive Energie Ph.A Byte 1 (int) [%d VARh]” (se9kmint) {modbus=“se9km:98”}
Number se9km_VARhQ4A2_int “SM Einpeisezaehler Q4 reaktive Energie Ph.A Byte 2 (int) [%d VARh]” (se9kmint) {modbus=“se9km:99”}
Number se9km_VARhQ4B1_int “SM Einpeisezaehler Q4 reaktive Energie Ph.B Byte 1 (int) [%d VARh]” (se9kmint) {modbus=“se9km:100”}
Number se9km_VARhQ4B2_int “SM Einpeisezaehler Q4 reaktive Energie Ph.B Byte 2 (int) [%d VARh]” (se9kmint) {modbus=“se9km:101”}
Number se9km_VARhQ4C1_int “SM Einpeisezaehler Q4 reaktive Energie Ph.C Byte 1 (int) [%d VARh]” (se9kmint) {modbus=“se9km:102”}
Number se9km_VARhQ4C2_int “SM Einpeisezaehler Q4 reaktive Energie Ph.C Byte 2 (int) [%d VARh]” (se9kmint) {modbus=“se9km:103”}
Number se9km_VARhSF_int “SM Zaehler reaktive Energie Skalierungsfaktor (int) [%d]” (se9kmint) {modbus=“se9km:104”}

// Event register
Number se9km_Event1_int “SM Eventregister Byte 1 (int) [%d]” (se9kmint) {modbus=“se9km:105”}
Number se9km_Event2_int “SM Eventregister Byte 2 (int) [%d]” (se9kmint) {modbus=“se9km:106”}

By the same logic, the integer values need to be converted to Float. These are the items:

// se9k Modbus Meter Float-Werte

// Typ (Map: 201 = single phase A-N , 202 = split single phase (A-B-N), 203 = Wye (A-B-C-N), 204 = Delta (A-B-C))
String se9km_DID “Netztyp Modbus Meter: [%s]” (se9km)
// Strom
Number se9km_Amp “SM Strom AC [%.2f A]” (se9km)
Number se9km_AmpA “SM Strom Ph.A [%.2f A]” (se9km)
Number se9km_AmpB “SM Strom Ph.B [%.2f A]” (se9km)
Number se9km_AmpC “SM Strom Ph.C [%.2f A]” (se9km)

// Spannung
Number se9km_VoltL “SM Spannung AC (MW alle Phasen) [%.2f V]” (se9km)
Number se9km_VoltA “SM Spannung Ph.A [%.2f A]” (se9km)
Number se9km_VoltB “SM Spannung Ph.B [%.2f A]” (se9km)
Number se9km_VoltC “SM Spannung Ph.C [%.2f A]” (se9km)

// Frequenz
Number se9km_Frequenz “SM Netzfrequenz [%.2f Hz]” (se9km)

// Wirkleistung
Number se9km_Watt “Einspeisepunkt Leistung (Einspeisung negativ) [%.2f W]” (se9km)
Number se9km_Wattp // Bezug
Number se9km_Wattm // Einspeisung
Number se9km_WattA “SM Wirkleistung Ph.A [%.2f W]” (se9km)
Number se9km_WattB “SM Wirkleistung Ph.B [%.2f W]” (se9km)
Number se9km_WattC “SM Wirkleistung Ph.C [%.2f W]” (se9km)

// Scheinleistung
Number se9km_VA “SM Scheinleistung AC (Summe alle Phasen) [%.2f VA]” (se9km)
Number se9km_VAA “SM Scheinleistung Ph.A [%.2f VA]” (se9km)
Number se9km_VAB “SM Scheinleistung Ph.B [%.2f VA]” (se9km)
Number se9km_VAC “SM Scheinleistung Ph.C [%.2f VA]” (se9km)

// reaktive Leistung
Number se9km_VAR “SM reaktive Leistung AC (Summe alle Phasen) [%d VAR]” (se9km)
Number se9km_VARA “SM reaktive Leistung Ph.A [%.2f VAR]” (se9km)
Number se9km_VARB “SM reaktive Leistung Ph.B [%.2f VAR]” (se9km)
Number se9km_VARC “SM reaktive Leistung Ph.C [%.2f VAR]” (se9km)

// Leistungsfaktor
Number se9km_PF “SM Leistungsfaktor (MW alle Phasen) [%.2f cos phi]” (se9km)
Number se9km_PFA “SM Leistungsfaktor Ph.A [%.2f cos phi]” (se9km)
Number se9km_PFB “SM Leistungsfaktor Ph.B [%.2f cos phi]” (se9km)
Number se9km_PFC “SM Leistungsfaktor Ph.C [%.2f cos phi]” (se9km)

// Zaehler Wirkleistung
Number se9km_kWh_Exp “SM Einspeisezaehler Wirkenergie (Summe alle Phasen) [%.3f kWh]” (se9km)
// The next 4 values are some derived values
Number se9km_kWh_Exp_Jahr “SM Einspeisezaehler seit 1.1. [%.3f kWh]” (se9km)
Number se9km_kWh_Exp_neg “SM Einspeisezaehler Wirkenergie (neg) (Summe alle Phasen) [%.3f kWh]” (se9km)
Number se9km_kWh_Exp_neg_Jahr “SM Einspeisezaehler (neg) seit 1.1. [%.3f kWh]” (se9km)
Number se9km_kWh_Exp_Jahr_Offset “Offset SM Einspeisezaehler seit 1.1. [%.3f kWh]” (se9km)
Number se9km_kWhA_Exp “SM Einspeisezaehler Wirkenergie Ph.A [%.3f kWh]” (se9km)
Number se9km_kWhB_Exp “SM Einspeisezaehler Wirkenergie Ph.B [%.3f kWh]” (se9km)
Number se9km_kWhC_Exp “SM Einseisezaehler Wirkenergie Ph.C [%.3f kWh]” (se9km)
Number se9km_kWh_Imp “SM Bezugszaehler Wirkenergie (Summe alle Phasen) [%.3f Wh]” (se9km)
// The next 2 are derived values too
Number se9km_kWh_Imp_Jahr “SM Bezugszaehler seit 1.1. [%.3f kWh]” (se9km)
Number se9km_kWh_Imp_Jahr_Offset “Offset SM Bezugszaehler seit 1.1. [%.3f kWh]” (se9km)
Number se9km_kWhA_Imp “SM Bezugszaehler Wirkenergie Ph.A [%.3f kWh]” (se9km)
Number se9km_kWhB_Imp “SM Bezugszaehler Wirkenergie Ph.B [%.3f kWh]” (se9km)
Number se9km_kWhC_Imp “SM Bezugszaehler Wirkenergie Ph.C [%.3f kWh]” (se9km)

// Zaehler Scheinleistung
Number se9km_VAh_Exp “SM Einspeisezaehler Scheinnergie (Summe alle Phasen) [%.2f kVAh]” (se9km)
Number se9km_VAhA_Exp “SM Einspeisezaehler Scheinenergie Ph.A [%.2f kVAh]” (se9km)
Number se9km_VAhB_Exp “SM Einspeisezaehler Scheinenergie Ph.B [%.2f kVAh]” (se9km)
Number se9km_VAhC_Exp “SM Einseisezaehler Scheinenergie Ph.C [%.2f kVAh]” (se9km)
Number se9km_VAh_Imp “SM Bezugszaehler Scheinenergie (Summe alle Phasen) [%.2f kVAh]” (se9km)
Number se9km_VAhA_Imp “SM Bezugszaehler Scheinenergie Ph.A [%.2f kVAh]” (se9km)
Number se9km_VAhB_Imp “SM Bezugszaehler Scheinenergie Ph.B [%.2f kVAh]” (se9km)
Number se9km_VAhC_Imp “SM Bezugszaehler Scheinenergie Ph.C [%.2f kVAh]” (se9km)

// Zaehler reaktive Leistung
Number se9km_VARhQ1 “SM Bezugszaehler Q1 reaktive Energie (Summe alle Phasen) [%.2f kVARh]” (se9km)
Number se9km_VARhQ1A “SM Bezugszaehler Q1 reaktive Energie Ph.A [%.2f kVARh]” (se9km)
Number se9km_VARhQ1B “SM Bezugszaehler Q1 reaktive Energie Ph.B [%.2f kVARh]” (se9km)
Number se9km_VARhQ1C “SM Bezugszaehler Q1 reaktive Energie Ph.C [%.2f kVARh]” (se9km)
Number se9km_VARhQ2 “SM Bezugszaehler Q2 reaktive Energie (Summe alle Phasen) [%.2f kVARh]” (se9km)
Number se9km_VARhQ2A “SM Bezugszaehler Q2 reaktive Energie Ph.A [%.2f kVARh]” (se9km)
Number se9km_VARhQ2B “SM Bezugszaehler Q2 reaktive Energie Ph.B [%.2f kVARh]” (se9km)
Number se9km_VARhQ2C “SM Bezugszaehler Q2 reaktive Energie Ph.C [%.2f kVARh]” (se9km)
Number se9km_VARhQ3 “SM Einpeisezaehler Q3 reaktive Energie (Summe alle Phasen) [%.2f kVARh]” (se9km)
Number se9km_VARhQ3A “SM Einpeisezaehler Q3 reaktive Energie Ph.A [%.2f kVARh]” (se9km)
Number se9km_VARhQ3B “SM Einpeisezaehler Q3 reaktive Energie Ph.B [%.2f kVARh]” (se9km)
Number se9km_VARhQ3C “SM Einpeisezaehler Q3 reaktive Energie Ph.C [%.2f kVARh]” (se9km)
Number se9km_VARhQ4 “SM Einpeisezaehler Q4 reaktive Energie (Summe alle Phasen) [%.2f kVARh]” (se9km)
Number se9km_VARhQ4A “SM Einpeisezaehler Q4 reaktive Energie Ph.A [%.2f kVARh]” (se9km)
Number se9km_VARhQ4B “SM Einpeisezaehler Q4 reaktive Energie Ph.B [%.2f kVARh]” (se9km)
Number se9km_VARhQ4C “SM Einpeisezaehler Q4 reaktive Energie Ph.C [%.2f kVARh]” (se9km)

4 Likes

Next, let me give you the sitemap definitions. Note that the Eclipse smart home designer doesn’t like me putting a Frame and a Group into the widget, but this seems to be cosmetic.
Once again, if you have no Modbus meter, remove the "SE9KM "items.

Text item=se9k_Watt {

  	Frame label="Wechselrichter SE9k" {
            Text item=se9k_Watt
            Text item=se9k_kWh
            Text item=se9k_kWh_Jahr
  		Setpoint item=se9k_kWh_Jahr_Offset  minValue=-100000 maxValue=100000 step=0.1
            Text item=se9k_Hz
  		Text item=se9k_VA
            Text item=se9k_VAR
            Text item=se9k_PF
  		Text item=se9k_Amps
  		Text item=se9k_AmpA
            Text item=se9k_AmpB
            Text item=se9k_AmpC
            Text item=se9k_VoltA
            Text item=se9k_VoltB
            Text item=se9k_VoltC
            Text item=se9k_DCA
            Text item=se9k_DCV
            Text item=se9k_DCW
            Text item=se9k_THS
            Text item=se9k_Status
            Text item=se9k_Status_Vendor
  	}
  	Group item=se9kint label="Werte SE9K Wechselrichter (int)"
  }
  Text item=se9km_Watt label="Smartmeter Einspeisepunkt [%.2f W]" {
  	
  		Frame label="Leistung und Zaehler" 
  		{
  			Text item=se9km_DID
  			Text item=se9km_Watt
  			Text item=se9km_kWh_Exp_Jahr
  			Text item=se9km_kWh_Imp_Jahr
  			Text item=se9km_Frequenz
  			Text item=se9km_PF
  			Text item=se9km_kWh_Exp
  			Setpoint item=se9km_kWh_Exp_Jahr_Offset minValue=-100000 maxValue=100000 step=0.1
  			Text item=se9km_kWh_Imp
  			Setpoint item=se9km_kWh_Imp_Jahr_Offset minValue=-100000 maxValue=100000 step=0.1
  		}
  		Frame label="Stromwerte Einspeisepunkt" {
  			Text item=se9km_Amp
                Text item=se9km_AmpA
                Text item=se9km_AmpB
                Text item=se9km_AmpC
  		}
            Frame label="Spannungswerte Einspeisepunkt" {
                Text item=se9km_VoltL
                Text item=se9km_VoltA
                Text item=se9km_VoltB
                Text item=se9km_VoltC
            }
         	Frame label="Wirkleistung Einspeisepunkt" {
                Text item=se9km_Watt
                Text item=se9km_WattA
                Text item=se9km_WattB
                Text item=se9km_WattC
           }
           Frame label="Scheinleistung Einspeisepunkt" {
                Text item=se9km_VA
                Text item=se9km_VAA
                Text item=se9km_VAB
                Text item=se9km_VAC
           }
           Frame label="reaktive Leistung Einspeisepunkt" {
                Text item=se9km_VAR
                Text item=se9km_VARA
                Text item=se9km_VARB
                Text item=se9km_VARC
           }
           Frame label="Leistungsfaktor Einspeisepunkt" {
                Text item=se9km_PF
                Text item=se9km_PFA
                Text item=se9km_PFB
                Text item=se9km_PFC
           }
           Frame label="Zaehler Wirkleistung" {
                Text item=se9km_kWh_Exp
                Text item=se9km_kWh_Exp_Jahr
                Text item=se9km_kWh_Imp
                Text item=se9km_kWh_Imp_Jahr
  			Text item=se9km_kWhA_Exp
                Text item=se9km_kWhB_Exp
                Text item=se9km_kWhC_Exp
                Text item=se9km_kWhA_Imp
                Text item=se9km_kWhB_Imp
                Text item=se9km_kWhC_Imp
           }
           Frame label="Zaehler Scheinleistung" {
                Text item=se9km_VAh_Exp
                Text item=se9km_VAh_Imp
                Text item=se9km_VAhA_Exp
                Text item=se9km_VAhB_Exp
                Text item=se9km_VAhC_Exp
                Text item=se9km_VAhA_Imp
                Text item=se9km_VAhB_Imp
                Text item=se9km_VAhC_Imp
           }
           Frame label="Zaehler reaktive Leistung" {
                Text item=se9km_VARhQ1
                Text item=se9km_VARhQ1A 
                Text item=se9km_VARhQ1B 
                Text item=se9km_VARhQ1C 
                Text item=se9km_VARhQ2
                Text item=se9km_VARhQ2A
                Text item=se9km_VARhQ2B
                Text item=se9km_VARhQ2C
                Text item=se9km_VARhQ3
                Text item=se9km_VARhQ3A
                Text item=se9km_VARhQ3B
                Text item=se9km_VARhQ3C
                Text item=se9km_VARhQ4
                Text item=se9km_VARhQ4A
                Text item=se9km_VARhQ4B
                Text item=se9km_VARhQ4C
           }
  	Group item=se9kmint label="Werte Modbus Meter (int)"
  }

Now, some rules to fill the Float items from the integer items read form the inverter:

import java.lang.Math
import java.lang.Double

rule se9k_Amps_add
when Item se9k_Amps_int received update
then
var Double SF = (se9k_AmpSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

  var Double result = (se9k_Amps_int.state as DecimalType).doubleValue * Math::pow(10,SF)
    var String value = result.toString
    logDebug("SE9K WR Stromerzeugung gesamt: ", value)

postUpdate(se9k_Amps, result)

end

rule se9k_AmpA_add
when Item se9k_AmpA_int received update
then
var Double SF = (se9k_AmpSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = (se9k_AmpA_int.state as DecimalType).doubleValue * Math::pow(10,SF)
    var String value = result.toString
    logDebug("SE9K WR Strom Phase A: ", value)
    postUpdate(se9k_AmpA, result)

end

rule se9k_AmpB_add
when Item se9k_AmpB_int received update
then
var Double SF = (se9k_AmpSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = (se9k_AmpB_int.state as DecimalType).doubleValue * Math::pow(10,SF)
    var String value = result.toString
    logDebug("SE9K WR Strom Phase B: ", value)
    postUpdate(se9k_AmpB, result)

end

rule se9k_AmpC_add
when Item se9k_AmpC_int received update
then
var Double SF = (se9k_AmpSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = (se9k_AmpC_int.state as DecimalType).doubleValue * Math::pow(10,SF)
    var String value = result.toString
    logDebug("SE9K WR Strom Phase C: ", value)
    postUpdate(se9k_AmpC, result)

end

rule se9k_VoltA_add
when Item se9k_VoltA_int received update
then
var Double SF = (se9k_VoltSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = (se9k_VoltA_int.state as DecimalType).doubleValue * Math::pow(10,SF)
    var String value = result.toString
    logDebug("SE9K WR Spannung Phase A: ", value)
    postUpdate(se9k_VoltA, result)

end

rule se9k_VoltB_add
when Item se9k_VoltB_int received update
then
var Double SF = (se9k_VoltSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = (se9k_VoltB_int.state as DecimalType).doubleValue * Math::pow(10,SF)
    var String value = result.toString
    logDebug("SE9K WR Spannung Phase B: ", value)
    postUpdate(se9k_VoltB, result)

end

rule se9k_VoltC_add
when Item se9k_VoltC_int received update
then
var Double SF = (se9k_VoltSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = (se9k_VoltC_int.state as DecimalType).doubleValue * Math::pow(10,SF)
    var String value = result.toString
    logDebug("SE9K WR Spannung Phase C: ", value)
    postUpdate(se9k_VoltC, result)

end

rule se9k_Watt_add
when Item se9k_Watt_int received update
then
var Double power = (se9k_Watt_int.state as DecimalType).doubleValue
if (power > 32767) power = power-(65536).doubleValue
var Double SF = (se9k_WattSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = power * Math::pow(10,SF)
    logInfo("[se9k] Watt: ", result.toString)
    postUpdate(se9k_Watt, result)

end

rule se9k_Hz_add
when Item se9k_Hz_int received update
then
var Double SF = (se9k_HzSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = (se9k_Hz_int.state as DecimalType).doubleValue * Math::pow(10,SF)
    var String value = result.toString
    logDebug("SE9K WR Netzfrequenz: ", value)
    postUpdate(se9k_Hz, result)

end

rule se9k_VA_add
when Item se9k_VA_int received update
then
var Double VA = (se9k_VA_int.state as DecimalType).doubleValue
if (VA > 32767) VA = VA-(65536).doubleValue
var Double SF = (se9k_VoltSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = VA * Math::pow(10,SF)
    var String value = result.toString
    logDebug("SE9K WR Scheinleistung: ", value)
    postUpdate(se9k_VA, result)

end

rule se9k_VAR_add
when Item se9k_VAR_int received update
then
var Double VAR = (se9k_VAR_int.state as DecimalType).doubleValue
if (VAR > 32767) VAR = VAR-(65536).doubleValue
var Double SF = (se9k_VARSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = VAR * Math::pow(10,SF)
    var String value = result.toString
    logDebug("SE9K WR reaktive Leistung: ", value)
    postUpdate(se9k_VAR, result)

end

rule se9k_PF_add
when Item se9k_PF_int received update
then
var Double PF = (se9k_PF_int.state as DecimalType).doubleValue
if (PF > 32767) PF = PF-(65536).doubleValue
var Double SF = (se9k_PFSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = PF * Math::pow(10,SF) /100
    var String value = result.toString
    logDebug("SE9K WR Leistungsfaktor: ", value)
    postUpdate(se9k_PF, result)

end

rule se9k_kWh_add
when Item se9k_Wh2_int received update
then
var Double SF = (se9k_WhSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double resultWh = ((se9k_Wh1_int.state as DecimalType * 65536).doubleValue + (se9k_Wh2_int.state as DecimalType).doubleValue) * Math::pow(10,SF)
    var Double Offset = (se9k_kWh_Jahr_Offset.state as DecimalType).doubleValue * 1000.0
    var Double Jahr = (resultWh - Offset) / 1000.0
  var String valueWh= resultWh.toString
    var String wrjahr = Jahr.toString
  logInfo("[se9k]  Wh: ", valueWh)
    logInfo("SE9K WR Erzeugung seit 1.1. kWh: ", wrjahr)
  var Double result = resultWh / 1000.0
    postUpdate(se9k_kWh, result)
  postUpdate(se9k_kWh_Jahr, Jahr)

end

rule se9k_DCA_add
when Item se9k_DCA_int received update
then
var Double SF = (se9k_DCASF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = (se9k_DCA_int.state as DecimalType).doubleValue * Math::pow(10,SF)
    var String value = result.toString
    logDebug("SE9K WR Strom DC: ", value)
    postUpdate(se9k_DCA, result)

end

rule se9k_DCV_add
when Item se9k_DCV_int received update
then
var Double SF = (se9k_DCVSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = (se9k_DCV_int.state as DecimalType).doubleValue * Math::pow(10,SF)
    var String value = result.toString
    logDebug("SE9K WR Spannung DC: ", value)
    postUpdate(se9k_DCV, result)

end

rule se9k_DCW_add
when Item se9k_DCW_int received update
then
var Double DCW= (se9k_DCW_int.state as DecimalType).doubleValue
if (DCW > 32767) DCW = DCW-(65536).doubleValue
var Double SF = (se9k_DCWSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = DCW * Math::pow(10,SF)
    var String value = result.toString
    logDebug("SE9K WR Leistung DC: ", value)
    postUpdate(se9k_DCW, result)

end

rule se9k_THS_add
when Item se9k_THS_int received update
then
var Double THS= (se9k_THS_int.state as DecimalType).doubleValue
if (THS > 32767) THS = THS-(65536).doubleValue
var Double SF = (se9k_THSSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = THS * Math::pow(10,SF)
    var String value = result.toString
    logDebug("SE9K Temperatur Kuehlkoerper: ", value)
    postUpdate(se9k_THS, result)

end

rule se9k_Status_map
when Item se9k_Status_int received update
then

var String str="-"
if (se9k_Status_int.state == 1) str = "AUS"
if (se9k_Status_int.state == 2) str = "Nachtmodus"
if (se9k_Status_int.state == 4) str = “AN/Produktion”

    logDebug("Status Wechselrichter:  ", str)
    postUpdate(se9k_Status, str)

end

rule se9k_DID_map
when Item se9k_DID_int received update
then

var String str="-"
if (se9k_DID_int.state == 101) str = "einphasig"
if (se9k_DID_int.state == 102) str = "Split phase"
if (se9k_DID_int.state == 103) str = “dreiphasig”

    logDebug("Status Wechselrichter:  ", str)
    postUpdate(se9k_DID, str)

end

rule se9k_Status__Vendor_map
when Item se9k_Status_vendor_int received update
then

var String str= se9k_Status_Vendor_int.state.toString

    logDebug("Status Wechselrichter (Fehlermeldungen):  ", str)
    postUpdate(se9k_Status_Vendor, str)

end

And finally, the rules needed to populate the Float items for the Modbus meter.

rule se9km_DID_map
when Item se9km_DID_int received update
then

var String str="-"
if (se9km_DID_int.state == 201) str = "Einphasig A-N"
if (se9km_DID_int.state == 202) str = "Split single phase A-B-N"
if (se9km_DID_int.state == 203) str = "Dreiphasig Wye (A-B-C-N)"
if (se9km_DID_int.state == 204) str = “Dreiphasig Delta (A-B-C)”

    logDebug("Einspeisepunkt Smartmeter Typ:  ", str)
    postUpdate(se9km_DID, str)

end

rule se9km_Amp_add
when Item se9km_Amp_int received update
then
var Double Amp= (se9km_Amp_int.state as DecimalType).doubleValue
if (Amp > 32767) Amp = Amp-(65536).doubleValue
var Double SF = (se9km_AmpSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = Amp * Math::pow(10,SF)
    var String value = result.toString
    logDebug("Einpseisepunkt Strom phasensaldiert gesamt: ", value)
    postUpdate(se9km_Amp, result)

end

rule se9km_AmpA_add
when Item se9km_AmpA_int received update
then
var Double Amp= (se9km_AmpA_int.state as DecimalType).doubleValue
if (Amp > 32767) Amp = Amp-(65536).doubleValue
var Double SF = (se9km_AmpSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = Amp * Math::pow(10,SF)
  var String value = result.toString
    logDebug("Einspeisepunkt Strom Ph. A: ", value)
    postUpdate(se9km_AmpA, result)

end

rule se9km_AmpB_add
when Item se9km_AmpB_int received update
then
var String str = "http://192.168.199.41:88/middleware.php/data/"
var String uuid = "212cde50-ef85-11e6-8115-e7892dde135b.json"
var String operation = "?operation=add&value="
var Double Amp= (se9km_AmpB_int.state as DecimalType).doubleValue
if (Amp > 32767) Amp = Amp-(65536).doubleValue
var Double SF = (se9km_AmpSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = Amp * Math::pow(10,SF)
    var String value = result.toString
    logDebug("Einspeisepunkt Strom Ph. B: ", value)
    postUpdate(se9km_AmpB, result)

end

rule se9km_AmpC_add
when Item se9km_AmpC_int received update
then
var Double Amp= (se9km_AmpC_int.state as DecimalType).doubleValue
if (Amp > 32767) Amp = Amp-(65536).doubleValue
var Double SF = (se9km_AmpSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = Amp * Math::pow(10,SF)
    var String value = result.toString
    logDebug("Einspeisepunkt Strom Ph. C: ", value)
    postUpdate(se9km_AmpC, result)

end

rule se9km_VoltL_add
when Item se9km_VoltL_int received update
then
var Double Volt= (se9km_VoltL_int.state as DecimalType).doubleValue
if (Volt > 32767) Volt = Volt-(65536).doubleValue
var Double SF = (se9km_VoltSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = Volt * Math::pow(10,SF)
    
    var String value = result.toString
    logDebug("Einpseisepunkt mittlere Spannung: ", value)
    postUpdate(se9km_VoltL, result)

end

rule se9km_VoltA_add
when Item se9km_VoltA_int received update
then
var Double Volt= (se9km_VoltA_int.state as DecimalType).doubleValue
if (Volt > 32767) Volt = Volt-(65536).doubleValue
var Double SF = (se9km_VoltSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = Volt * Math::pow(10,SF)
    var String value = result.toString
    logDebug("Einpseisepunkt Spannung Ph.A: ", value)
    postUpdate(se9km_VoltA, result)

end

rule se9km_VoltB_add
when Item se9km_VoltB_int received update
then
var Double Volt= (se9km_VoltB_int.state as DecimalType).doubleValue
if (Volt > 32767) Volt = Volt-(65536).doubleValue
var Double SF = (se9km_VoltSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = Volt * Math::pow(10,SF)
    var String value = result.toString
    logDebug("Einpseisepunkt Spannung Ph.B: ", value)
    postUpdate(se9km_VoltB, result)

end

rule se9km_VoltC_add
when Item se9km_VoltC_int received update
then
var Double Volt= (se9km_VoltC_int.state as DecimalType).doubleValue
if (Volt > 32767) Volt = Volt-(65536).doubleValue
var Double SF = (se9km_VoltSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = Volt * Math::pow(10,SF)
    var String value = result.toString
    logDebug("Einpseisepunkt Spannung Ph.C: ", value)
    postUpdate(se9km_VoltC, result)

end

rule se9km_Frequenz_add
when Item se9km_Frequenz_int received update
then
var Double Hz= (se9km_Frequenz_int.state as DecimalType).doubleValue
if (Hz > 32767) Hz = Hz-(65536).doubleValue
var Double SF = (se9km_FrequenzSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = Hz * Math::pow(10,SF)
    var String value = result.toString
    logDebug("Einpseisepunkt Netzfrequenz: ", value)
    postUpdate(se9km_Frequenz, result)

end

rule se9km_Watt_add
when Item se9km_Watt_int received update
then

	var Double Watt= (se9km_Watt_int.state as DecimalType).doubleValue
	if (Watt > 32767) Watt = Watt-(65536).doubleValue
	var Double SF = (se9km_WattSF_int.state as DecimalType).doubleValue
    if (SF > 32767) SF = SF-(65536).doubleValue
    var Double result = -1.0 * Watt * Math::pow(10,SF)
  var Double resultplus = 0.0
  var Double resultminus = 0.0
  if (result > 0) {
  	resultplus = result
  } else {
  	resultminus = result
  }
    
    logInfo("[se9km_Watt ]: ", result.toString)
  logInfo("[se9km_Watt+]: ", resultplus.toString)
  logInfo("[se9km_Watt-]: ", resultminus.toString)
    
    postUpdate(se9km_Watt, result)
    postUpdate(se9km_Wattp, resultplus)
    postUpdate(se9km_Wattm, resultminus)

end

rule se9km_WattA_add
when Item se9km_WattA_int received update
then
var Double Watt= (se9km_WattA_int.state as DecimalType).doubleValue
if (Watt > 32767) Watt = Watt-(65536).doubleValue
var Double SF = (se9km_WattSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = -1.0 * Watt * Math::pow(10,SF)
    var String value = result.toString
    logDebug("Einpseisepunkt Wirkleistung Ph.A: ", value)
    postUpdate(se9km_WattA, result)

end

rule se9km_WattB_add
when Item se9km_WattB_int received update
then
var Double Watt= (se9km_WattB_int.state as DecimalType).doubleValue
if (Watt > 32767) Watt = Watt-(65536).doubleValue
var Double SF = (se9km_WattSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = -1.0 * Watt * Math::pow(10,SF)
    var String value = result.toString
    logDebug("Einpseisepunkt Wirkleistung Ph.B: ", value)
    postUpdate(se9km_WattB, result)

end

rule se9km_WattC_add
when Item se9km_WattC_int received update
then
var Double Watt= (se9km_WattC_int.state as DecimalType).doubleValue
if (Watt > 32767) Watt = Watt-(65536).doubleValue
var Double SF = (se9km_WattSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = -1.0 * Watt * Math::pow(10,SF)
    var String value = result.toString
    logDebug("Einpseisepunkt Wirkleistung Ph.C: ", value)
    postUpdate(se9km_WattC, result)

end

rule se9km_VA_add
when Item se9km_VA_int received update
then
var Double VA= (se9km_VA_int.state as DecimalType).doubleValue
if (VA > 32767) VA = VA-(65536).doubleValue
var Double SF = (se9km_VASF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = VA * Math::pow(10,SF)
    var String value = result.toString
    logDebug("Einpseisepunkt Scheinleistung Summe: ", value)
    postUpdate(se9km_VA, result)

end

rule se9km_VAA_add
when Item se9km_VAA_int received update
then
var Double VA= (se9km_VAA_int.state as DecimalType).doubleValue
if (VA > 32767) VA = VA-(65536).doubleValue
var Double SF = (se9km_VASF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = VA * Math::pow(10,SF)
    var String value = result.toString
    logDebug("Einpseisepunkt Scheinleistung Ph.A: ", value)
    postUpdate(se9km_VAA, result)

end

rule se9km_VAB_add
when Item se9km_VAB_int received update
then
var Double VA= (se9km_VAB_int.state as DecimalType).doubleValue
if (VA > 32767) VA = VA-(65536).doubleValue
var Double SF = (se9km_VASF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = VA * Math::pow(10,SF)
    var String value = result.toString
    logDebug("Einpseisepunkt Scheinleistung Ph.B: ", value)
    postUpdate(se9km_VAB, result)

end

rule se9km_VAC_add
when Item se9km_VAC_int received update
then
var Double VA= (se9km_VAC_int.state as DecimalType).doubleValue
if (VA > 32767) VA = VA-(65536).doubleValue
var Double SF = (se9km_VASF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = VA * Math::pow(10,SF)
    var String value = result.toString
    logDebug("Einpseisepunkt Scheinleistung Ph.C: ", value)
    postUpdate(se9km_VAC, result)

end

rule se9km_VAR_add
when Item se9km_VAR_int received update
then
var Double VAR= (se9km_VAR_int.state as DecimalType).doubleValue
if (VAR > 32767) VAR = VAR-(65536).doubleValue
var Double SF = (se9km_VARSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = VAR * Math::pow(10,SF)
    var String value = result.toString
    logDebug("Einpseisepunkt reaktive Leistung (Summe): ", value)
    postUpdate(se9km_VAR, result)

end

rule se9km_VARA_add
when Item se9km_VARA_int received update
then
var Double VAR= (se9km_VARA_int.state as DecimalType).doubleValue
if (VAR > 32767) VAR = VAR-(65536).doubleValue
var Double SF = (se9km_VARSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = VAR * Math::pow(10,SF)
    var String value = result.toString
    logDebug("Einpseisepunkt reaktive Leistung Ph.A: ", value)
    postUpdate(se9km_VARA, result)

end

rule se9km_VARB_add
when Item se9km_VARB_int received update
then
var Double VAR= (se9km_VARB_int.state as DecimalType).doubleValue
if (VAR > 32767) VAR = VAR-(65536).doubleValue
var Double SF = (se9km_VARSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = VAR * Math::pow(10,SF)
    var String value = result.toString
    logDebug("Einpseisepunkt reaktive Leistung Ph.B: ", value)
    postUpdate(se9km_VARB, result)

end

rule se9km_VARC_add
when Item se9km_VARC_int received update
then
var Double VAR= (se9km_VARC_int.state as DecimalType).doubleValue
if (VAR > 32767) VAR = VAR-(65536).doubleValue
var Double SF = (se9km_VARSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = VAR * Math::pow(10,SF)
    var String value = result.toString
    logDebug("Einpseisepunkt reaktive Leistung Ph.C: ", value)
    postUpdate(se9km_VARC, result)

end

rule se9km_PF_add
when Item se9km_PF_int received update
then
var Double PF= (se9km_PF_int.state as DecimalType).doubleValue
if (PF > 32767) PF = PF-(65536).doubleValue
var Double SF = (se9km_PFSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = PF * Math::pow(10,SF) /100
    var String value = result.toString
    logDebug("Einpseisepunkt Leistungsfaktor MW: ", value)
    postUpdate(se9km_PF, result)

end

rule se9km_PFA_add
when Item se9km_PFA_int received update
then
var Double PF= (se9km_PFA_int.state as DecimalType).doubleValue
if (PF > 32767) PF = PF-(65536).doubleValue
var Double SF = (se9km_PFSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = PF * Math::pow(10,SF) /100
    var String value = result.toString
    logDebug("Einpseisepunkt Leistungsfaktor Ph.A: ", value)
    postUpdate(se9km_PFA, result)

end

rule se9km_PFB_add
when Item se9km_PFB_int received update
then
var Double PF= (se9km_PFB_int.state as DecimalType).doubleValue
if (PF > 32767) PF = PF-(65536).doubleValue
var Double SF = (se9km_PFSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = PF * Math::pow(10,SF) /100
    var String value = result.toString
    logDebug("Einpseisepunkt Leistungsfaktor Ph.B: ", value)
    postUpdate(se9km_PFB, result)

end

rule se9km_PFC_add
when Item se9km_PFC_int received update
then
var Double PF= (se9km_PFC_int.state as DecimalType).doubleValue
if (PF > 32767) PF = PF-(65536).doubleValue
var Double SF = (se9km_PFSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = PF * Math::pow(10,SF) /100
    var String value = result.toString
    logDebug("Einpseisepunkt Leistungsfaktor Ph.C: ", value)
    postUpdate(se9km_PFC, result)

end

rule se9km_kWh_Exp_add
when Item se9km_Wh2_Exp_int received update

then
var Double SF = (se9km_WhSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double resultWh = ((se9km_Wh1_Exp_int.state as DecimalType * 65536).doubleValue + (se9km_Wh2_Exp_int.state as DecimalType).doubleValue) * Math::pow(10,SF)
  var Double resultnegWh = 1000000000 - resultWh
    var Double Offset = (se9km_kWh_Exp_Jahr_Offset.state as DecimalType).doubleValue * 1000.0
    var Double Jahr = (resultWh - Offset) / 1000.0
  var String valueWh = resultWh.toString
  var String valuenegWh = resultnegWh.toString
    var String wrjahr = Jahr.toString
  logInfo("[se9km_Exp      ]  Wh: ",valueWh)
  logInfo("[se9km_Exp (neg)]  Wh: ",valuenegWh)
    logInfo("[se9km_Exp Jahr ] kWh: ", wrjahr)
  var Double result = resultWh / 1000.0
  var Double resultneg = resultnegWh / 1000.0
    postUpdate(se9km_kWh_Exp, result)
    postUpdate(se9km_kWh_Exp_Jahr, Jahr)
    postUpdate(se9km_kWh_Exp_neg, resultneg)

end

rule se9km_kWhA_Exp_add
when Item se9km_WhA2_Exp_int received update

then
var Double SF = (se9km_WhSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = ((se9km_WhA1_Exp_int.state as DecimalType *65536).doubleValue + (se9km_WhA2_Exp_int.state as DecimalType).doubleValue) * Math::pow(10,SF) / 1000.0 
    var String value = result.toString
    logDebug("Einspeisezaehler Ph.A kWh: ", value)
    postUpdate(se9km_kWhA_Exp, result)

end

rule se9km_kWhB_Exp_add
when Item se9km_WhB2_Exp_int received update
then
var Double SF = (se9km_WhSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = ((se9km_WhB1_Exp_int.state as DecimalType * 65536).doubleValue + (se9km_WhB2_Exp_int.state as DecimalType).doubleValue) * Math::pow(10,SF) / 1000.0 
    var String value = result.toString
    logDebug("Einspeisezaehler Ph.B kWh: ", value)
    postUpdate(se9km_kWhB_Exp, result)

end

rule se9km_kWhC_Exp_add
when Item se9km_WhC2_Exp_int received update
then
var Double SF = (se9km_WhSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = ((se9km_WhC1_Exp_int.state as DecimalType * 65536).doubleValue + (se9km_WhC2_Exp_int.state as DecimalType).doubleValue) * Math::pow(10,SF) / 1000.0 
    var String value = result.toString
    logDebug("Einspeisezaehler Ph.C kWh: ", value)
    postUpdate(se9km_kWhC_Exp, result)

end

rule se9km_kWh_Imp_add
when Item se9km_Wh2_Imp_int received update
then
var Double SF = (se9km_WhSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double resultWh = ((se9km_Wh1_Imp_int.state as DecimalType * 65536).doubleValue + (se9km_Wh2_Imp_int.state as DecimalType).doubleValue) * Math::pow(10,SF)
    var Double Offset = (se9km_kWh_Imp_Jahr_Offset.state as DecimalType).doubleValue * 1000.0
    var Double Jahr = (resultWh - Offset) / 1000.0
  var String valueWh = resultWh.toString
  var String urlWh = str + uuidWh + operation + valueWh
    var String wrjahr = Jahr.toString
  logInfo("[se9km_Imp]  Wh: ", valueWh)
    logInfo("[se9km_Imp Jahr] kWh: ", wrjahr)
  var Double result = resultWh / 1000.0
    postUpdate(se9km_kWh_Imp, result)
    postUpdate(se9km_kWh_Imp_Jahr, Jahr)

end

rule se9km_kWhA_Imp_add
when Item se9km_WhA2_Imp_int received update
then
var Double SF = (se9km_WhSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = ((se9km_WhA1_Imp_int.state as DecimalType * 65536).doubleValue + (se9km_WhA2_Imp_int.state as DecimalType).doubleValue) * Math::pow(10,SF) / 1000.0 

    var String value = result.toString
    logDebug("Bezugszaehler Ph.A kWh: ", value)
    postUpdate(se9km_kWhA_Imp, result)

end

rule se9km_kWhB_Imp_add
when Item se9km_WhB2_Imp_int received update
then
var Double SF = (se9km_WhSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = ((se9km_WhB1_Imp_int.state as DecimalType * 65536).doubleValue + (se9km_WhB2_Imp_int.state as DecimalType).doubleValue) * Math::pow(10,SF) / 1000.0 

    var String value = result.toString
    logDebug("Bezugszaehler Ph.B kWh: ", value)
    postUpdate(se9km_kWhB_Imp, result)

end

rule se9km_kWhC_Imp_add
when Item se9km_WhC2_Imp_int received update
then
var Double SF = (se9km_WhSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = ((se9km_WhC1_Imp_int.state as DecimalType * 65536).doubleValue + (se9km_WhC2_Imp_int.state as DecimalType).doubleValue) * Math::pow(10,SF) / 1000.0 
    var String value = result.toString
    logDebug("Bezugszaehler Ph.C kWh: ", value)
    postUpdate(se9km_kWhC_Imp, result)

end

rule se9km_VAh_Exp_add
when Item se9km_VAh2_Exp_int received update
then
var Double SF = (se9km_VAhSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = ((se9km_VAh1_Exp_int.state as DecimalType * 65536).doubleValue + (se9km_VAh2_Exp_int.state as DecimalType).doubleValue) * Math::pow(10,SF) / 1000.0 

    var String value = result.toString
    logDebug("Einspeisezaehler Scheinleistung (Summe) kVAh: ", value)
    postUpdate(se9km_VAh_Exp, result)

end

rule se9km_VAhA_Exp_add
when Item se9km_VAhA2_Exp_int received update
then
var Double SF = (se9km_VAhSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = ((se9km_VAhA1_Exp_int.state as DecimalType * 65536).doubleValue + (se9km_VAhA2_Exp_int.state as DecimalType).doubleValue) * Math::pow(10,SF) / 1000.0 

    var String value = result.toString
    logDebug("Einspeisezaehler Scheinleistung Ph.A kVAh: ", value
    postUpdate(se9km_VAhA_Exp, result)

end

rule se9km_VAhB_Exp_add
when Item se9km_VAhB2_Exp_int received update
then
var Double SF = (se9km_VAhSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = ((se9km_VAhB1_Exp_int.state as DecimalType * 65536).doubleValue + (se9km_VAhB2_Exp_int.state as DecimalType).doubleValue) * Math::pow(10,SF) / 1000.0 

    var String value = result.toString
    logDebug("Einspeisezaehler Scheinleistung Ph.B kVAh: ", value
    postUpdate(se9km_VAhB_Exp, result)

end

rule se9km_VAhC_Exp_add
when Item se9km_VAhC2_Exp_int received update
then
var Double SF = (se9km_VAhSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = ((se9km_VAhC1_Exp_int.state as DecimalType * 65536).doubleValue + (se9km_VAhC2_Exp_int.state as DecimalType).doubleValue) * Math::pow(10,SF) / 1000.0 

    var String value = result.toString
    logDebug("Einspeisezaehler Scheinleistung Ph.C kVAh: ", value
    postUpdate(se9km_VAhC_Exp, result)

end

rule se9km_VAh_Imp_add
when Item se9km_VAh2_Imp_int received update
then
var Double SF = (se9km_VAhSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = ((se9km_VAh1_Imp_int.state as DecimalType * 65536).doubleValue + (se9km_VAh2_Imp_int.state as DecimalType).doubleValue) * Math::pow(10,SF) / 1000.0 

    var String value = result.toString
    logDebug("Bezugszaehler Scheinleistung (Summe) kVAh: ", value
    postUpdate(se9km_VAh_Imp, result)

end

rule se9km_VAhA_Imp_add
when Item se9km_VAhA2_Imp_int received update
then
var Double SF = (se9km_VAhSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = ((se9km_VAhA1_Imp_int.state as DecimalType * 65536).doubleValue + (se9km_VAhA2_Imp_int.state as DecimalType).doubleValue) * Math::pow(10,SF) / 1000.0 
    var String value = result.toString
    logDebug("Bezugszaehler Scheinleistung Ph.A kVAh: ", value
    postUpdate(se9km_VAhA_Imp, result)

end

rule se9km_VAhB_Imp_add
when Item se9km_VAhB2_Imp_int received update
then
var Double SF = (se9km_VAhSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = ((se9km_VAhB1_Imp_int.state as DecimalType * 65536).doubleValue + (se9km_VAhB2_Imp_int.state as DecimalType).doubleValue) * Math::pow(10,SF) / 1000.0 
    var String value = result.toString
    logDebug("Bezugszaehler Scheinleistung Ph.B kVAh: ", value)
    postUpdate(se9km_VAhB_Imp, result)

end

rule se9km_VAhC_Imp_add
when Item se9km_VAhC2_Imp_int received update
then
var Double SF = (se9km_VAhSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = ((se9km_VAhC1_Imp_int.state as DecimalType * 65536).doubleValue + (se9km_VAhC2_Imp_int.state as DecimalType).doubleValue) * Math::pow(10,SF) / 1000.0 
    var String value = result.toString
    logDebug("Bezugszaehler Scheinleistung Ph.C kVAh: ", value
    postUpdate(se9km_VAhC_Imp, result)

end

rule se9km_VARhQ1_add
when Item se9km_VARhQ12_int received update
then
var Double SF = (se9km_VARhSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = ((se9km_VARhQ11_int.state as DecimalType * 65536).doubleValue + (se9km_VARhQ12_int.state as DecimalType).doubleValue) * Math::pow(10,SF) / 1000.0 
    var String value = result.toString
    logDebug("Bezugszaehler Q1 reaktive Energie (Summe) kWh: ", value
    postUpdate(se9km_VARhQ1, result)

end

rule se9km_VARhQ1A_add
when Item se9km_VARhQ1A2_int received update
then
var Double SF = (se9km_VARhSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = ((se9km_VARhQ1A1_int.state as DecimalType * 65536).doubleValue + (se9km_VARhQ1A2_int.state as DecimalType).doubleValue) * Math::pow(10,SF) / 1000.0 
    var String value = result.toString
    logDebug("Bezugszaehler Q1 reaktive Energie Ph.A kVARh: ", value
    postUpdate(se9km_VARhQ1A, result)

end

rule se9km_VARhQ1B_add
when Item se9km_VARhQ1B2_int received update
then
var Double SF = (se9km_VARhSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = ((se9km_VARhQ1B1_int.state as DecimalType * 65536).doubleValue + (se9km_VARhQ1B2_int.state as DecimalType).doubleValue) * Math::pow(10,SF) / 1000.0 
    var String value = result.toString
    logDebug("Bezugszaehler Q1 reaktive Energie Ph.B kVARh: ", value
    postUpdate(se9km_VARhQ1B, result)

end

rule se9km_VARhQ1C_add
when Item se9km_VARhQ1C2_int received update
then
var Double SF = (se9km_VARhSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = ((se9km_VARhQ1C1_int.state as DecimalType * 65536).doubleValue + (se9km_VARhQ1C2_int.state as DecimalType).doubleValue) * Math::pow(10,SF) / 1000.0 
    var String value = result.toString
    logDebug("Bezugszaehler Q1 reaktive Energie Ph.C kVARh: ", value
    postUpdate(se9km_VARhQ1C, result)

end

rule se9km_VARhQ2_add
when Item se9km_VARhQ22_int received update
then
var Double SF = (se9km_VARhSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = ((se9km_VARhQ21_int.state as DecimalType * 65536).doubleValue + (se9km_VARhQ22_int.state as DecimalType).doubleValue) * Math::pow(10,SF) / 1000.0 
    var String value = result.toString
    logDebug("Bezugszaehler Q2 reaktive Energie (Summe) kVARh: ", value)
    postUpdate(se9km_VARhQ2, result)

end

rule se9km_VARhQ2A_add
when Item se9km_VARhQ2A2_int received update
then
var Double SF = (se9km_VARhSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = ((se9km_VARhQ2A1_int.state as DecimalType * 65536).doubleValue + (se9km_VARhQ2A2_int.state as DecimalType).doubleValue) * Math::pow(10,SF) / 1000.0 
    var String value = result.toString
    logDebug("Bezugszaehler Q2 reaktive Energie Ph.A kVARh: ", value)
    postUpdate(se9km_VARhQ2A, result)

end

rule se9km_VARhQ2B_add
when Item se9km_VARhQ2B2_int received update
then
var Double SF = (se9km_VARhSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = ((se9km_VARhQ2B1_int.state as DecimalType * 65536).doubleValue + (se9km_VARhQ2B2_int.state as DecimalType).doubleValue) * Math::pow(10,SF) / 1000.0 
    var String value = result.toString
    logDebug("Bezugszaehler Q2 reaktive Energie Ph.B kVARh: ", value)
    postUpdate(se9km_VARhQ2B, result)

end

rule se9km_VARhQ2C_add
when Item se9km_VARhQ2C2_int received update
then
var Double SF = (se9km_VARhSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = ((se9km_VARhQ2C1_int.state as DecimalType * 65536).doubleValue + (se9km_VARhQ2C2_int.state as DecimalType).doubleValue) * Math::pow(10,SF) / 1000.0 
    var String value = result.toString
    logDebug("Bezugszaehler Q2 reaktive Energie Ph.C kVARh: ", value)
    postUpdate(se9km_VARhQ2C, result)

end

rule se9km_VARhQ3_add
when Item se9km_VARhQ32_int received update
then
var Double SF = (se9km_VARhSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = ((se9km_VARhQ31_int.state as DecimalType * 65536).doubleValue + (se9km_VARhQ32_int.state as DecimalType).doubleValue) * Math::pow(10,SF) / 1000.0 
    var String value = result.toString
    logDebug("Einspeisezaehler Q3 reaktive Energie (Summe) kVARh: ", value)
    postUpdate(se9km_VARhQ3, result)

end

rule se9km_VARhQ3A_add
when Item se9km_VARhQ3A2_int received update
then
var Double SF = (se9km_VARhSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = ((se9km_VARhQ3A1_int.state as DecimalType * 65536).doubleValue + (se9km_VARhQ3A2_int.state as DecimalType).doubleValue) * Math::pow(10,SF) / 1000.0 
    var String value = result.toString
    logDebug("Einspeisezaehler Q3 reaktive Energie Ph.A kVARh: ", value)
    postUpdate(se9km_VARhQ3A, result)

end

rule se9km_VARhQ3B_add
when Item se9km_VARhQ3B2_int received update
then
var Double SF = (se9km_VARhSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = ((se9km_VARhQ3B1_int.state as DecimalType * 65536).doubleValue + (se9km_VARhQ3B2_int.state as DecimalType).doubleValue) * Math::pow(10,SF) / 1000.0 
    var String value = result.toString
    logDebug("Einspeisezaehler Q3 reaktive Energie Ph.B kVARh: ", value)
    postUpdate(se9km_VARhQ3B, result)

end

rule se9km_VARhQ3C_add
when Item se9km_VARhQ3C2_int received update
then
var Double SF = (se9km_VARhSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = ((se9km_VARhQ3C1_int.state as DecimalType * 65536).doubleValue + (se9km_VARhQ3C2_int.state as DecimalType).doubleValue) * Math::pow(10,SF) / 1000.0 
    var String value = result.toString
    logDebug("Einspeisezaehler Q3 reaktive Energie Ph.C kVARh: ", value)
    postUpdate(se9km_VARhQ3C, result)

end

rule se9km_VARhQ4_add
when Item se9km_VARhQ42_int received update
then
var Double SF = (se9km_VARhSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = ((se9km_VARhQ41_int.state as DecimalType * 65536).doubleValue + (se9km_VARhQ42_int.state as DecimalType).doubleValue) * Math::pow(10,SF) / 1000.0 
    var String value = result.toString
    logDebug("Einspeisezaehler Q4 reaktive Energie (Summe) kVARh: ", value)
    postUpdate(se9km_VARhQ4, result)

end

rule se9km_VARhQ4A_add
when Item se9km_VARhQ4A2_int received update
then
var Double SF = (se9km_VARhSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = ((se9km_VARhQ4A1_int.state as DecimalType * 65536).doubleValue + (se9km_VARhQ4A2_int.state as DecimalType).doubleValue) * Math::pow(10,SF) / 1000.0 
    var String value = result.toString
    logDebug("Einspeisezaehler Q4 reaktive Energie Ph.A kVARh: ", value)
    postUpdate(se9km_VARhQ4A, result)

end

rule se9km_VARhQ4B_add
when Item se9km_VARhQ4B2_int received update
then
var Double SF = (se9km_VARhSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = ((se9km_VARhQ4B1_int.state as DecimalType * 65536).doubleValue + (se9km_VARhQ4B2_int.state as DecimalType).doubleValue) * Math::pow(10,SF) / 1000.0 
    var String value = result.toString
    logDebug("Einspeisezaehler Q4 reaktive Energie Ph.B kVARh: ", value)
    postUpdate(se9km_VARhQ4B, result)

end

rule se9km_VARhQ4C_add
when Item se9km_VARhQ4C2_int received update
then
var Double SF = (se9km_VARhSF_int.state as DecimalType).doubleValue
if (SF > 32767) SF = SF-(65536).doubleValue

    var Double result = ((se9km_VARhQ4C1_int.state as DecimalType * 65536).doubleValue + (se9km_VARhQ4C2_int.state as DecimalType).doubleValue) * Math::pow(10,SF) / 1000.0 
    var String value = result.toString
    logDebug("Einspeisezaehler Q4 reaktive Energie Ph.C kVARh: ", value)
    postUpdate(se9km_VARhQ4C, result)

end

1 Like

Please note that the binding actually opens only single connection, even in the case of many “slaves” in the config. Each slave definition maps to single modbus request.

Even better, the extended item syntax in binding 1.10.0 (see docs here http://docs.openhab.org/addons/bindings/modbus1/readme.html#extended-format) allows you to override valuetype per item.

Perhaps you can simplify the rules using this functionality?

Best
Sami

Hello Sami,

yes I am aware and I did run a number of tests with multiple slaves and a lot of timings. Initially, I had three slaves, one for each valuetype. However it seems that the inverter needs quite a bit of time to recover from read requests and I was not able to get a working config that had more that this minimal number of slaves.

Cheers,

Thomas

Ok that makes then! I think I misunderstood your first post then.

As said, you can use the 1.10.0 functionality to set valuetype per each item separately. If you have single slave, only single request is Sent.

However, I noticed the 32 bit types read from n’th item (first register index would be ((slave start) + (read index)*2)) which means that it’s not applicable to all situations (e.g. When you would like to read 32bit type offsetted by one register).

And transformations are not useful when the transformation should use information from many registers.

So yeah, I think you are right, it does not get much simpler than that.

Sami

Here’s a nice graph of all the data that we have been reading (plus some derived values, such as the directly consumed energy in the house) from a really sunny day.
You can also see where the logic triggers the heatpump to produce some extra hot water with all the nice free energy from the sun.
The graphs are generated using the volkszaehler.org metering application. In my rules, I have some code to feed the data that we read from the inverter to the volkszaehler middleware API. I guess you could also us InfluxDB persistence and feed the data to grafana to produce similar results, but I like the volkszaehler since it is specifically designed to handle meter data.

There are some useful items that you might want to calculate once you have production, export and import power value available, such as:

Directly used energy in your house (“Eigenverbrauch” in german):

Eigenverbrauch = Production - Export

The total used power in your house:

Total = Production + Import - Export

(take care, since Export might be a negative value, so this might actually be Production + Import + Export in that case)

The fraction of the produced solar energy that you use directly in the house without feeding it to the grid (“Eigenverbrauchsanteil” in german):

Eigenverbrauchsanteil = Directly used energy / total production

The part of your total energy usage that you were able to cover by your solar power plant (“Solarer Deckungsgrad” in german):

Solarer Deckungsgrad = Eigenverbrauch / Total used power

Here’s some rules I set up for this (again, sorry for the german item names, I hope you can figure it out):

// Eigenverbrauch (Direktverbrauch) = Erzeugung - Einspeisung
rule se9km_Eigenverbrauch_add
when
Item se9k_kWh received update

then

    var Double result = (se9k_kWh.state as DecimalType).doubleValue - (se9km_kWh_Exp.state as DecimalType).doubleValue
    var String value = result.toString
    logDebug("Eigenverbrauchszaehler kWh: ", value)
    postUpdate(se9km_kWh_Eigen, result)

end

rule se9km_Eigenverbrauchsanteil_Jahr_add
when
Item se9km_kWh_Eigen_Jahr received update

then

    var Double result = (se9km_kWh_Eigen_Jahr.state as DecimalType).doubleValue / (se9k_kWh_Jahr.state as DecimalType).doubleValue * 100.0
    var String value = result.toString
    logDebug("Eigenverbrauchsanteil Jahr: ", value)
    postUpdate(se9km_Eigenanteil_Jahr, result)

end

//Gesamtverbrauch = Eigenverbrauch + Bezug
// = Erzeugung - Einspeisung + Bezug
rule se9km_Gesamtverbrauch_add
when
Item se9km_kWh_Imp received update

then
var Double result = (se9km_kWh_Imp.state as DecimalType).doubleValue + (se9k_kWh.state as DecimalType).doubleValue - (se9km_kWh_Exp.state as DecimalType).doubleValue

    var String value = result.toString
    logDebug("Gesamtverbrauchszaehler Haus kWh: ", value)
    postUpdate(se9km_kWh_Gesamtverbrauch, result)

end

// solarer Deckungsgrad = Eigenverbrauch / Gesamtverbrauch
rule se9km_SolDeckung_add
when
Item se9km_kWh_Eigen received update
or
Item se9km_kWh_Gesamtverbrauch received update

then

    var Double result = (se9km_kWh_Eigen.state as DecimalType).doubleValue / (se9km_kWh_Gesamtverbrauch.state as DecimalType).doubleValue  * 100.0
    var String value = result.toString
    logDebug("solare Deckung: ", value)
    postUpdate(se9km_SolDeckung, result)

end

All the values above use energy meter values rather than power values. These are good to keep track of the total energy values over a longer period of time. However, I found that due to the limited resolution of these values, you will sometimes see jumps in your power graphs. To visualize data (i.e. the nice power graph of the previous post, I usually don’t use energy meter values, but rather I use power values. Here’s a rule that will generate all those derived values and put them into some items:

rule "Update Zaehler und abgeleitete Zaehler"
when Item se9km_Watt received update
then
var Double erzeugung = (se9k_Watt.state as DecimalType).doubleValue
// gridpower = bezug - einspeisung
var Double gridpower = (se9km_Watt.state as DecimalType).doubleValue
var Double verbrauch = erzeugung + gridpower
// Direktverbrauch = Erzeugung - Einspeisung
var Double direktverbrauch = 0.0
// Watthaus = Gesamtverbrauch Haus (Erzeugung + Bezug + Einspeisung)
sendCommand(se9km_WattHaus,verbrauch)

    if (gridpower < 0.0) {
                    direktverbrauch = erzeugung + gridpower
    } else if (gridpower > 0.0) {
                    direktverbrauch = erzeugung
    }
            sendCommand(se9km_direkt,direktverbrauch)
            var String valuedirekt = direktverbrauch.toString
        logInfo("[se9km_WattHaus: ]", valueWattHaus.toString)
            logInfo("[se9km_direkt: ]", valuedirekt.toString)

end

From your experience: Is this going to work with any sun spec implementing inverter? It would be really nice if I could concentrate on the special rules for my heatpump (systemair) instead of replicating all the stuff for Fronius symo inverters.

Thanks

Thomas
(http://www.fronius.com/cps/rde/xchg/SID-2FCEEEAF-3476C114/fronius_international/hs.xsl/83_33732_DEU_HTML.htm#.WOzm3kdCShc)

I guess the answer is “it depends”. Apparently Fronius implements two type of sunpec register maps, one for float and one for integer + scale factors. If your inverter does Integer + scale factors, you should be good with my code. Browsing briefly through the documentation on the Fronius Website, it seems that you should be able to configure the inverter for float oder integer + scale factors to your liking. It also seems that you might need to adjust the Modbus ID in the slave definition to match your inverter and smartmeter if present.

BR,

Thomas

Hello Thomas
Thank you very much, great work! I just could copy and paste !
Do you have also the “code” for the data to push to volkszähler ?

Michael

Sure, the principle is pretty easy. In those rules where you calculate the float values, just add a bit of code to push data into the volkszaehler using it’s API.

The URL is like: “http://ip-address/middleware.php/data/uuid.json?operation=add&value=value

The uuid is the uuid of an existing channel in the volkszaehler (just add one of the correct type using the frontend).

A bit of code to add at the end of each rule would look like this:

        var String str = "http://<ip>/middleware.php/data/"
        var String uuid = "<uuid>.json"
        var String operation = "?operation=add&value="
        var String value = result.toString
        var String url = str + uuid + operation + value
        sendHttpGetRequest(url)

Assuming that the variable “result” holds the value that you want to add.

Cheers,

Thomas

Hi @miesi1,

I have a working config which polls most of the data from a Fronius inverter if you need it.

Brent

I would love to see it documented for the community in rhis section :sunglasses:

The items could probably use some tidying up - I did this a while ago in OpenHAB 1.x which I stopped using then recently converted it to OH2. Unlike in the above example- I was able to use mutiple poll requests, so used a separate poll for each block of contiguous data. This may not be the most efficient, but it works.

modbus.cfg

#Separate connection blocks required for different register type polls
poll=2000

tcp.FroniusBlk1.connection=192.168.21.202:502
tcp.FroniusBlk1.id=1
tcp.FroniusBlk1.start=213
tcp.FroniusBlk1.length=1
tcp.FroniusBlk1.type=holding
tcp.FroniusBlk1.valuetype=uint16

tcp.FroniusBlk2.connection=192.168.21.202:502
tcp.FroniusBlk2.id=1
tcp.FroniusBlk2.start=499
tcp.FroniusBlk2.length=14
tcp.FroniusBlk2.type=holding
tcp.FroniusBlk2.valuetype=uint32

tcp.FroniusBlk3.connection=192.168.21.202:502
tcp.FroniusBlk3.id=1
tcp.FroniusBlk3.start=40071
tcp.FroniusBlk3.length=22
tcp.FroniusBlk3.type=holding
tcp.FroniusBlk3.valuetype=float32

tcp.FroniusBlk4.connection=192.168.21.202:502
tcp.FroniusBlk4.id=1
tcp.FroniusBlk4.start=40091
tcp.FroniusBlk4.length=20
tcp.FroniusBlk4.type=holding
tcp.FroniusBlk4.valuetype=float32

tcp.FroniusBlk5.connection=192.168.21.202:502
tcp.FroniusBlk5.id=1
tcp.FroniusBlk5.start=40117
tcp.FroniusBlk5.length=1
tcp.FroniusBlk5.type=holding
tcp.FroniusBlk5.valuetype=uint16

tcp.FroniusBlk6.connection=192.168.21.202:502
tcp.FroniusBlk6.id=1
tcp.FroniusBlk6.start=40123
tcp.FroniusBlk6.length=8
tcp.FroniusBlk6.type=holding
tcp.FroniusBlk6.valuetype=uint32

tcp.FroniusBlk7.connection=192.168.21.202:502
tcp.FroniusBlk7.id=1
tcp.FroniusBlk7.start=40281
tcp.FroniusBlk7.length=31
tcp.FroniusBlk7.type=holding
tcp.FroniusBlk7.valuetype=uint16

items

Group 	gMyOpenHab
Group 	gSolar
Group	gSolarMain	(gSolar)
Group 	gSolarPower	(gSolar)
Group 	gSolarAC		(gSolar)		
Group 	gSolarDC		(gSolar)
Group	gSolarInfo	(gSolar)
/* Solar 
Number  Solar_Active_StateCode   "Current State [%d]"                  (gSolarMain) {modbus="FroniusBlk1:0"}

Number  Solar_Site_Power         	"Actual Power [%d W]"                  (gSolarMain, gSolarPower) {modbus="FroniusBlk2:0"}
//Number  Solar_Site_Energy_Day_HW 	"Generated Today HW [%d Wh]"         (gSolarMain, gSolarPower) {modbus="FroniusBlk2:1"}
Number  Solar_Site_Energy_Day 		"Generated Today [%d Wh]"            (gSolarMain, gSolarPower) {modbus="FroniusBlk2:2"}
//Number  Solar_F_Site_Energy_Year_HW "Generated Year HW [%d Wh]"      (gSolarPower) {modbus="FroniusBlk2:3"}
Number  Solar_F_Site_Energy_Year_LW "Generated Year  [%d Wh]"          (gSolarPower) {modbus="FroniusBlk2:4"}
//Number  Solar_F_Site_Energy_Tot_HW"Generated Lifetime HW [%d Wh]"        (gSolarPower) {modbus="FroniusBlk2:5"}
Number  Solar_F_Site_Energy_Tot_LW	"Generated Lifetime [%d Wh]"        (gSolarPower) {modbus="FroniusBlk2:6"}

Number  Solar_AC_Current         "AC total current [%.2f A]"               (gSolarAC) {modbus="FroniusBlk3:0"}
Number  Solar_AphA               "AC phase A current [%.2f A]"            (gSolarAC) {modbus="FroniusBlk3:1"}
Number  Solar_AphB               "AC phase B current [%.2f  A]"            (gSolarAC) {modbus="FroniusBlk3:2"}
Number  Solar_AphC               "AC phase C current [%.2f  A]"            (gSolarAC) {modbus="FroniusBlk3:3"}
Number  Solar_PPVphBC            "AC voltage phase BC [%.2f V]"           (gSolarAC) {modbus="FroniusBlk3:5"}
Number  Solar_PPVphCA            "AC voltage phase CA [%.2f V]"           (gSolarAC) {modbus="FroniusBlk3:6"}
Number  Solar_PPVphAB            "AC voltage phase AB [%.2f V]"           (gSolarAC) {modbus="FroniusBlk3:4"}
Number  Solar_PhVphA             "AC voltage phase AN [%.2f V]"           (gSolarAC) {modbus="FroniusBlk3:7"}
Number  Solar_PhVphB             "AC voltage phase BN [%.2f V]"           (gSolarAC) {modbus="FroniusBlk3:8"}
Number  Solar_PhVphC             "AC voltage phase CN [%.2f V]"           (gSolarAC) {modbus="FroniusBlk3:9"}

Number  Solar_AC_Power           "AC power [%.2f W]"                      (gSolarAC) {modbus="FroniusBlk4:0"}
Number  Solar_AC_Freq            "AC frequency [%.2f  Hz]"                 (gSolarAC) {modbus="FroniusBlk4:1"}
Number  Solar_WH                 "AC lifetime energy production [%.0f Wh]"(gSolarAC) {modbus="FroniusBlk4:5"}
//BCK 16/07/17 for some reason Solar_DCA & Solar_DCV below cause errors - need to look at it
//Number  Solar_DCA                "DC current [%.2f  A]"                    (gSolarDC) {modbus="FroniusBlk4:6"}
//Number  Solar_DCV                "DC voltage [%.2f  V]"                    (gSolarDC) {modbus="FroniusBlk4:7"}
Number  Solar_DCW                "DC power [%.2f  W]"                      (gSolarDC) {modbus="FroniusBlk4:8"}

Number  Solar_State              "Operating state (enum)[%d]"            (gSolarInfo) {modbus="FroniusBlk5:0"}

Number  Solar_EvtVnd1            "Event Flag 1 [%d]Bit field"          (gSolarInfo) {modbus="FroniusBlk6:0"}
Number  Solar_EvtVnd2            "Event Flag 2 [%d]Bit field"          (gSolarInfo) {modbus="FroniusBlk6:1"}
Number  Solar_EvtVnd3            "Event Flag 3 [%d]Bit field"          (gSolarInfo) {modbus="FroniusBlk6:2"}
Number  Solar_EvtVnd4            "Event Flag 4 [%d]Bit field"          (gSolarInfo) {modbus="FroniusBlk6:3"}

Number  Solar_1_DCA              "String 1 DC current [%d A]"           (gSolarDC) {modbus="FroniusBlk7:0"}
Number  Solar_1_DCV              "String 1 DC voltage [%d V]"           (gSolarDC) {modbus="FroniusBlk7:1"}
Number  Solar_1_DCW              "String 1 DC power [%d W]"             (gSolarDC) {modbus="FroniusBlk7:2"}
Number  Solar_1_Tmp              "String 1 Temperature [%d C]"          (gSolarDC) {modbus="FroniusBlk7:7"}
Number  Solar_1_DCSt             "String 1 Operating state [%d]"       (gSolarDC) {modbus="FroniusBlk7:8"}
Number  Solar_2_DCA              "String 2 DC current [%d A]"           (gSolarDC) {modbus="FroniusBlk7:20"}
Number  Solar_2_DCV              "String 2 DC voltage [%d V]"           (gSolarDC) {modbus="FroniusBlk7:21"}
Number  Solar_2_DCW              "String 2 DC power [%d W]"             (gSolarDC) {modbus="FroniusBlk7:22"}
Number  Solar_2_Tmp              "String 2 Temperature [%d C]"          (gSolarDC) {modbus="FroniusBlk7:27"}
Number  Solar_2_DCSt             "String 2 Operating state [%d]"       (gSolarDC) {modbus="FroniusBlk7:28"}

Hopefully somebody finds this useful.

Brent

1 Like

Hello Thomas,

I don’t use openhab but iobroker - but maybe you can help anyway :sunglasses:
You seem to be able to interpret the values that the inverter and the Modbus meter output.
Can you tell me how I can use the values to determine the current consumption of the house?
The value must be determined by the inverter as it is displayed in the SolarEdge web interface.

Here are the values I read from the Modbus counter:

 address   name   description   unit   type   len   factor   offset   role   room   poll   wp
40071   I_AC_Current   AC Total Current value   Amp   uint16be   1   1   0   level      true   false   
40075   I_AC_Current_SF   AC Current scale factor      int16be   1   1   0   level      true   false   
40083   I_AC_Power   AC Power value   W   int16be   1   1   0   level      true   false   
40084   I_AC_Power_SF   AC Power scale factor      int16be   1   1   0   level      true   false   
40085   I_AC_Frequency   AC Frequency value   Hz   uint16be   1   0.01   0   level      true   false   
40093   I_AC_Energy_WH   AC Lifetime Energy production   kWh   int32be   2   0.001   0   level      true   false   
40098   I_DC_Voltage   DC Voltage value   V   uint16be   1   0.1   0   level      true   false   
40100   I_DC_Power   DC Power Value   W   int16be   1   0.1   0   level      true   false   
40103   I_Temp_Sink   Temperatur   °C   int16be   1   1   0   level      true   false   
40107   I_Status   Operation State      uint16be   1   1   0   level      true   false   
40154   C_Option   Export + Import, Production, consumption,   NA   string   8   1   0   level      true   false   
40189   M_AC_Current   AC Current (sum of active phases)   A   int16be   1   1   0   level      true   false   
40193   M_AC_Current_S F   AC Current Scale Factor   SF   int16be   1   1   0   level      true   false   
40194   M_AC_Voltage_L N   Line to Neutral AC Voltage (average of active phases)   V   int16be   1   1   0   level      true   false   
40198   M_AC_Voltage_L L   Line to Line AC Voltage (average of active phases)   V   int16be   1   1   0   level      true   false   
40202   M_AC_Voltage_S F   AC Voltage Scale Factor   V   int16be   1   1   0   level      true   false   
40203   M_AC_Freq   AC Frequency   Hz   int16be   1   1   0   level      true   false   
40204   M_AC_Freq_SF   AC Frequency Scale Factor   SF   int16be   1   1   0   level      true   false   
40205   M_AC_Power   Total Real Power (sum of active phases)   W   uint16be   1   1   0   level      true   false   
40209   M_AC_Power_SF   AC Real Power Scale Factor   SW   int16be   1   1   0   level      true   false   
40210   M_AC_VA   Total AC Apparent Power (sum of active phases)   VA   int16be   1   1   0   level      true   false   
40214   M_AC_VA_SF   AC Apparent Power Scale Factor   SF   int16be   1   1   0   level      true   false   
40215   M_AC_VAR   Total AC Reactive Power (sum of active phases)   VAR   int16be   1   1   0   level      true   false   
40219   M_AC_VAR_SF   AC Reactive Power Scale Factor   %   int16be   1   1   0   level      true   false   
40220   M_AC_PF   Average Power Factor (average of active phases)   %   int16be   1   1   0   level      true   false   
40224   M_AC_PF_SF   AC Power Factor Scale Factor   SF   int16be   1   1   0   level      true   false   
40225   M_Exported   Total Exported Real Energy   Wh   uint32le   2   1   0   level      true   false   
40233   M_Imported   Total Imported Real Energy   Wh   uint32le   2   1   0   level      true   false   
40233   M_Imported   Total Imported Real Energy   Wh   uint32le   2   1   0   level      true   false   
40241   M_Energy_W_SF   Real Energy Scale Factor   Wh   int16be   1   1   0   level      true   false   
40242   M_Exported_VA   Total Exported Apparent Energy   VAh   uint32le   2   1   0   level      true   false   
40106   I_Temp_SF   Scale factor      int16be   1   1   0   level      true   false

Kind regards,
Olli

The current consumption of your house would be:

House = inverter power (I_AC_Power) + modbus meter power (M_AC_Power)

Assuming, that the modbus meter counts exported energy as negative values and imported as positive values.
As highlighted above, you need to use the scaling factor (M_AC_Power_SF) to scale your power values:

Modbus meter power = M_AC_Power * exp (10, M_AC_Power_SF)
Interver meter power = I_AC_Power * exp (10, I_AC_Power_SF)

BR,

Thomas

thx Thomas,

FYI, there is a new 2.x binding for Solaredge inverters which is using the web monitoring portal API for data, which is very easy to install and setup.
It’s the only solution for older inverters which lacks modbus communication port. You don’t even need a website API key.
Only the Solaredge web monitoring credentials are needed.