-
Notifications
You must be signed in to change notification settings - Fork 17
/
Copy pathread-ginlong.bash
157 lines (129 loc) · 7.98 KB
/
read-ginlong.bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#!/bin/bash
###################################################################################################
#
# Copyright 2015 Graham Whiteside, Manchester, UK. Version 0.4 June 2020.
#
# 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/>.
#
###################################################################################################
###################################################################################################
#
# Linux bash script 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.
#
# change the file locations to suit your system.
#
# read-ginlong requires the following dependencies:-
# nc netcat reads incoming stream
# od octal dump to create hex output
# grep compares strings etc
# date displays system date/time
# bc command line calculator
# sed stream edit
# Most of these will already be installed, if not grab them from your repository.
#
# Output of log file, format (space separated) new lines appended:-
# 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 script 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.
#
###################################################################################################
set +o monitor # Make sure job control is disabled
# change these values to suit your requirements:-
logfile="ginlong.log" # location of output log file
webfile="ginlong.status" # location of web file with all values
listen_port=9999 # port server listens for inverter stream
# stream values found (so far) all big endian:-
header="685951b0" # stream header
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 currant generation Watts
inverter_yes=67 # offset 67 & 68 yesterday kwh (/100)
inverter_day=69 # offset 69 & 70 daily kWh (/100)
inverter_tot=71 # offset 71 & 72 & 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
for (( ; ; )); do # loop forever
inverter_output=$(nc -l $listen_port | od -w500 -An -t x1) # read incoming stream and convert to hex
inverter_output=$(echo $inverter_output | sed 's/ //g') # remove spaces from between hex values
find_header=$(echo $inverter_output | grep "^$header") # look for header at start of stream
if [ "$find_header" != "" ]; then # check header string is there
# extract main values and convert to decimal
watts_now=${inverter_output:$inverter_now*2:4} # read values for watts now
watts_now=$(echo $((16#$watts_now))) # convert to integer
kwh_day=${inverter_output:$inverter_day*2:4} # read values for kWh day
kwh_day=$(echo $((16#$kwh_day))) # convert to integer
kwh_day=$(echo "scale=1; $kwh_day/100" | bc) # apply factor /100
kwh_day=$(echo $kwh_day | sed 's/^\./0./') # add leading zero
kwh_tot=${inverter_output:$inverter_tot*2:8} # read values for kWh day
kwh_tot=$(echo $((16#$kwh_tot))) # convert to integer
kwh_tot=$(echo "$kwh_tot/10" | bc) # apply factor /10
# extract dc input values and convert to decimal
dc_volts1=${inverter_output:$inverter_vdc1*2:4} # read values for DC volts 1 from chain 1
dc_volts1=$(echo $((16#$dc_volts1))) # convert to integer
dc_volts1=$(echo "scale=1; $dc_volts1/10" | bc) # apply factor /10
dc_volts2=${inverter_output:$inverter_vdc2*2:4} # read values for DC volts 2 from chain 2
dc_volts2=$(echo $((16#$dc_volts2))) # convert to integer
dc_volts2=$(echo "scale=1; $dc_volts2/10" | bc) # apply factor /10
dc_amps1=${inverter_output:$inverter_adc1*2:4} # read values for DC amps 1 from chain 1
dc_amps1=$(echo $((16#$dc_amps1))) # convert to integer
dc_amps1=$(echo "scale=1; $dc_amps1/10" | bc) # apply factor /10
dc_amps1=$(echo $dc_amps1 | sed 's/^\./0./') # add leading zero
dc_amps2=${inverter_output:$inverter_adc2*2:4} # read values for DC amps 2 from chain 2
dc_amps2=$(echo $((16#$dc_amps2))) # convert to integer
dc_amps2=$(echo "scale=1; $dc_amps2/10" | bc) # apply factor /10
dc_amps2=$(echo $dc_amps2 | sed 's/^\./0./') # add leading zero
# extract other ac values and convert to decimal
ac_volts=${inverter_output:$inverter_vac*2:4} # read values for AC volts output
ac_volts=$(echo $((16#$ac_volts))) # convert to integer
ac_volts=$(echo "scale=1; $ac_volts/10" | bc) # apply factor /10
ac_amps=${inverter_output:$inverter_aac*2:4} # read values for AC amps output
ac_amps=$(echo $((16#$ac_amps))) # convert to integer
ac_amps=$(echo "scale=1; $ac_amps/10" | bc) # apply factor /10
ac_amps=$(echo $ac_amps | sed 's/^\./0./') # add leading zero
ac_freq=${inverter_output:$inverter_freq*2:4} # read values for AC output frequency Hertz
ac_freq=$(echo $((16#$ac_freq))) # convert to integer
ac_freq=$(echo "scale=2; $ac_freq/100" | bc) # apply factor /100
# extract other historical values and convert to decimal
kwh_yesterday=${inverter_output:$inverter_yes*2:4} # read values for kWh day
kwh_yesterday=$(echo $((16#$kwh_yesterday))) # convert to integer
kwh_yesterday=$(echo "scale=1; $kwh_yesterday/100" | bc) # apply factor /100
kwh_yesterday=$(echo $kwh_yesterday | sed 's/^\./0./') # add leading zero
kwh_month=${inverter_output:$inverter_mth*2:4} # read values total kwh for month
kwh_month=$(echo $((16#$kwh_month))) # convert to integer
kwh_lastmonth=${inverter_output:$inverter_lmth*2:4} # read values total kwh for last month
kwh_lastmonth=$(echo $((16#$kwh_lastmonth))) # convert to integer
temp=${inverter_output:$inverter_temp*2:4} # read values for inverter temp
temp=$(echo $((16#$temp))) # convert to integer
temp=$(echo "scale=1; $temp/10" | bc) # apply factor /10
time_stamp=$(date +'%F %H:%M') # get date and time
echo "$time_stamp $watts_now $kwh_day $kwh_tot" >>$logfile # output to log (main values only)
echo "$time_stamp $watts_now $kwh_day $kwh_tot $dc_volts1 $dc_amps1 $dc_volts2 $dc_amps2 $ac_volts $ac_amps $ac_freq $kwh_yesterday $kwh_month $kwh_lastmonth $temp" >$webfile # output all values, possibly for webpage
fi
sleep 5s # wait five seconds
done # end of loop