Reading data from Huawei inverter SUN 2000 (3KTL-10KTL) via modbus TCP and RTU

Hello,

I made some configuration to read all the data from the huawei SUN 2000 inverters with the modbus binding.And i want to share it so other people can use it to.

With the Huawei Smart Dongle-WLAN-FE you can connect with modbusTCP and Fusion solar app at the same time.
With modbus RTU you can not connect to the Fusion solar app and with modbus RTU at the same time.

To connect via TCP you need the Smart Dongle-WLAN-FE with the latest software update (SDongle_V100R001C00SPC120_package) and take the TCPBridgeModbus in the BridgeModbus.things file.

To connect via RTU u need a usb to modbus RS485 converter.
I connected data + to port pin 1 and data - to port pin 3 of the signal cable.
If you have a slightly different model than me, you should take a look at the manual because apparently there is a difference on the pin out of other models.
You have to remove the wlan smart dongle if you want to connect with serial RTU modbus.
And take the RTUBridgeModbus in the BridgeModbus.things file

For more info on how to configure usb port en modbus please read the modbus binding doc

For openHAB3 GIU configuration .

BridgeModbus.things

//Choose the bridge you want to use and delete the other one.
Bridge modbus:tcp:localhostTCP [ host="your_inverter_ip", port=502, id=1 ]{

Bridge modbus:serial:slave100 [ port="/dev/ttyUSB0" ,id=1 , baud=9600, stopBits="1", parity="none", dataBits=8, encoding="rtu" ]{



Bridge poller slave101holding [ start=30073, length=10, refresh=10000, type="holding" ]{
    
        Thing data Rated_power                      [ readStart="30073", readValueType="uint32",readTransform="JS(divide1000.js)",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Maximum_active_power             [ readStart="30075", readValueType="uint32",readTransform="JS(divide1000.js)",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Maximum_apparent_power           [ readStart="30077", readValueType="uint32",readTransform="JS(divide1000.js)",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Maximum_reactive_power_fed       [ readStart="30079", readValueType="int32",readTransform="JS(divide1000.js)",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Maximum_reactive_power_absorbed  [ readStart="30081", readValueType="int32",readTransform="JS(divide1000.js)",updateUnchangedValuesEveryMillis="5000000" ]

   }

Bridge poller slave102holding [ start=32000, length=1, refresh=10000, type="holding" ]{


        Thing data Standalone_tele_indicationbit0          [ readStart="32000.0", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Standalone_tele_indicationbit1          [ readStart="32000.1", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ] 
        Thing data Standalone_tele_indicationbit2          [ readStart="32000.2", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]     
        Thing data Standalone_tele_indicationbit3          [ readStart="32000.3", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ] 
        Thing data Standalone_tele_indicationbit4          [ readStart="32000.4", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Standalone_tele_indicationbit5          [ readStart="32000.5", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ] 
        Thing data Standalone_tele_indicationbit6          [ readStart="32000.6", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ] 
        Thing data Standalone_tele_indicationbit7          [ readStart="32000.7", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ] 
        Thing data Standalone_tele_indicationbit8          [ readStart="32000.8", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ] 
        Thing data Standalone_tele_indicationbit9          [ readStart="32000.9", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Standalone_tele_indicationbit10         [ readStart="32000.10", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Standalone_tele_indicationbit11         [ readStart="32000.11", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Standalone_tele_indicationbit12         [ readStart="32000.12", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Standalone_tele_indicationbit13         [ readStart="32000.13", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Standalone_tele_indicationbit14         [ readStart="32000.14", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Standalone_tele_indicationbit15         [ readStart="32000.15", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]

   }

Bridge poller slave102aholding [ start=32002, length=1, refresh=10000, type="holding" ]{
    
        Thing data Operating_statusbit0                 [ readStart="32002.0", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Operating_statusbit1                 [ readStart="32002.1", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ] 
        Thing data Operating_statusbit2                 [ readStart="32002.2", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]  

   }

Bridge poller slave103holding [ start=32008, length=1, refresh=10000, type="holding" ]{

        
        Thing data Alarm_1bit0                          [ readStart="32008.0", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Alarm_1bit1                          [ readStart="32008.1", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Alarm_1bit2                          [ readStart="32008.2", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Alarm_1bit3                          [ readStart="32008.3", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Alarm_1bit4                          [ readStart="32008.4", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Alarm_1bit5                          [ readStart="32008.5", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Alarm_1bit6                          [ readStart="32008.6", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Alarm_1bit7                          [ readStart="32008.7", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Alarm_1bit8                          [ readStart="32008.8", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Alarm_1bit9                          [ readStart="32008.9", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Alarm_1bit10                         [ readStart="32008.10", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Alarm_1bit11                         [ readStart="32008.11", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Alarm_1bit12                         [ readStart="32008.12", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Alarm_1bit13                         [ readStart="32008.13", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Alarm_1bit14                         [ readStart="32008.14", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Alarm_1bit15                         [ readStart="32008.15", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]

    }

Bridge poller slave103aholding [ start=32009, length=1, refresh=10000, type="holding" ]{        
        
        Thing data Alarm_2bit0                          [ readStart="32009.0", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Alarm_2bit1                          [ readStart="32009.1", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Alarm_2bit2                          [ readStart="32009.2", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Alarm_2bit3                          [ readStart="32009.3", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Alarm_2bit4                          [ readStart="32009.4", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Alarm_2bit5                          [ readStart="32009.5", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Alarm_2bit6                          [ readStart="32009.6", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Alarm_2bit7                          [ readStart="32009.7", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Alarm_2bit8                          [ readStart="32009.8", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Alarm_2bit9                          [ readStart="32009.9", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Alarm_2bit10                         [ readStart="32009.10", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Alarm_2bit11                         [ readStart="32009.11", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Alarm_2bit12                         [ readStart="32009.12", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Alarm_2bit13                         [ readStart="32009.13", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Alarm_2bit14                         [ readStart="32009.14", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Alarm_2bit15                         [ readStart="32009.15", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]

    } 

//Bridge poller slave103bholding [ start=32010, length=1, refresh=1000, type="holding" ]{        
                
        
    //    Thing data Alarm_3bit0                          [ readStart="320010.0", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
    //    Thing data Alarm_3bit1                          [ readStart="320010.1", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
    //    Thing data Alarm_3bit2                          [ readStart="320010.2", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
    //    Thing data Alarm_3bit3                          [ readStart="320010.3", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
    //    Thing data Alarm_3bit4                          [ readStart="320010.4", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
    //    Thing data Alarm_3bit5                          [ readStart="320010.5", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
    //    Thing data Alarm_3bit6                          [ readStart="320010.6", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
    //    Thing data Alarm_3bit7                          [ readStart="320010.7", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
    //    Thing data Alarm_3bit8                          [ readStart="320010.8", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
    //    Thing data Alarm_3bit9                          [ readStart="320010.9", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
    //    Thing data Alarm_3bit10                         [ readStart="320010.10", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
    //    Thing data Alarm_3bit11                         [ readStart="320010.11", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
    //    Thing data Alarm_3bit12                         [ readStart="320010.12", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
    //    Thing data Alarm_3bit13                         [ readStart="320010.13", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
    //    Thing data Alarm_3bit14                         [ readStart="320010.14", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
    //    Thing data Alarm_3bit15                         [ readStart="320010.15", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]

//   }

Bridge poller slave104holding [ start=32016, length=8, refresh=1000, type="holding" ]{
    
        Thing data Pv_1_Voltage                    [ readStart="32016", readValueType="int16",readTransform="JS(divide10.js)",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Pv_1_Current                    [ readStart="32017", readValueType="int16",readTransform="JS(divide100.js)",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Pv_2_Voltage                    [ readStart="32018", readValueType="int16",readTransform="JS(divide10.js)",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Pv_2_Current                    [ readStart="32019", readValueType="int16",readTransform="JS(divide100.js)",updateUnchangedValuesEveryMillis="5000000" ]
       // Thing data Pv_3_Voltage                    [ readStart="32020", readValueType="int16",readTransform="JS(divide10.js)",updateUnchangedValuesEveryMillis="5000000" ]
       // Thing data Pv_3_Current                    [ readStart="32021", readValueType="int16",readTransform="JS(divide100.js)",updateUnchangedValuesEveryMillis="5000000" ]
       // Thing data Pv_4_Voltage                    [ readStart="32022", readValueType="int16",readTransform="JS(divide10.js)",updateUnchangedValuesEveryMillis="5000000" ]
       // Thing data Pv_4_Current                    [ readStart="32023", readValueType="int16",readTransform="JS(divide100.js)",updateUnchangedValuesEveryMillis="5000000" ]

   }

Bridge poller slave105holding [ start=32064, length=31, refresh=1000, type="holding" ]{
    
        Thing data Input_power                    [ readStart="32064", readValueType="int32",readTransform="JS(divide1000.js)",updateUnchangedValuesEveryMillis="5000000" ]     
        Thing data Uab                            [ readStart="32066", readValueType="uint16",readTransform="JS(divide10.js)",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Ubc                            [ readStart="32067", readValueType="uint16",readTransform="JS(divide10.js)",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Uca                            [ readStart="32068", readValueType="uint16",readTransform="JS(divide10.js)",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Ua                             [ readStart="32069", readValueType="uint16",readTransform="JS(divide10.js)",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Ub                             [ readStart="32070", readValueType="uint16",readTransform="JS(divide10.js)",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Uc                             [ readStart="32071", readValueType="uint16",readTransform="JS(divide10.js)",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data La                             [ readStart="32072", readValueType="int32",readTransform="JS(divide1000.js)",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Lb                             [ readStart="32074", readValueType="int32",readTransform="JS(divide1000.js)",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Lc                             [ readStart="32076", readValueType="int32",readTransform="JS(divide1000.js)",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Active_peak_of_current_day     [ readStart="32078", readValueType="int32",readTransform="JS(divide1000.js)",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Active_power                   [ readStart="32080", readValueType="int32",readTransform="JS(divide1000.js)",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Reactive_power                 [ readStart="32082", readValueType="int32",readTransform="JS(divide1000.js)",updateUnchangedValuesEveryMillis="5000000" ]     
        Thing data Power_factor                   [ readStart="32084", readValueType="int16",readTransform="JS(divide1000.js)",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Frequency                      [ readStart="32085", readValueType="uint16",readTransform="JS(divide100.js)",updateUnchangedValuesEveryMillis="5000000" ] 
        Thing data Inverter_efficiency            [ readStart="32086", readValueType="uint16",readTransform="JS(divide100.js)",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Cabinet_temperature            [ readStart="32087", readValueType="int16",readTransform="JS(divide10.js)",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Insulation_resistance          [ readStart="32088", readValueType="uint16",readTransform="JS(divide1000.js)",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Device_status                  [ readStart="32089", readValueType="uint16",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Fault_code                     [ readStart="32090", readValueType="uint16",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Start_up_time                  [ readStart="32091", readValueType="uint32",readTransform="JS(divide1.js)",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Shutdown_time                  [ readStart="32093", readValueType="uint32",readTransform="JS(divide1.js)",updateUnchangedValuesEveryMillis="5000000" ]

    }

Bridge poller slave106holding [ start=32106, length=2, refresh=10000, type="holding" ]{
    
        Thing data E_total                       [ readStart="32106", readValueType="uint32",readTransform="JS(divide100.js)",updateUnchangedValuesEveryMillis="5000000" ]

    }

Bridge poller slave107holding [ start=32114, length=2, refresh=10000, type="holding" ]{            
        
        Thing data E_day                         [ readStart="32114", readValueType="uint32",readTransform="JS(divide100.js)",updateUnchangedValuesEveryMillis="5000000" ]  

    }

Bridge poller slave108holding [ start=40122, length=6, refresh=10000, type="holding" ]{
    
        Thing data Reactive_power_compensation_pf [ readStart="40122", readValueType="int16",readTransform="JS(divide1000.js)",updateUnchangedValuesEveryMillis="5000000" ]     
        Thing data Reactive_power_compensation_qs [ readStart="40123", readValueType="int16",readTransform="JS(divide1000.js)",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Active_power_derating_percent  [ readStart="40125", readValueType="uint16",readTransform="JS(divide10.js)",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data Active_power_derating_fixed    [ readStart="40126", readValueType="uint32",readTransform="JS(divide1.js)",updateUnchangedValuesEveryMillis="5000000" ]
    }


}
   

Inverter items modbus RTU
For modbus TCP you have to change slave100 to localhostTCP in the channel
I can not put it here because the the post is to big then i wil post it below all messages

Inverter.items

Group   gSolar "Solar data"
Group:Number:SUM   gSolalarmMinor  "Minor alarm [%d] "<error>
Group:Number:SUM   gSolalarmWarning "Warning [%d] "   <error>
Group:Number:SUM   gSolalarmMajor "Major alarm [%d] " <error>
Group:Number:SUM   gSolateleIndica  "Standelone tele indication [%d] " <settings>

Number  Rated_power                                                                                                         { channel="modbus:data:slave100:slave101holding:Rated_power:number" }
Number  Maximum_active_power                                                                                                { channel="modbus:data:slave100:slave101holding:Maximum_active_power:number" }
Number  Maximum_apparent_power                                                                                              { channel="modbus:data:slave100:slave101holding:Maximum_apparent_power:number" }
Number  Maximum_reactive_power_fed                                                                                          { channel="modbus:data:slave100:slave101holding:Maximum_reactive_power_fed:number" }
Number  Maximum_reactive_power_absorbed                                                                                     { channel="modbus:data:slave100:slave101holding:Maximum_reactive_power_absorbed:number" }

String  Standalone_tele_indication       "Tele indicatie  [%s]"                 
Number  Standalone_tele_indicationbit0   "Stand by"                                                       (gSolateleIndica) { channel="modbus:data:slave100:slave102holding:Standalone_tele_indicationbit0:number" }
Number  Standalone_tele_indicationbit1   "Grid connection"                                                (gSolateleIndica) { channel="modbus:data:slave100:slave102holding:Standalone_tele_indicationbit1:number" }
Number  Standalone_tele_indicationbit2   "Normal grid connection"                                         (gSolateleIndica) { channel="modbus:data:slave100:slave102holding:Standalone_tele_indicationbit2:number" }
Number  Standalone_tele_indicationbit3   "Grid connection with derating due to power rationing"           (gSolateleIndica) { channel="modbus:data:slave100:slave102holding:Standalone_tele_indicationbit3:number" }
Number  Standalone_tele_indicationbit4   "Grid connection with derating due to inverter internel causes"  (gSolateleIndica) { channel="modbus:data:slave100:slave102holding:Standalone_tele_indicationbit4:number" }
Number  Standalone_tele_indicationbit5   "Normal stop"                                                    (gSolateleIndica) { channel="modbus:data:slave100:slave102holding:Standalone_tele_indicationbit5:number" }
Number  Standalone_tele_indicationbit6   "Stop due to faults"                                             (gSolateleIndica) { channel="modbus:data:slave100:slave102holding:Standalone_tele_indicationbit6:number" }
Number  Standalone_tele_indicationbit7   "Stop due to power rationing"                                    (gSolateleIndica) { channel="modbus:data:slave100:slave102holding:Standalone_tele_indicationbit7:number" }
Number  Standalone_tele_indicationbit8   "Shutdown"                                                       (gSolateleIndica) { channel="modbus:data:slave100:slave102holding:Standalone_tele_indicationbit8:number" }
Number  Standalone_tele_indicationbit9   "Spot check"                                                     (gSolateleIndica) { channel="modbus:data:slave100:slave102holding:Standalone_tele_indicationbit9:number" }

Number  Unlocked              "Unlocked [MAP(0-1.map):%s]"   <settings>                                                     { channel="modbus:data:slave100:slave102aholding:Operating_statusbit0:number" }
Number  Pv_connection         "Pv connection [MAP(0-1.map):%s]"  <settings>                                                 { channel="modbus:data:slave100:slave102aholding:Operating_statusbit1:number" }
Number  Dsp_data_collection   "Dsp data collection [MAP(0-1.map):%s]"  <settings>                                           { channel="modbus:data:slave100:slave102aholding:Operating_statusbit2:number" }

Number  Alarm_1bit0            "High String Voltage 2001"                                                 (gSolalarmMajor)  { channel="modbus:data:slave100:slave103holding:Alarm_1bit0:number" }
Number  Alarm_1bit1            "DC Arc Fault 2002"                                                        (gSolalarmMajor)  { channel="modbus:data:slave100:slave103holding:Alarm_1bit1:number" }
Number  Alarm_1bit2            "String Reversed 2011"                                                     (gSolalarmMajor)  { channel="modbus:data:slave100:slave103holding:Alarm_1bit2:number" }
Number  Alarm_1bit3            "PV String Backfeed 2012"                                                  (gSolalarmWarning){ channel="modbus:data:slave100:slave103holding:Alarm_1bit3:number" }
Number  Alarm_1bit4            "Abnormal String 2013"                                                     (gSolalarmWarning){ channel="modbus:data:slave100:slave103holding:Alarm_1bit4:number" }
Number  Alarm_1bit5            "AFCI Self-test Fault 2021"                                                (gSolalarmMajor)  { channel="modbus:data:slave100:slave103holding:Alarm_1bit5:number" }
Number  Alarm_1bit6            "Short circuit between phase to PE 2031"                                   (gSolalarmMajor)  { channel="modbus:data:slave100:slave103holding:Alarm_1bit6:number" }
Number  Alarm_1bit7            "Power Grid Failure 2032"                                                  (gSolalarmMajor)  { channel="modbus:data:slave100:slave103holding:Alarm_1bit7:number" }
Number  Alarm_1bit8            "Grid Undervoltage 2033"                                                   (gSolalarmMajor)  { channel="modbus:data:slave100:slave103holding:Alarm_1bit8:number" }
Number  Alarm_1bit9            "Grid Overvoltage 2034"                                                    (gSolalarmMajor)  { channel="modbus:data:slave100:slave103holding:Alarm_1bit9:number" }
Number  Alarm_1bit10           "Unbalanced Grid Voltage 2035"                                             (gSolalarmMajor)  { channel="modbus:data:slave100:slave103holding:Alarm_1bit10:number" }
Number  Alarm_1bit11           "Grid Overfrequency 2036"                                                  (gSolalarmMajor)  { channel="modbus:data:slave100:slave103holding:Alarm_1bit11:number" }
Number  Alarm_1bit12           "Grid Underfrequency 2037"                                                 (gSolalarmMajor)  { channel="modbus:data:slave100:slave103holding:Alarm_1bit12:number" }
Number  Alarm_1bit13           "Grid Frequency Instability 2038"                                          (gSolalarmMajor)  { channel="modbus:data:slave100:slave103holding:Alarm_1bit13:number" }
Number  Alarm_1bit14           "Output Overcurrent 2039"                                                  (gSolalarmMajor)  { channel="modbus:data:slave100:slave103holding:Alarm_1bit14:number" }
Number  Alarm_1bit15           "Large DC of Output current 2040"                                          (gSolalarmMajor)  { channel="modbus:data:slave100:slave103holding:Alarm_1bit15:number" }


Number  Alarm_2bit0           "Abnormal Leakage Current 2051"                                             (gSolalarmMajor)   { channel="modbus:data:slave100:slave103aholding:Alarm_2bit0:number" }
Number  Alarm_2bit1           "Abnormal Ground 2061"                                                      (gSolalarmMajor)   { channel="modbus:data:slave100:slave103aholding:Alarm_2bit1:number" }
Number  Alarm_2bit2           "Low Insulation Res 2062"                                                   (gSolalarmMajor)   { channel="modbus:data:slave100:slave103aholding:Alarm_2bit2:number" }
Number  Alarm_2bit3           "High Temperature 2063"                                                     (gSolalarmMajor)   { channel="modbus:data:slave100:slave103aholding:Alarm_2bit3:number" }
Number  Alarm_2bit4           "Abnormal Equipment 2064"                                                   (gSolalarmMajor)   { channel="modbus:data:slave100:slave103aholding:Alarm_2bit4:number" }
Number  Alarm_2bit5           "Upgrade Failed 2065"                                                       (gSolalarmMinor)   { channel="modbus:data:slave100:slave103aholding:Alarm_2bit5:number" }
Number  Alarm_2bit6           "License Expired 2066"                                                      (gSolalarmWarning) { channel="modbus:data:slave100:slave103aholding:Alarm_2bit6:number" }
Number  Alarm_2bit7           "Abnormal Monitor Unit 61440"                                               (gSolalarmMinor)   { channel="modbus:data:slave100:slave103aholding:Alarm_2bit7:number" }
Number  Alarm_2bit8           "Power collector fault 2067"                                                (gSolalarmMajor)   { channel="modbus:data:slave100:slave103aholding:Alarm_2bit8:number" }
Number  Alarm_2bit9           "Abnormal energy storage device 2068"                                       (gSolalarmMinor)   { channel="modbus:data:slave100:slave103aholding:Alarm_2bit9:number" }
Number  Alarm_2bit10          "Active islanding 2070"                                                     (gSolalarmMajor)   { channel="modbus:data:slave100:slave103aholding:Alarm_2bit10:number" }
Number  Alarm_2bit11          "Passive islanding 2071"                                                    (gSolalarmMajor)   { channel="modbus:data:slave100:slave103aholding:Alarm_2bit11:number" }
Number  Alarm_2bit12          "Transient AC overvoltage 2072"                                             (gSolalarmMajor)   { channel="modbus:data:slave100:slave103aholding:Alarm_2bit12:number" }
//Number  Alarm_2bit13                                                                                                       { channel="modbus:data:slave100:slave103aholding:Alarm_2bit13:number" }
//Number  Alarm_2bit14                                                                                                       { channel="modbus:data:slave100:slave103aholding:Alarm_2bit14:number" }
Number  Alarm_2bit15          "Abnormal PV module configuration 2080"                                     (gSolalarmMajor)   { channel="modbus:data:slave100:slave103aholding:Alarm_2bit15:number" }


//Number  Alarm_3bit0                                                                                                        { channel="modbus:data:slave100:slave103bholding:Alarm_3bit0:number" }
//Number  Alarm_3bit1                                                                                                        { channel="modbus:data:slave100:slave103bholding:Alarm_3bit1:number" }
//Number  Alarm_3bit2                                                                                                        { channel="modbus:data:slave100:slave103bholding:Alarm_3bit2:number" }
//Number  Alarm_3bit3                                                                                                        { channel="modbus:data:slave100:slave103bholding:Alarm_3bit3:number" }
//Number  Alarm_3bit4                                                                                                        { channel="modbus:data:slave100:slave103bholding:Alarm_3bit4:number" }
//Number  Alarm_3bit5                                                                                                        { channel="modbus:data:slave100:slave103bholding:Alarm_3bit5:number" }
//Number  Alarm_3bit6                                                                                                        { channel="modbus:data:slave100:slave103bholding:Alarm_3bit6:number" }
//Number  Alarm_3bit7                                                                                                        { channel="modbus:data:slave100:slave103bholding:Alarm_3bit7:number" }
//Number  Alarm_3bit8                                                                                                        { channel="modbus:data:slave100:slave103bholding:Alarm_3bit8:number" }
//Number  Alarm_3bit9                                                                                                        { channel="modbus:data:slave100:slave103bholding:Alarm_3bit9:number" }
//Number  Alarm_3bit10                                                                                                       { channel="modbus:data:slave100:slave103bholding:Alarm_3bit10:number" }
//Number  Alarm_3bit11                                                                                                       { channel="modbus:data:slave100:slave103bholding:Alarm_3bit11:number" }
//Number  Alarm_3bit12                                                                                                       { channel="modbus:data:slave100:slave103bholding:Alarm_3bit12:number" }
//Number  Alarm_3bit13                                                                                                       { channel="modbus:data:slave100:slave103bholding:Alarm_3bit13:number" }
//Number  Alarm_3bit14                                                                                                       { channel="modbus:data:slave100:slave103bholding:Alarm_3bit14:number" }
//Number  Alarm_3bit15                                                                                                       { channel="modbus:data:slave100:slave103bholding:Alarm_3bit15:number" }

Number  Pv_1_Voltage        "Pv 1 voltage[%.1f V]"    <energy>                                         (gSolar)             { channel="modbus:data:slave100:slave104holding:Pv_1_Voltage:number" }
Number  Pv_1_Current        "Pv 1 stroom[%.2f A]"     <energy>                                         (gSolar)              { channel="modbus:data:slave100:slave104holding:Pv_1_Current:number" }
Number  Pv_2_Voltage        "Pv 2 voltage[%.1f V]"    <energy>                                         (gSolar)              { channel="modbus:data:slave100:slave104holding:Pv_2_Voltage:number" }
Number  Pv_2_Current        "Pv 2 stroom[%.2f A]"     <energy>                                         (gSolar)              { channel="modbus:data:slave100:slave104holding:Pv_2_Current:number" }
//Number  Pv_3_Voltage        "Pv 3 voltage[%.1f V]"                                                                         { channel="modbus:data:slave100:slave104holding:Pv_3_Voltage:number" }
//Number  Pv_3_Current        "Pv 3 stroom[%.2f A]"                                                                          { channel="modbus:data:slave100:slave104holding:Pv_3_Current:number" }
//Number  Pv_4_Voltage        "Pv 4 voltage[%.1f V]"                                                                         { channel="modbus:data:slave100:slave104holding:Pv_4_Voltage:number" }
//Number  Pv_4_Current        "Pv 4 stroom[%.2f A]"                                                                          { channel="modbus:data:slave100:slave104holding:Pv_4_Current:number" }

Number  Input_power                                                                                                          { channel="modbus:data:slave100:slave105holding:Input_power:number" }
Number  Uab                                                                                                                  { channel="modbus:data:slave100:slave105holding:Uab:number" }
Number  Ubc                                                                                                                  { channel="modbus:data:slave100:slave105holding:Ubc:number" }
Number  Uca                                                                                                                  { channel="modbus:data:slave100:slave105holding:Uca:number" }
Number  Ua                                                                                            (gSolar)               { channel="modbus:data:slave100:slave105holding:Ua:number" }
Number  Ub                                                                                            (gSolar)               { channel="modbus:data:slave100:slave105holding:Ub:number" }
Number  Uc                                                                                            (gSolar)               { channel="modbus:data:slave100:slave105holding:Uc:number" }
Number  La                                                                                                                   { channel="modbus:data:slave100:slave105holding:La:number" }
Number  Lc                                                                                                                   { channel="modbus:data:slave100:slave105holding:Lc:number" }
Number  Active_peak_of_current_day                                                                                           { channel="modbus:data:slave100:slave105holding:Active_peak_of_current_day:number" }
Number  Active_power         "Actieve power[%.2f Kw]"      <energy>                                (gSolar)               { channel="modbus:data:slave100:slave105holding:Active_power:number" }
Number  Reactive_power                                                                                                       { channel="modbus:data:slave100:slave105holding:Reactive_power:number" }
Number  Power_factor                                                                                                         { channel="modbus:data:slave100:slave105holding:Power_factor:number" }
Number  Frequency                                                                                                            { channel="modbus:data:slave100:slave105holding:Frequency:number" }
Number  Inverter_efficiency  "Efficientie omvormer[%.1f %%]" <settings>                               (gSolar)               { channel="modbus:data:slave100:slave105holding:Inverter_efficiency:number" }
Number  Cabinet_temperature  "Temperatuur omvormer[%.1f °C]"<temperature>                             (gSolar)               { channel="modbus:data:slave100:slave105holding:Cabinet_temperature:number" }
Number  Insulation_resistance                                                                                                { channel="modbus:data:slave100:slave105holding:Insulation_resistance:number" }
Number  Device_status    "Apparaat status[MAP(inverter_device_status.map):%s]" <settings>             (gSolar)               { channel="modbus:data:slave100:slave105holding:Device_status:number" }
Number  Fault_code            "Fault code[%d]"      <error>                                           (gSolar)               { channel="modbus:data:slave100:slave105holding:Fault_code:number" }
Number  Start_up_time                                                                                                        { channel="modbus:data:slave100:slave105holding:Start_up_time:number" }
Number  Shutdown_time                                                                                                        { channel="modbus:data:slave100:slave105holding:Shutdown_time:number" }

Number  E_total            "Totaal opgewekt[%.2f Kwh]"    <line>                                      (gSolar)               { channel="modbus:data:slave100:slave106holding:E_total:number" }

Number  E_day              "Dagelijks opgewekt[%.2f Kwh]" <line>                                      (gSolar)               { channel="modbus:data:slave100:slave107holding:E_day:number" }

Number  Reactive_power_compensation_pf                                                                                       { channel="modbus:data:slave100:slave108holding:Reactive_power_compensation_pf:number" }
Number  Reactive_power_compensation_qs                                                                                       { channel="modbus:data:slave100:slave108holding:Reactive_power_compensation_qs:number" }
Number  Active_power_derating_percent                                                                                        { channel="modbus:data:slave100:slave108holding:Active_power_derating_percent:number" }
Number  Active_power_derating_fixed                                                                                          { channel="modbus:data:slave100:slave108holding:Active_power_derating_fixed:number" }

And put this in the transform file

divide1.js

// Wrap everything in a function (no global variable pollution)
// variable "input" contains data passed by openHAB
(function(inputData) {
    // on read: the polled number as string
    // on write: openHAB command as string
    var DIVIDE_BY = 1;
    return parseFloat(inputData) / DIVIDE_BY;
})(input)

divide10.js

// Wrap everything in a function (no global variable pollution)
// variable "input" contains data passed by openHAB
(function(inputData) {
    // on read: the polled number as string
    // on write: openHAB command as string
    var DIVIDE_BY = 10;
    return parseFloat(inputData) / DIVIDE_BY;
})(input)

divide100.js

// Wrap everything in a function (no global variable pollution)
// variable "input" contains data passed by openHAB
(function(inputData) {
    // on read: the polled number as string
    // on write: openHAB command as string
    var DIVIDE_BY = 100;
    return parseFloat(inputData) / DIVIDE_BY;
})(input)

divide1000.js

// Wrap everything in a function (no global variable pollution)
// variable "input" contains data passed by openHAB
(function(inputData) {
    // on read: the polled number as string
    // on write: openHAB command as string
    var DIVIDE_BY = 1000;
    return parseFloat(inputData) / DIVIDE_BY;
})(input)

inverter_device_status.map

0=Initializing
1=Detecting ISO
2=Detecting irradiation
3=Grid detecting
256=Starting
512=On grid
513=On grid Power limit
514=On grid self derating
768=Shutdown fault
769=Shutdown command
770=Shutdown OVGR
771=Shutdown communication disconnected
772=Shutdown power limit
773=Shutdown start manually
774=Shutdown DC switch OFF
1025=Grid dispatch cos(Phi)-P curve
1026=Grid dispatch Q-U curve
40960=No irradiation
1280=Spot-check
1281=Spot-checking
1536=Inspecting
1792=AFCI self-check
2048=I V scanning
2304=DC input detection 

I made a sitemap with some info

.sitemap

Frame label="Inverter" {
        Text item=Pv_1_Voltage 
        Text item=Pv_1_Current
        Text item=Pv_2_Voltage
        Text item=Active_power
        Text item=Pv_2_Current
        Text item=Inverter_efficiency
        Text item=Cabinet_temperature
        Text item=Device_status
        Text item=Unlocked
        Text item=Pv_connection 
        Text item=Dsp_data_collection
        Text item=E_total
        Text item=E_day
        Text item=Fault_code 
        Group item=gSolateleIndica
        Group item=gSolalarmWarning
        Group item=gSolalarmMinor
        Group item=gSolalarmMajor
        
}					

And if you use habpanel matrix theme

Zonne energie.widget.json (5.3 KB)

4 Likes

Have you also tried Modbus over TCP?

Hello Emilv2,

Welkom to the Community.
As far as i know it only works with modbus RTU.
I could not find anything in the docs about TCP.

Can you specify what type you used mine with at max485 chip does not react at all?
What do you mean by ‘remove the wlan smart dongle’, mine just got an antenna.
Can you suggest me a program to verify the serial 485 connection setup?

Hello,

I use this cable https://www.ftdichip.com/Support/Documents/DataSheets/Cables/DS_USB_RS485_CABLES.pdf
What type of inverter do you have?
At the bottom there is a wlan smart dongle. This is not just an antenna.
You have to remove this.
I dont now any program to test the serial connection;
When the plug of the usb converter flashes red en green you have a good connection.
Make sure you have set the right usb port in the config.
Wat platform do you run openhab on?
Every time you make a changes in the modbus config you have to restart openhab service.
Do you have any error logs?

Must say I did not take out the wlan antenna, it might be the reason for no reaction?
Just noticed you are talking about the 2000 version (not the 2000L like I have) page 3 item 13?

Ordered one like this on the cheap but got no respons at all from it.
Do you remember where you got it from? Could not find anything in the stores nearby…

For testing I found this program Modbus poll, this should work, I believe, to get some test talking with the unit.
Tested on 2.4.2 on WIN10, but got a RPI3 for the daily jobs :slight_smile:
Logs only show lots of no respons, binding does come online.

I have just looked to the modbus definitions of the 2000l series and most are the same. So it should work.We can adjust the parameters that are different.
I bought my converter cable here https://www.acculaders.nl/rs485-naar-usb-interface-kabel-1-8m.html?utm_source=daisycon&utm_medium=affiliate&utm_campaign=daisycon_Shopforward.be%20(NL/FR)
But i think yours should work to it uses the fdti chip.
It is very important that you remove the wlan antenna.
If you are convinced you are using the right usb port and the wiring is right.
Try tot restart the openhab service and take the power of the inverter and let it restart.
You also need sunlight if the inverter is in stanby because there is no sunlight, it does not send out anything.

That might be a very critical point; efforts were in the evening hours and converter was at the time in standby mode.
Next weekend will have plenty of opportunities and I borrowed a second/different cable to complete the tests.
Will keep you posted.
Thanks for your effort about the implementation of the modbus readings!

No luck, so far yet.
Got the online (almost) realtime info on huawei portal - in the cloud from my installer but prefer a offline, local storage.

The device seems to be prefering the wlan connection instead of talking over the rs485.
Tried the modbus over tcp but no succes either. I am not willing to give up the portal (yet).

They kindly installed an extra Landis & Gyr E350, that talks ODIS over IR. Got some (other) values to start with…

1 Like

You have to remove the wlan and reboot the inverter.
I could not make it work with the wlan antenna.
I am sending no data to the huawei portal.

Excellent news (in these dark corona days): it works!
The SUN2000L is slightly different form its predecessor:

  • COM-pinout connector = pin 1 - & pin 2 + (not pin3 as I did all my previous tests without result)
  • WLAN can stay active together with RS485, working both at the same time
  • offline “No irradiation” does not cut off the communication
  • hotplugable COM-port, no restart needed

With my test setup, seen frequent ‘Try 1 out of 3 failed when executing request’. 2nd retry often is enough to obtain the data. Even after extending all settings to ‘refresh=10000’ kept me seeing this messages. Any idea, suggestion?

1 Like

Nice.
I just looked at my manual and the pin out is really different then.
Because pin 1 and 2 would not work with my inverter.
Offline "no irradiation"does not cut off all communication you can only see E-total,E-day ,warnings and alarms.
do you use an exact copy of my things file?(if not show me your things file)
I still think the WLAN causes your problem.(mine runs super stable without errors)

I have never done a lot of tests with the WLAN module(it was allways causing issues) because I prefer to keep everything local. If I have some time tomorrow I will test some more with the WLAN module plugged in to see what happens and if it is causing your problem.

I know your inverter modbus definitions are a little bit different I will send you my modbus definitions so you can compare with yoursSUN2000-3-10KTL-M0 MODBUS Interface Definitions.pdf (461.5 KB)

You can also find your inverter modbus definitions on the internet or ask your installer.

Just did a quick first test with exact your things and items, even used the sitemap.

Downloaded, printed a hard copy; will compare them tomorrow with ‘Solar Inverter Modbus Interface Definitions (V3.0)’

For this huge data amount, what type of ‘Persistence’ do you use/advise?

Take care with your physical RS485 wiring. Twisted pair, avoid running alongside power cables, ensure good termination. Most USB dongles include one terminator which willoften “do”, but consider another if the cable is over a couple of metres and the other end is unterminated.

Show complete error messages for more help.

For persistence en graphing i use grafana and influxdb.
you can make nice graphs with grafana.
i followed this tutorial InfluxDB+Grafana persistence and graphing
It is not a huge amount of data i reinstalled openhab 6 months ago and this is the volume of data for all my items i persist.

81M	/var/lib/influxdb/data/openhab_db

I am only persisting the gSolar group in the inverter items file.
This is my influxdb.persist

Strategies { 

    everyHour : "0 0 * * * ?"
    everyDay  : "0 0 0 * * ?"
    everyMinute : "0 * * * * ?"

     // if no strategy is specified for an item entry below, the default list will be used
    default = everyMinute
}

/* 
 * Each line in this section defines for which item(s) which strategy(ies) should be applied.
 * You can list single items, use "*" for all items or "groupitem*" for all members of a group
 * item (excl. the group item itself).
 */
Items { 
    
     Heatpump * : strategy = everyMinute,restoreOnStartup
     gShelly * ,gSolar *,gHeatpump * ,gSystem * : strategy = everyChange,restoreOnStartup,everyMinute
     Sun_Azimuth *                   : strategy = everyHour
     gVerlichting * ,ComfoAir * ,  gIrrigation * ,gIrrigation_Times *  ,gVac * ,gVacStat * ,gVacCons * , gVacHist * ,gVerlichtingsinput * : strategy = restoreOnStartup 
     }
                    

I just plugged in the WLAN module and then I get this error

2020-03-21 10:29:28.630 [ERROR] [t.wimpi.modbus.io.ModbusRTUTransport] - Last request: 64 03 7d 10 00 08 54 50

2020-03-21 10:29:28.630 [ERROR] [t.wimpi.modbus.io.ModbusRTUTransport] - failed to read: CRC Error in received frame: 0 bytes: 

2020-03-21 10:29:28.631 [ERROR] [pi.modbus.io.ModbusSerialTransaction] - execute try 1/1 error: I/O exception: IOException CRC Error in received frame: 0 bytes: . Request: net.wimpi.modbus.msg.ReadMultipleRegistersRequest@629267 (unit id 100 & transaction 53715). Serial parameters: SerialParameters@160024f[portName=/dev/ttyUSB-RS485,baudRate=9600,flowControlIn=none,flowControlOut=none,databits=8,stopbits=1,parity=none,encoding=rtu,echo=false,receiveTimeoutMillis=1500]

2020-03-21 10:29:28.632 [ERROR] [pi.modbus.io.ModbusSerialTransaction] - execute reached max tries 1, throwing last error: I/O exception: IOException CRC Error in received frame: 0 bytes: . Request: net.wimpi.modbus.msg.ReadMultipleRegistersRequest@629267 (unit id 100 & transaction 53715). Serial parameters: SerialParameters@160024f[portName=/dev/ttyUSB-RS485,baudRate=9600,flowControlIn=none,flowControlOut=none,databits=8,stopbits=1,parity=none,encoding=rtu,echo=false,receiveTimeoutMillis=1500]

2020-03-21 10:29:28.633 [WARN ] [rt.modbus.internal.ModbusManagerImpl] - Try 1 out of 3 failed when executing request (ModbusPollerThingHandlerImpl.ModbusPollerReadRequest@9d07f5[slaveId=100,functionCode=READ_MULTIPLE_REGISTERS,start=32016,length=8,maxTries=3]). Will try again soon. Error was I/O error, so reseting the connection. Error details: net.wimpi.modbus.ModbusIOException I/O exception: IOException CRC Error in received frame: 0 bytes:  [operation ID 44e1ad62-0077-4927-bebc-f893b60b2d98]


I think this explains your error.

Exactly the same, thanks for testing!
Choices I have to make or take the downside of it.

I just plugged the WLAN module out and the error remains.
I had to take the power of the inverter and let it reboot to get everything back to normal.
I just read the quick guide and it said if the smart dongle(WLAN module) is configured you are advised to install the smart dongle before connecting the signal cable.
Maybe you can give that a try?
But why do you want to use the smart dongle you can have the same fuctions in openhab?

Checked both register definitions versions one by one, all appear to be equal.

Did some another test; see the screenshot below; left my WLAN active and connected to RS485 over usb and pulled all the meaningfull holding registers with a scan rate of 1000ms. A significant larger datastream without any errors over an interval of 10 minutes (Modbus Poll limit unregistered - used setting files available on request).

My installer is supervising his installations for errors as a free service, on the Huawei platform.

My idea on the dropped answer issue: I suspect that the openhab modbus binding is connecting/disconnecting after each poll. On reconnect, there might by a (longer) wait time (penalty) when the WLAN is active.
Can the poller things be configured to keep the COM port open, once connected?

Why would you think that would matter? Modbus is a master-slave protocol. The slave has no idea when it is going to be queried, until it is queried. However long it takes the master to prepare to query is immaterial.
It might make a difference to slave response time, if it has to handle extra tasks too on WLAN.

CRC errors are a pretty reliable indicator of crap on the serial line. Have you considered that the WLAN may contribute to RF interference, or noise via the RS485 interface’s power feed?

Earth loop and termination issues can create time-based weirdness, where a busy line can run error free, while transmission silences allow errors to appear.