Page 9 of 12
Re: Ginlong, Omnik Solar, Solarman and Trannergy Inverters
Posted: Thursday 02 May 2019 23:14
by sincze
Can you try
Netcat will listen for a connection on port 10000, redirect anything received to log.txt.
In the ginlock direct all traffic to IP of your raspberry and port 10000
The file will fill up for you

around every 5 minutes an entry. If you want you can parse the file to retrieve your values. However they are encoded I would say.
Re: Ginlong, Omnik Solar, Solarman and Trannergy Inverters
Posted: Friday 03 May 2019 9:14
by Toulon7559
@sincze
Your latest hints directed me to a python script which should perform the processing function at the receiving side in Server_B, including dissect and conversion to 'workable' file-formats.
[Left out the scriptlines for direct upload to PVOutput, because not yet required]
The Ginlong inverter and Server_B are in the same IP-range on a common LAN.
Setting of Ginlong Setup for Server_B to port 9999 and to the IP-address of the receiving server and to required protocol.
When testrunning the script from Putty's CLI, Server_B reports that it starts and listens, connects to the inverter (in my case at IP=192.168.0.112), and then waits , waits, waits ........
Code: Select all
Start Ginlong inverter WiFi/LAN-poller script
9999
Socket now listening
Connected with 192.168.0.112:54296
Makes no difference which protocol has been set in the Inverter Setup for Server_B.
The Ginlong Inverter reports that it has pingable interface to Server_B
What could be wrong/missing in the script and/or at the interface?
Code: Select all
#!/usr/bin/python3
# Line 02
# Version 00, as adapted from 2018-material from Tweakers Forum by Toulon7559 20190128
###################################################################################################
#
# Copyright 2018
# The source script was derived from script read_ginlong.py by Graham Whiteside, v0.3 Oct 2015.
# Further developed from the source script from Tweakers-Forum dating from 2016.
# This 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.
#
# This software 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/>.
#
###################################################################################################
# Line 20
###################################################################################################
#
# Python program to read data sent from a single Ginlong/Solis xK-2G and 4G inverters
# equipped with Wifi or cabled LAN-interface
# Requires setting up the inverter Wifi/LAN to send data to the computer running the read-ginlong script.
# Settings located in the advanced settings, then remote Server_B.
# Add a new 'remote server B' with the ip address of your computer and port 9999 and restart.
# The inverter will then send data over Wifi/LAN every five minutes.
#
# Output logfile format (space separated):-
# Date Time Watts_now Day_kWh Total_kWh
#
# Output of status to 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
#
# Output of live status to PVoutput.org site.
# Requires a PV output account and the API access enabled.
# Apikey and System ID from PV output need to be filled in the script !!!
#
# The 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.
#
###################################################################################################
# Line 45
# requires Python3.4 or better
import socket, binascii, time, urllib, urllib.request
# change these values to suit your requirements:-
HOST = '' # Hostname or ip address of interface, leave blank for all
PORT = 9999 # listening on port 9999 or 3200
logfile = 'ginlong.log' # location of output log file
webfile = 'ginlong.status' # location of web file
# Line 54
# inverter values found (so far) all big endian 16 bit unsigned:-
header = '685951b0' # hex stream header [original 685951b0]
data_size = 260 # hex stream size [original 206, elsewhere 270 & actual len=216 ]
inverter_temp = 31 # offset 31 & 32 temperature (/10)
inverter_vdc1 = 33 # offset 33 & 34 DC volts chain 1 (/10)
inverter_vdc2 = 35 # offset 35 & 36 DC volts chain 2 (/10)
inverter_adc1 = 39 # offset 39 & 40 DC amps chain 1 (/10)
inverter_adc2 = 41 # offset 41 & 42 DC amps chain 2 (/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 current generation Watts
inverter_yes = 67 # offset 67 & 68 yesterday kwh (/100)
inverter_day = 69 # offset 69 & 70 daily kWh (/100) or Wh (*10)
inverter_tot = 73 # offset 73 & 74 total kWh (/10)
inverter_mth = 87 # offset 87 & 88 total kWh for month
inverter_lmth = 91 # offset 91 & 92 total kWh for last month
# Line 72
print ('Start Ginlong inverter WiFi/LAN-poller script')
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # create socket on required port
print (HOST)
print (PORT)
sock.bind((HOST, PORT))
# Line 80
while True: # loop forever
sock.listen(1) # listen on port
print ('Socket now listening')
conn, addr = sock.accept() # wait for inverter connection
print ('Connected with ' + addr[0] + ':' + str(addr[1]))
rawdata = conn.recv(1000) # read incoming data
hexdata = binascii.hexlify(rawdata) # convert data to hex
# Line 89
print (hexdata)
# if(hexdata[0:8] == header and len(hexdata) == data_size): # check for valid data (not working!!!)
if(len(hexdata) <= data_size):
# extract main values and convert to decimal
watt_now = str(int(hexdata[inverter_now*2:inverter_now*2+4],16)) # generating power in watts
print (hexdata[inverter_now*2:inverter_now*2+4])
kwh_day_num = float(int(hexdata[inverter_day*2:inverter_day*2+4],16))/100 # running total kwh for day
kwh_day = str(kwh_day_num)
wh_day = str(int(hexdata[inverter_day*2:inverter_day*2+4],16) * 10) # running total kwh for day
kwh_total = str(int(hexdata[inverter_tot*2:inverter_tot*2+4],16)/10) # running total kwh from installation # Line 100
temp = str(float(int(hexdata[inverter_temp*2:inverter_temp*2+4],16))/10) # temperature # extract dc input values and convert to decimal
v1 =float(int(hexdata[inverter_vdc1*2:inverter_vdc1*2+4],16))/10 # input dc volts from chain 1
dc_volts1= str(v1)
v2 = float(int(hexdata[inverter_vdc2*2:inverter_vdc2*2+4],16))/10 # input dc volts from chain 2
dc_volts2= str(v2)
a1 = float(int(hexdata[inverter_adc1*2:inverter_adc1*2+4],16))/10 # input dc amps from chain 1
dc_amps1 = str(a1)
a2 = float(int(hexdata[inverter_adc2*2:inverter_adc2*2+4],16))/10 # input dc amps from chain 2
dc_amps2 = str(a2)
# 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
# Line 114
# Extract other historical values from inverter 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
# DateTime
t = (time.strftime("%R")) # Get time
d = (time.strftime("%Y%m%d")) # Get date
# Line 123
#Local logging
# write data to logfile, main values only
log = open(logfile,'a')
log.write(d + ' ' + t + ' ' + watt_now + ' ' + kwh_day + ' ' + kwh_total + '\n')
log.close()
# output status, overwrite all values, possibly for webpage
web = open(webfile,'w')
web.write(d + ' ' + t + ' ' + watt_now + ' ' + kwh_day + ' ' + kwh_total + ' ' + dc_volts1 + ' ' + dc_amps1 + ' ' + dc_volts2 + ' ' + dc_amps2 + ' ' + ac_volts + ' ' + ac_amps + ' ' + ac_freq + ' ' + kwh_yesterday + ' ' + kwh_month + ' ' + kwh_lastmonth + ' ' + temp + '\n')
web.close()
# Line 136
conn.close()
Re: Ginlong, Omnik Solar, Solarman and Trannergy Inverters
Posted: Friday 03 May 2019 12:15
by sincze
Hahaha nicely done.
Well I just waited for 5 minutes max and started to receive data. I checked the omnik portal for the timestamp of a new entry. They were spot on the same.. Server A omnik.. Server B mine.
Debug Time:
I think we need to figure out first if you also receive data.
Netcat and the write to file can confirm this. Or just write to your terminal.
If you wire shark in between you should see the same packages to your server B as to Server A.
Also identifying the protocol. I guess plaint http
If that works we can move to your great script.
Re: Ginlong, Omnik Solar, Solarman and Trannergy Inverters
Posted: Friday 03 May 2019 16:20
by Toulon7559
@Sincze

