This is the script. Only the connection to OpenHAB is my work, the rest is taken from Graham Whiteside to whom most of the credit is due.
Different series of inverters place the results in different places in the string so a bit of fiddling around might be required.
#!/usr/bin/python
###################################################################################################
#
# Copyright 2015 Graham Whiteside, Manchester, UK. Version 0.3 Oct 2015.
#
# Script modified by Barny Daley to suit Solis 3G and post outputs to OpenHAB items using REST API
#
# read-ginlong is free software: you can redistribute it and/or modify it under the terms of the
# GNU General Public License as published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# read-ginlong is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You can browse the GNU license here: <http://www.gnu.org/licenses/>.
#
###################################################################################################
###################################################################################################
#
# Python program to read data sent from a single Ginlong/Solis 2G inverter equipped with a
# Wi-Fi 'stick'.
#
# Requires setting up the inverter stick to send data to the computer running the read-ginlong
# script. Settings located in the advanced settings, then remote server. Add a new 'remote
# server' with the ip address of your computer and port 9999. The inverter will send data every
# five minutes.
#
# Output file format (space separated):-
# Date Time Watts_now Day_kWh Total_kWh
#
# Output of webserver file, format (space separated) file overwritten each update:-
# Date Time Watts_now Day_kWh Total_kWh DC_volts_1 DC_amps_1 DC_volts_2 DC_amps_2 AC_volts AC_amps AC_freq kwh_yesterday kwh_month kwh_last_month
#
# The read-ginlong.py program is deliberately left simple without error reporting. It is intended
# as a 'starting point' and proof of concept. It could easily be modified to provide more
# information from the inverter. Furthermore the output log file can be further processed or
# loaded into other software such as LibreOffice Calc.
#
###################################################################################################
import socket, binascii, time, requests
# import urllib2
# print "Import complete"
# change these values to suit your requirements:-
HOST = '' # Hostname or ip address of interface, leave blank for all
PORT = 9999 # listening on port 9999
logfile = 'ginlong.log' # location of output log file
webfile = 'ginlong.status' # location of web file
# inverter values found (so far) all big endian 16 bit unsigned:-
header = '685951b0' # hex stream header
data_size = 206 # hex stream size
inverter_temp = 31 # offset 31 & 32 temperature (/10)
inverter_vdc1 = 33 # offset 33 & 34 DC volts chain 1 (/10)
inverter_adc1 = 39 # offset 39 & 40 DC amps chain 1 (/10)
inverter_aac = 45 # offset 45 & 46 AC output amps (/10)
inverter_vac = 51 # offset 51 & 52 AC output volts (/10)
inverter_freq = 57 # offset 57 & 58 AC frequency (/100)
inverter_now = 59 # offset 59 & 60 currant generation Watts
inverter_yes = 67 # offset 67 & 68 yesterday kwh (/100)
inverter_day = 69 # offset 69 & 70 daily kWh (/100)
inverter_tot = 73 # offset 73 & 74 total kWh
inverter_mth = 87 # offset 87 & 88 total kWh for month
inverter_lmth = 91 # offset 91 & 92 total kWh for last month
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # create socket on required port
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((HOST, PORT))
print "Socket bound"
while True: # loop forever
sock.listen(1) # listen on port
conn, addr = sock.accept() # wait for inverter connection
rawdata = conn.recv(1000) # read incoming data
hexdata = binascii.hexlify(rawdata) # convert data to hex
print(hexdata)
if(hexdata[0:8] == header and len(hexdata) == data_size): # check for valid data
# extract main values and convert to decimal
watt_now = str(int(hexdata[inverter_now*2:inverter_now*2+4],16)) # generating power in watts
kwh_day = str(float(int(hexdata[inverter_day*2:inverter_day*2+4],16))/100) # running total kwh for day
kwh_total = str(float(int(hexdata[inverter_tot*2:inverter_tot*2+4],16))/2) # running total kwh from installation
temp = str(float(int(hexdata[inverter_temp*2:inverter_temp*2+4],16))/10) # temperature # extract dc input values and convert to decimal
dc_volts1= str(float(int(hexdata[inverter_vdc1*2:inverter_vdc1*2+4],16))/10) # input dc volts from chain 1
dc_amps1 = str(float(int(hexdata[inverter_adc1*2:inverter_adc1*2+4],16))/10) # input dc amps from chain 1
# extract other ac values and convert to decimal
ac_volts = str(float(int(hexdata[inverter_vac*2:inverter_vac*2+4],16))/10) # output ac volts
ac_amps = str(float(int(hexdata[inverter_aac*2:inverter_aac*2+4],16))/10) # output ac amps
ac_freq = str(float(int(hexdata[inverter_freq*2:inverter_freq*2+4],16))/100) # output ac frequency hertz
# extract other historical values and convert to decimal
kwh_yesterday = str(float(int(hexdata[inverter_yes*2:inverter_yes*2+4],16))/100) # yesterday's kwh
kwh_month = str(int(hexdata[inverter_mth*2:inverter_mth*2+4],16)) # running total kwh for month
kwh_lastmonth = str(int(hexdata[inverter_lmth*2:inverter_lmth*2+4],16)) # running total kwh for last month
timestamp = (time.strftime("%F %H:%M")) # get date time
log = open(logfile,'a') # write data to logfile, main values only
log.write(timestamp + ' ' + watt_now + ' ' + kwh_day + ' ' + kwh_total + '\n')
log.close()
web = open(webfile,'w') # output all values, possibly for webpage
web.write(timestamp + ' ' + watt_now + ' ' + kwh_day + ' ' + kwh_total + ' ' + dc_volts1 + ' ' + dc_amps1 + ' ' + ac_volts + ' ' + ac_amps + ' ' + ac_freq + ' ' + kwh_yesterday + ' ' + kwh_month + ' ' + kwh_lastmonth + ' ' + temp + '\n')
web.close()
urlbase = "http://openhabian:8080/rest/items/"
# print (watt_now)
url = urlbase + "Solar_watt_now" + "/state"
requests.put(url, str(watt_now))
# print (kwh_day)
url = urlbase + "Solar_kwh_day" + "/state"
requests.put(url, str(kwh_day))
url = urlbase + "Solar_kwh_total" + "/state"
requests.put(url, str(kwh_total))
url = urlbase + "Solar_dc_volts" + "/state"
requests.put(url, str(dc_volts1))
url = urlbase + "Solar_dc_amps" + "/state"
requests.put(url, str(dc_amps1))
url = urlbase + "Solar_ac_volts" + "/state"
requests.put(url, str(ac_volts))
url = urlbase + "Solar_ac_amps" + "/state"
requests.put(url, str(ac_amps))
url = urlbase + "Solar_ac_freq" + "/state"
requests.put(url, str(ac_freq))
# print (temp)
url = urlbase + "Solar_temp" + "/state"
requests.put(url, str(temp))
conn.close()
These are the accompanying OpenHAB items:
Number Solar_watt_now "Current solar generation [%.0f W]" (Solar)
Number Solar_kwh_day "Solar generated energy today [%.1f kWh]" (Solar)
Number Solar_kwh_total "Solar generated energy [%.0f kWh]" (Solar)
Number Solar_dc_volts "Solar array DC [%.1f V]" (Solar)
Number Solar_dc_amps "Solar array DC [%.1f A]" (Solar)
Number Solar_ac_volts "Solar AC [%.1f V]" (Solar)
Number Solar_ac_amps "Solar AC [%.1f A]" (Solar)
Number Solar_ac_freq "Solar AC [%.1f Hz]" (Solar)
Number Solar_temp "Temperature at solar inverter [%.1f °C]" (Solar)