Code: Select all
nc -l localhost 10000 > log.txt
In the ginlock direct all traffic to IP of your raspberry and port 10000
The file will fill up for you

Moderator: leecollings
Code: Select all
nc -l localhost 10000 > log.txt
Code: Select all
Start Ginlong inverter WiFi/LAN-poller script
9999
Socket now listening
Connected with 192.168.0.112:54296
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()
You have a spare pi that you can put in LAN1 for testing the assumption.. it seems something is workingToulon7559 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]
Maybe openwrt installed on 1 of the routers?? Use a netcat there??? Skips the part of ordering a spare piToulon7559 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.
Thanks for the OP, just got my PV and want to combine the data with the data from my Smart Meter in Domoticz.
Code: Select all
AttributeError: 'NoneType' object has no attribute 'text'
Code: Select all
token = root.find('token').text
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.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 }
Code: Select all
on = {
timer = { "every minute at daytime" },
httpResponses = { 'trigger-solar-data' }
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()
Code: Select all
#login call
root = ET.parse(urllib.urlopen(requestURL)).getroot()
token = root.find('token').text
That was not the solution. The scripts hangs on this two lines. But it doesn't throw an exception.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()
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()
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)
Code: Select all
sudo python dev-domoticz/scripts/ginlong.py
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
Users browsing this forum: No registered users and 1 guest