It doesn't work: nothing received.
Headscratching.
Related to this case, perhaps the network-configuration an aspect to consider in settings and calls?
For this aspect, the network is divided in 2 LAN-segments:
'front'-LAN1 is for the ESP8266s and the inverters+loggers, communicating with main router1.
'back'-LAN2 is separated from LAN1 by a router2, and house for the other computers.
Some computers, incl. Server_B have cable to LAN2 in combination with (Wifi + related IP) to main router1 at LAN1.
Till this moment never a communication problem, but obvious 'a first time' is possible.
Perhaps necessary to 'force' Server_B to connect in a specific way to LAN1 for communication with the Ginlong inverter?
[Although the ping-test from the inverter and the reverse reaction from Server_B do not indicate a blocking]
Re: Ginlong, Omnik Solar, Solarman and Trannergy Inverters
Posted: Friday 03 May 2019 16:41
by sincze
Toulon7559 wrote:@Sincze

It doesn't work: nothing received.
Headscratching.
Related to this case, perhaps the network-configuration an aspect to consider in settings and calls?
For this aspect, the network is divided in 2 LAN-segments:
'front'-LAN1 is for the ESP8266s and the inverters+loggers, communicating with main router1.
'back'-LAN2 is separated from LAN1 by a router2, and house for the other computers.
Some computers, incl. Server_B have cable to LAN2 in combination with (Wifi + related IP) to main router1 at LAN1.
Till this moment never a communication problem, but obvious 'a first time' is possible.
Perhaps necessary to 'force' Server_B to connect in a specific way to LAN1 for communication with the Ginlong inverter?
[Although the ping-test from the inverter and the reverse reaction from Server_B do not indicate a blocking]
You have a spare pi that you can put in LAN1 for testing the assumption.. it seems something is working
Multiple routers (sometimes NAT behind NAT) not always a good solution. However it can work. My personal advise. 1 router and create vlans

