Python Plugin: Growatt Solar Inverter via USB RS232 or RS485 Modbus

Python and python framework

Moderator: leecollings

Post Reply
jeroenst
Posts: 25
Joined: Sunday 18 June 2017 7:28
Target OS: Linux
Domoticz version: V3.7976
Location: Netherlands
Contact:

Python Plugin: Growatt Solar Inverter via USB RS232 or RS485 Modbus

Post by jeroenst »

This is the first code for the Growatt plugin.

I don't have a Growatt inverter at this moment, can someone test it?

It uses the modbus port of the Growatt converter, get a modbus interface from ebay ( http://www.ebay.com/sch/i.html?_odkw=us ... 5&_sacat=0 ) or somewhere else...

It runs on Ubuntu 17.04 after I did include the right paths with sys.path.append

Known bugs:
1. When adding the hardware device there are 2 Serial Port fields. This is possible a bug in Domoticz because in the plugin only 1 field is defined
2. The icons of power and frequency don't match electric power, there is no Watt and Frequency available in TypeName of Domoticz

Code: Select all

# Growatt Python Plugin for Domoticz
#
# Author: jst
#
# Install modbus library: https://pypi.python.org/pypi/MinimalModbus
#
"""
<plugin key="Growatt" name="Growatt Solar Inverter via RS485" author="jst" version="1.0.0">
    <params>
        <param field="SerialPort" label="Serial Port" width="150px" required="true"/>
        <param field="Mode6" label="Debug" width="75px">
            <options>
                <option label="True" value="Debug"/>
                <option label="False" value="Normal" default="true"/>
            </options>
        </param>
    </params>
</plugin>
"""

import sys
sys.path.append('/usr/local/lib/python3.5/dist-packages/')
sys.path.append('/usr/local/lib/python3.5/dist-packages/pyserial-3.3-py3.5.egg')

import minimalmodbus
try:
    import Domoticz
except ImportError:
    import fakeDomoticz as Domoticz


class BasePlugin:
    enabled = False
    def __init__(self):
        return

    def onStart(self):
       Domoticz.Log("onStart called")
       if (len(Devices) == 0):
         Domoticz.Device("pv watt", 1, "Custom", Options = { "Custom" : "1;W"}).Create()
         Domoticz.Device("pv voltage", 2, "Voltage").Create()
         Domoticz.Device("pv current", 3, "Current (Single)").Create()
         Domoticz.Device("grid watt", 4, "Custom", Options = { "Custom" : "1;W"}).Create()
         Domoticz.Device("grid voltage", 5, "Voltage").Create()
         Domoticz.Device("grid current", 6, "Current (Single)").Create()
         Domoticz.Device("grid frequency", 7, "Custom", Options = { "Custom" : "1;Hz"}).Create()
         Domoticz.Device("kwh today", 8, "Custom", Options = { "Custom" : "1;kWh"}).Create()
         Domoticz.Device("kwh total", 9, "Custom", Options = { "Custom" : "1;kWh"}).Create()
       DumpConfigToLog()
       Domoticz.Log("Plugin is started.")
       Domoticz.Heartbeat(20)

    def onStop(self):
        Domoticz.Log("onStop called")

    def onConnect(self, Connection, Status, Description):
        Domoticz.Log("onConnect called")

    def onMessage(self, Connection, Data, Status, Extra):
        Domoticz.Log("onMessage called")

    def onCommand(self, Unit, Command, Level, Hue):
        Domoticz.Log("onCommand called for Unit " + str(Unit) + ": Parameter '" + str(Command) + "', Level: " + str(Level))

    def onNotification(self, Name, Subject, Text, Status, Priority, Sound, ImageFile):
        Domoticz.Log("Notification: " + Name + "," + Subject + "," + Text + "," + Status + "," + str(Priority) + "," + Sound + "," + ImageFile)

    def onDisconnect(self, Connection):
        Domoticz.Log("onDisconnect called")

    def onHeartbeat(self):
        #Domoticz.Log("onHeartbeat called")
        ## Read Growatt Inverter ##
        try:
          instrument = minimalmodbus.Instrument(Parameters["SerialPort"], 1) # port name, slave address (in decimal)
        except:
          Domoticz.Log("Error openining USB Modbus connection to growatt inverter on "+Parameters["SerialPort"])
        else:
          try:
            instrument.serial.baudrate = 9600
            growatt_pv_watt = ((instrument.read_register(1) << 16) + instrument.read_register(2))/10
            growatt_pv_volt = instrument.read_register(int(3))/10
            growatt_pv_amp = instrument.read_register(4)/10
            growatt_grid_watt = ((instrument.read_register(11) << 16) + instrument.read_register(12))/10
            growatt_grid_freq = instrument.read_register(13)/100
            growatt_grid_volt = instrument.read_register(14)/10
            growatt_grid_amp = instrument.read_register(15)/10
            growatt_kwh_today = ((instrument.read_register(26) << 16) + instrument.read_register(27))/10
            growatt_kwh_total = ((instrument.read_register(28) << 16) + instrument.read_register(29))/10

            Devices[1].Update(growatt_pv_watt, growatt_pv_watt.replace('.',''))
            Devices[2].Update(growatt_pv_volt, growatt_pv_volt.replace('.',''))
            Devices[3].Update(growatt_pv_amp, growatt_pv_amp.replace('.',''))
            Devices[4].Update(growatt_grid_watt, growatt_grid_watt.replace('.',''))
            Devices[5].Update(growatt_grid_volt, growatt_grid_volt.replace('.',''))
            Devices[6].Update(growatt_grid_amp, growatt_grid_amp.replace('.',''))
            Devices[7].Update(growatt_grid_freq, growatt_grid_freq.replace('.',''))
            Devices[8].Update(growatt_kwh_today, growatt_kwh_today.replace('.',''))
            Devices[9].Update(growatt_kwh_total, growatt_kwh_total.replace('.',''))
            instrument.close()
          except:
            Domoticz.Log("Error reading growatt inverter on "+Parameters["SerialPort"])

global _plugin
_plugin = BasePlugin()

def onStart():
    global _plugin
    _plugin.onStart()

def onStop():
    global _plugin
    _plugin.onStop()

def onConnect(Connection, Status, Description):
    global _plugin
    _plugin.onConnect(Connection, Status, Description)

def onMessage(Connection, Data, Status, Extra):
    global _plugin
    _plugin.onMessage(Connection, Data, Status, Extra)

def onCommand(Unit, Command, Level, Hue):
    global _plugin
    _plugin.onCommand(Unit, Command, Level, Hue)

def onNotification(Name, Subject, Text, Status, Priority, Sound, ImageFile):
    global _plugin
    _plugin.onNotification(Name, Subject, Text, Status, Priority, Sound, ImageFile)

def onDisconnect(Connection):
    global _plugin
    _plugin.onDisconnect(Connection)

def onHeartbeat():
    global _plugin
    _plugin.onHeartbeat()

    # Generic helper functions
def DumpConfigToLog():
    for x in Parameters:
        if Parameters[x] != "":
            Domoticz.Debug( "'" + x + "':'" + str(Parameters[x]) + "'")
    Domoticz.Debug("Device count: " + str(len(Devices)))
    for x in Devices:
        Domoticz.Debug("Device:           " + str(x) + " - " + str(Devices[x]))
        Domoticz.Debug("Device ID:       '" + str(Devices[x].ID) + "'")
        Domoticz.Debug("Device Name:     '" + Devices[x].Name + "'")
        Domoticz.Debug("Device nValue:    " + str(Devices[x].nValue))
        Domoticz.Debug("Device sValue:   '" + Devices[x].sValue + "'")
        Domoticz.Debug("Device LastLevel: " + str(Devices[x].LastLevel))
    return
Last edited by jeroenst on Wednesday 21 June 2017 16:26, edited 5 times in total.
devros
Posts: 183
Joined: Saturday 29 October 2016 20:55
Target OS: -
Domoticz version:
Contact:

Re: Python Plugin: Growatt Solar Inverter via USB Modbus

Post by devros »

hello, i have something similar
solar inverter (http://www.ebay.com/itm/2000W-Solar-on- ... F5Ow8R3kEw) with wifi-plug-usb (conected to this portal http://www.shinemonitor.com/main.html) figured out that wifi plug is conected to this page using modbus protocol.
In Wifi plug admin page i can specify own server with port.
Any idea how to modify this script to support TCP/modbus comunication ?
User avatar
Dnpwwo
Posts: 820
Joined: Sunday 23 March 2014 9:00
Target OS: Raspberry Pi / ODroid
Domoticz version: Beta
Location: Melbourne, Australia
Contact:

Re: Python Plugin: Growatt Solar Inverter via USB Modbus

Post by Dnpwwo »

@jeroenst,

The double serial port field is probably caused by a 'feature' of the Domoticz hardware page.

Prior to the Python plugin framework all hardware support was effectively hardcoded from a parameter point of view, this was heavily influenced by the name of the hardware. I suspect that by having the word "USB" in the name the Hardware page has assumed you want it to show the Serial Port field.

Try renaming it to see if the extra field goes away.
The reasonable man adapts himself to the world; the unreasonable one persists to adapt the world to himself. Therefore all progress depends on the unreasonable man. George Bernard Shaw
jeroenst
Posts: 25
Joined: Sunday 18 June 2017 7:28
Target OS: Linux
Domoticz version: V3.7976
Location: Netherlands
Contact:

Re: Python Plugin: Growatt Solar Inverter via USB Modbus

Post by jeroenst »

Dnpwwo wrote:@jeroenst,
Try renaming it to see if the extra field goes away.
You're right, I renamed it and the extra field is gone. Shouldn't this be changed in Domoticz?
jeroenst
Posts: 25
Joined: Sunday 18 June 2017 7:28
Target OS: Linux
Domoticz version: V3.7976
Location: Netherlands
Contact:

Re: Python Plugin: Growatt Solar Inverter via USB Modbus

Post by jeroenst »

devros wrote:hello, i have something similar
solar inverter (http://www.ebay.com/itm/2000W-Solar-on- ... F5Ow8R3kEw) with wifi-plug-usb (conected to this portal http://www.shinemonitor.com/main.html) figured out that wifi plug is conected to this page using modbus protocol.
In Wifi plug admin page i can specify own server with port.
Any idea how to modify this script to support TCP/modbus comunication ?
I think you have to create a whole new module for this with a TCP server socket and a piece of code that decodes the parameters received.

If you can receive the data using netcat and specify the values received I'm willing to write a module for you.
devros
Posts: 183
Joined: Saturday 29 October 2016 20:55
Target OS: -
Domoticz version:
Contact:

Re: Python Plugin: Growatt Solar Inverter via USB Modbus

Post by devros »

jeroenst wrote:
devros wrote:hello, i have something similar
solar inverter (http://www.ebay.com/itm/2000W-Solar-on- ... F5Ow8R3kEw) with wifi-plug-usb (conected to this portal http://www.shinemonitor.com/main.html) figured out that wifi plug is conected to this page using modbus protocol.
In Wifi plug admin page i can specify own server with port.
Any idea how to modify this script to support TCP/modbus comunication ?
I think you have to create a whole new module for this with a TCP server socket and a piece of code that decodes the parameters received.

If you can receive the data using netcat and specify the values received I'm willing to write a module for you.
Great i will try to grab data, so far i was able to extract JSON file from shinemonitor. Any link with tutorial how to do this ?
jeroenst
Posts: 25
Joined: Sunday 18 June 2017 7:28
Target OS: Linux
Domoticz version: V3.7976
Location: Netherlands
Contact:

Re: Python Plugin: Growatt Solar Inverter via USB RS485 Modbus

Post by jeroenst »

@devros

ncat -e /bin/cat -k -t -l <portnumber>
devros
Posts: 183
Joined: Saturday 29 October 2016 20:55
Target OS: -
Domoticz version:
Contact:

Re: Python Plugin: Growatt Solar Inverter via USB RS485 Modbus

Post by devros »

jeroenst wrote:@devros

ncat -e /bin/cat -k -t -l <portnumber>
thanks, but how to specify WIFI-PLUG IP adress (im scaning from another computer)?, also im not sure about used port on that machine (tried nmap but only 80 is open (http)). Log on webpage shinemonitor.com is log updated every 5 minutes so maybe is port opened only at sending time.
jeroenst
Posts: 25
Joined: Sunday 18 June 2017 7:28
Target OS: Linux
Domoticz version: V3.7976
Location: Netherlands
Contact:

Re: Python Plugin: Growatt Solar Inverter via USB RS485 Modbus

Post by jeroenst »

Specify the adres and port ncat is listening on in de admin webpage of the wifiplug but if if you want to continue use of shinemonitor grabbing the json file is a better idea.
devros
Posts: 183
Joined: Saturday 29 October 2016 20:55
Target OS: -
Domoticz version:
Contact:

Re: Python Plugin: Growatt Solar Inverter via USB RS485 Modbus

Post by devros »

jeroenst wrote:Specify the adres and port ncat is listening on in de admin webpage of the wifiplug but if if you want to continue use of shinemonitor grabbing the json file is a better idea.
Finally I understand (ncat open specific port and save log) :), I'll try it when I'm home and post results later
in admin webpage i can specify 3 IP addresses with ports, so it should work fine together :)
it looks like wifiplug is sending
today energy(kWh)
total energy(kWh)
grid voltage AB(V)
actual output power(W)
DC voltage 1(V)
jeroenst
Posts: 25
Joined: Sunday 18 June 2017 7:28
Target OS: Linux
Domoticz version: V3.7976
Location: Netherlands
Contact:

Re: Python Plugin: Growatt Solar Inverter via USB RS485 Modbus

Post by jeroenst »

Post Reply

Who is online

Users browsing this forum: Bing [Bot] and 1 guest