the firewall will control who can talk to what.
In my case the IOT stuff (front) can only talk to Domoticz on a specific port in 'back'
But let's try the spare pi part or put a nic of server B in front network.
Ginlock Omnik I think all do the same trick different destination...
Sent from my ONEPLUS A6003 using Tapatalk
Re: Ginlong, Omnik Solar, Solarman and Trannergy Inverters
Posted: Friday 03 May 2019 16:51
by Toulon7559

as indicated
here, already an extra Raspberry planned & reserved to separately get all 'power-related' functions at LAN1.
Just have to find enough time to organise & test that Raspberry and the shifted interfaces.
Till that time fiddling with the Domoticz2-Raspberry at LAN2.
As 'make-shift' solution perhaps Router2 give a temporary port-forwarding for port 9999 and tell the Ginlong-inverter to use the cable-interface to Server_B: not 'clean', but may be a practical solution.
Re: Ginlong, Omnik Solar, Solarman and Trannergy Inverters
Posted: Friday 03 May 2019 17:36
by sincze
Toulon7559 wrote:
as indicated
here, already an extra Raspberry planned & reserved to separately get all 'power-related' functions at LAN1.
Just have to find enough time to organise & test that Raspberry and the shifted interfaces.
Till that time fiddling with the Domoticz2-Raspberry at LAN2.
As 'make-shift' solution perhaps Router2 give a temporary port-forwarding for port 9999 and tell the Ginlong-inverter to use the cable-interface to Server_B: not 'clean', but may be a practical solution.
Maybe openwrt installed on 1 of the routers?? Use a netcat there??? Skips the part of ordering a spare pi
Sent from my ONEPLUS A6003 using Tapatalk
Re: Ginlong, Omnik Solar, Solarman and Trannergy Inverters
Posted: Friday 03 May 2019 17:58
by Toulon7559
Quick test: setting port forwarding in the routers doesn't get Server_B operational in this configuration.
The 3 'Expansion'-Raspberries are at my desk:

just lack of time for installation of one at LAN1 ......
Re: Ginlong, Omnik Solar, Solarman and Trannergy Inverters
Posted: Friday 03 May 2019 21:01
by sincze
Hahaha automation on a tight budget

we will figure it out.
Sent from my ONEPLUS A6003 using Tapatalk
Re: Ginlong, Omnik Solar, Solarman and Trannergy Inverters
Posted: Wednesday 08 May 2019 14:13
by sincze
Re: Ginlong, Omnik Solar, Solarman and Trannergy Inverters
Posted: Tuesday 30 July 2019 19:00
by sincze
Re: Ginlong, Omnik Solar, Solarman and Trannergy Inverters
Posted: Friday 23 August 2019 10:00
by Stormryder
galadril wrote: ↑Tuesday 30 April 2019 14:23
Ok i finished a new script for platform 2 of Ginlong, i've added the new script for platform 2 to the bottom of the OP !!
Thanks for the OP, just got my PV and want to combine the data with the data from my Smart Meter in Domoticz.
I use Solarman (online platform) to get my data at the moment.
When I try to run the scripts (StationID.py and Solarman.py, which is similar to your ginseng.py platform 1) I get an error on line 29.
Code: Select all
AttributeError: 'NoneType' object has no attribute 'text'
I have tried to delete the .text after
but this results in an error further on in the script.
I know this is an old thread, but hopefully you can still help me out with this one! Thanks
Re: Ginlong, Omnik Solar, Solarman and Trannergy Inverters
Posted: Monday 09 September 2019 13:59
by dutchronnie
I have a problem wit executing this script with a crontab.
When i start the script on the command line, the script is updating the data fields in a virtual sensor in domoticz.
But when i put it in a crontab nothing happens.
The scrips doesn't generate errors, so i think the script is good.
It must be the cronjob.
The line in the cronjob is as follows
*/5 * * * * /home/pi/domoticz/scripts/trannergy.py
Does somebody know what is wrong?
Re: Ginlong, Omnik Solar, Solarman and Trannergy Inverters
Posted: Monday 09 September 2019 15:22
by sincze
Re: Ginlong, Omnik Solar, Solarman and Trannergy Inverters
Posted: Monday 09 September 2019 19:41
by dutchronnie
That is a crontab -e
Re: Ginlong, Omnik Solar, Solarman and Trannergy Inverters
Posted: Thursday 28 November 2019 12:01
by P6Mole
Morning all,
Can anyone please help me with the error I am having below?
pi@raspberrypi:~ $ sudo python /home/pi/domoticz/scripts/ginlong.py
Login Succesfull!
Traceback (most recent call last):
File "/home/pi/domoticz/scripts/ginlong.py", line 50, in <module>
TodayIncome = resultJson['result']['plantAllWapper']['plantData'].get('incomeTotal')
TypeError: string indices must be integers
I'm using Raspbian Buster release 10,
Cheers
Re: Ginlong, Omnik Solar, Solarman and Trannergy Inverters
Posted: Wednesday 11 December 2019 16:25
by MeAlbert
rednas wrote: ↑Monday 08 April 2019 14:06
This is the code I use to scrape the info from the status.js file.
Modify it with your ip, username and password for logging into the webpage of the inverter. Also modify the idx of the sensors mentioned in the script.
Code: Select all
-- https://www.domoticz.com/forum/viewtopic.php?f=65&t=7941
return {
on = {
timer = { "every minute" },
httpResponses = { 'trigger-solar-data' }
},
logging = {
--level = domoticz.LOG_DEBUG, -- for debugging
--level = domoticz.LOG_INFO,
marker = "Zonnepanelen"
},
execute = function(domoticz, item)
ip = '192.168.x.xxx' --ip address of the solar inverter
user = 'xxx' --user name for solar inverter
pw = 'xxx' --password for solar inverter
Electric_meter_idx = 259 --kWhcounter
E_today_idx = 268 --custom
E_total_idx = 269 --custom
E_total_c_idx = 270 --counter
E_power_idx = 264 --energy
function update_kWhcounter_devc(devc, power, energy)
if (devc~='' and devc~=nil) then
--if (domoticz.devices(devc).usage ~= power or domoticz.devices(devc).WhTotal ~= energy) then
domoticz.devices(devc).updateElectricity(power, energy)
--end
end
end
function update_custom_devc(devc, value)
if (devc~='' and devc~=nil) then
--if (domoticz.devices(devc).state ~= value) then
domoticz.devices(devc).updateCustomSensor(value)
--end
end
end
function update_counterkWh_devc(devc, value)
if (devc~='' and devc~=nil) then
--if (domoticz.devices(devc).counter*1000 ~= value) then
domoticz.devices(devc).updateCounter(value)
--end
end
end
function update_energy_devc(devc, value)
if (devc~='' and devc~=nil) then
--if (domoticz.devices(devc).WhActual ~= value) then
domoticz.devices(devc).updateEnergy(value)
--end
end
end
function split(s, delimiter)
result = {};
for match in (s..delimiter):gmatch("(.-)"..delimiter) do
table.insert(result, match);
end
return result;
end
if (item.isTimer) then
requestURL = 'http://'..user..':'..pw..'@'..ip..'/js/status.js'
domoticz.openURL({
url = requestURL,
--method = 'GET',
callback = 'trigger-solar-data'
})
end
if (item.isHTTPResponse and item.ok) then
-- check to which request this response was the result
if (item.trigger == 'trigger-solar-data') then
--domoticz.log(item.data)
idata = string.match(item.data, 'myDeviceArray%[0%]="(.-)";')
--domoticz.log(idata)
s = split(idata, ",")
--for key, value in pairs(s) do
-- print(key..'='..value)
--end
powerW = s[6] -- in W
etoday = s[7]/100 -- in kWh
etotal = s[8]/10 -- in kWh
domoticz.log("Power: "..powerW.." W",domoticz.LOG_FORCE)
domoticz.log("Today: "..etoday.." kWh",domoticz.LOG_FORCE)
domoticz.log("Total: "..etotal.." kWh",domoticz.LOG_FORCE)
update_kWhcounter_devc(Electric_meter_idx, powerW, etotal*1000)
update_custom_devc(E_today_idx, etoday)
update_custom_devc(E_total_idx, etotal)
update_counterkWh_devc(E_total_c_idx, etotal*1000)
update_energy_devc(E_power_idx, powerW)
end
end
end
}
The program works fine on my solarsmart inverter. I added something to the beginning to prevent conyinues trying to reach the inverter when there is no power.
Code: Select all
on = {
timer = { "every minute at daytime" },
httpResponses = { 'trigger-solar-data' }
When contact with the inverter is lost there is still a none zero number left in powerW. This is then showed in the graphic as a line above zero.
How could we prevent that?
Re: Ginlong, Omnik Solar, Solarman and Trannergy Inverters
Posted: Saturday 28 December 2019 12:19
by Marijn
I have adjusted the script a bit. Because Solarmanpv can sometimes not be accessed.
Because of this I got a memoryleak on my raspberry, which caused the raspberry to crash.
I added a try to the login:
Code: Select all
#login call
try:
root = ET.parse(urllib.urlopen(requestURL)).getroot()
token = root.find('token').text
except: #Catch all
print 'Not logged in: ERROR'
exit()
Original code:
Code: Select all
#login call
root = ET.parse(urllib.urlopen(requestURL)).getroot()
token = root.find('token').text
Re: Ginlong, Omnik Solar, Solarman and Trannergy Inverters
Posted: Sunday 29 December 2019 12:33
by Marijn
Marijn wrote: ↑Saturday 28 December 2019 12:19
I have adjusted the script a bit. Because Solarmanpv can sometimes not be accessed.
Because of this I got a memoryleak on my raspberry, which caused the raspberry to crash.
I added a try to the login:
Code: Select all
#login call
try:
root = ET.parse(urllib.urlopen(requestURL)).getroot()
token = root.find('token').text
except: #Catch all
print 'Not logged in: ERROR'
exit()
That was not the solution. The scripts hangs on this two lines. But it doesn't throw an exception.
Now trying:
Code: Select all
#login call
try:
root = ET.parse(urllib2.urlopen(requestURL,timeout=10)).getroot()
token = root.find('token').text
except urllib2.UrlError, e: #Catch all
print 'Not logged in: ERROR'
print e
exit()
Re: Ginlong, Omnik Solar, Solarman and Trannergy Inverters
Posted: Monday 27 January 2020 12:40
by Wilu88
Hi. I have account on Ginlong ver 2 and i try use this code:
Code: Select all
#!/usr/bin/python
import requests
import urllib, urllib2
#config
username = 'USERNAME' #your username
password = 'PASSWORD' #your password
domain = 'm.ginlong.com' #domain
plantId = '123456' #plant id
lan = '2' #lanuage (2 = English)
#domoticz settings
domoticz_host = 'DOMOTICZ_USERNAME:DOMOTICZ_PASSWORD@IP'
domoticz_port = '8080'
domoticz_url = 'json.htm' #leave this
domoticz_device_idx = '58'
# Create session for requests
session = requests.session()
#building url
url = 'http://'+domain+'/cpro/login/validateLogin.json'
params = {
"userName": username,
"password": password,
"lan": lan,
"domain": domain,
"userType": "C"
}
#login call
resultData = session.post(url, params=params)
resultJson = resultData.json()
if resultJson['result'].get('isAccept') == 1:
print("Login Succesfull!")
else:
print("Login Failed!!")
Exit()
# Get plant details
url = 'http://'+domain+'/cpro/epc/plantDetail/showPlantDetailAjax.json'
params = {
'plantId': int(plantId)
}
cookies = {'language': lan}
resultData = session.get(url, params=params, cookies=cookies)
resultJson = resultData.json()
TodayIncome = resultJson['result']['plantAllWapper']['plantData'].get('incomeTotal')
ActualPower = resultJson['result']['plantAllWapper']['plantData'].get('power')
etoday = resultJson['result']['plantAllWapper']['plantData'].get('energyToday')
etotal = resultJson['result']['plantAllWapper']['plantData'].get('energyTotal')
multiply='1000.0'
etotal1000 = float(etotal) * float(multiply)
etotalstr=str(etotal1000)
#logging values
print 'TodayIncome: ' + str(TodayIncome)
print 'ActualPower: ' + str(ActualPower)
print 'etoday: ' + str(etoday)
print 'etotal: ' + str(etotal)
print 'etotal 1000: ' + str(etotalstr)
#uploading values to domoticz
url = ("http://" + domoticz_host + ":" + domoticz_port + "/" + domoticz_url+ "?type=command¶m=udevice&idx=" + domoticz_device_idx+ "&nvalue=0&svalue=" + str(ActualPower) + ";" + str(etotalstr))
urllib.urlopen(url)
But after use command
Code: Select all
sudo python dev-domoticz/scripts/ginlong.py
i see reasult:
Code: Select all
Traceback (most recent call last):
File "dev-domoticz/scripts/ginlong.py", line 4, in <module>
import requests
ImportError: No module named requests
Any idea?
Sorry for my English
