maybe it needs a lock?
This commit is contained in:
parent
b9c49613fe
commit
30ef059ce4
3 changed files with 29 additions and 16 deletions
32
main.go
32
main.go
|
@ -20,7 +20,7 @@ import (
|
||||||
var (
|
var (
|
||||||
httpAddr = flag.String("http-addr", ":9455", "Address to listen on")
|
httpAddr = flag.String("http-addr", ":9455", "Address to listen on")
|
||||||
inverterAddr = flag.String("inverter-addr", "192.168.86.33:502", "Address of inverter")
|
inverterAddr = flag.String("inverter-addr", "192.168.86.33:502", "Address of inverter")
|
||||||
scrapeInterval = flag.Duration("scrape-interval", 5*time.Second, "Period of modbus scraping loop")
|
scrapeInterval = flag.Duration("scrape-interval", 15*time.Second, "Period of modbus scraping loop")
|
||||||
|
|
||||||
registerGauges = make(map[uint16]prometheus.Gauge)
|
registerGauges = make(map[uint16]prometheus.Gauge)
|
||||||
|
|
||||||
|
@ -73,6 +73,21 @@ func statusHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
http.Error(w, "not implemented", http.StatusNotFound)
|
http.Error(w, "not implemented", http.StatusNotFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func readRegs(client modbus.Client, start, qty uint16) {
|
||||||
|
data, err := client.ReadInputRegisters(5000, 50)
|
||||||
|
if err != nil {
|
||||||
|
die("Couldn't read input registers %d-%d: %v", start+1, start+qty, err)
|
||||||
|
}
|
||||||
|
for addr, reg := range sungrowInputRegs {
|
||||||
|
if addr <= start || addr > start+qty {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
val := reg.read(data[(addr-start-1)*2:])
|
||||||
|
//fmt.Printf("%s: %v %s\n", reg.name, val, reg.unit)
|
||||||
|
registerGauges[addr].Set(val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
scrapeIntervalGauge.Set(float64(*scrapeInterval))
|
scrapeIntervalGauge.Set(float64(*scrapeInterval))
|
||||||
|
@ -118,19 +133,8 @@ func main() {
|
||||||
for {
|
for {
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
scrapeStart.SetToCurrentTime()
|
scrapeStart.SetToCurrentTime()
|
||||||
d0, err := client.ReadInputRegisters(5000, 100)
|
readRegs(client, 5000, 50)
|
||||||
if err != nil {
|
readRegs(client, 5100, 50)
|
||||||
die("Couldn't read input registers 5001-5100: %v", err)
|
|
||||||
}
|
|
||||||
d1, err := client.ReadInputRegisters(5100, 50)
|
|
||||||
if err != nil {
|
|
||||||
die("Couldn't read input registers 5101-5149: %v", err)
|
|
||||||
}
|
|
||||||
data := append(d0, d1...)
|
|
||||||
for addr, reg := range sungrowInputRegs {
|
|
||||||
//fmt.Printf("%s: %v %s\n", reg.name, val, reg.unit)
|
|
||||||
registerGauges[addr].Set(reg.read(data[(addr-5001)*2:]))
|
|
||||||
}
|
|
||||||
scrapeEnd.SetToCurrentTime()
|
scrapeEnd.SetToCurrentTime()
|
||||||
scrapeDuration.Set(time.Since(start).Seconds())
|
scrapeDuration.Set(time.Since(start).Seconds())
|
||||||
scrapeCounter.Inc()
|
scrapeCounter.Inc()
|
||||||
|
|
12
sungrow.go
12
sungrow.go
|
@ -8,6 +8,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -40,10 +41,11 @@ func getKey(conn io.ReadWriter) ([]byte, error) {
|
||||||
// sungrowConn wraps a regular TCP connection with funky Sungrow encryption.
|
// sungrowConn wraps a regular TCP connection with funky Sungrow encryption.
|
||||||
type sungrowConn struct {
|
type sungrowConn struct {
|
||||||
net.Conn
|
net.Conn
|
||||||
|
|
||||||
block cipher.Block
|
block cipher.Block
|
||||||
fifo *bytes.Buffer
|
fifo *bytes.Buffer
|
||||||
txid uint16
|
|
||||||
|
mu sync.Mutex
|
||||||
|
txid uint16
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *sungrowConn) Write(msg []byte) (int, error) {
|
func (c *sungrowConn) Write(msg []byte) (int, error) {
|
||||||
|
@ -51,7 +53,10 @@ func (c *sungrowConn) Write(msg []byte) (int, error) {
|
||||||
return c.Conn.Write(msg)
|
return c.Conn.Write(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c.mu.Lock()
|
||||||
c.txid = binary.BigEndian.Uint16(msg[:2])
|
c.txid = binary.BigEndian.Uint16(msg[:2])
|
||||||
|
c.mu.Unlock()
|
||||||
|
|
||||||
c.fifo.Truncate(0)
|
c.fifo.Truncate(0)
|
||||||
|
|
||||||
bs := c.block.BlockSize()
|
bs := c.block.BlockSize()
|
||||||
|
@ -76,6 +81,7 @@ func (c *sungrowConn) Read(out []byte) (int, error) {
|
||||||
if c.block == nil {
|
if c.block == nil {
|
||||||
return c.Conn.Read(out)
|
return c.Conn.Read(out)
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.fifo.Len() > 0 {
|
if c.fifo.Len() > 0 {
|
||||||
return c.fifo.Read(out)
|
return c.fifo.Read(out)
|
||||||
}
|
}
|
||||||
|
@ -95,7 +101,9 @@ func (c *sungrowConn) Read(out []byte) (int, error) {
|
||||||
for cp := pkt; len(cp) > 0; cp = cp[bs:] {
|
for cp := pkt; len(cp) > 0; cp = cp[bs:] {
|
||||||
c.block.Decrypt(cp, cp)
|
c.block.Decrypt(cp, cp)
|
||||||
}
|
}
|
||||||
|
c.mu.Lock()
|
||||||
binary.BigEndian.PutUint16(pkt, c.txid)
|
binary.BigEndian.PutUint16(pkt, c.txid)
|
||||||
|
c.mu.Unlock()
|
||||||
c.fifo.Write(pkt[:pktlen])
|
c.fifo.Write(pkt[:pktlen])
|
||||||
return c.fifo.Read(out)
|
return c.fifo.Read(out)
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,7 @@ var sungrowInputRegs = map[uint16]*register{
|
||||||
5035: {"power_factor", s16, 0.001, ""},
|
5035: {"power_factor", s16, 0.001, ""},
|
||||||
5036: {"frequency", u16, 0.1, "Hz"},
|
5036: {"frequency", u16, 0.1, "Hz"},
|
||||||
5049: {"nominal_reactive_power", s16, 0.1, "kVA"},
|
5049: {"nominal_reactive_power", s16, 0.1, "kVA"},
|
||||||
|
|
||||||
5113: {"daily_running_time", u16, 1, "m"},
|
5113: {"daily_running_time", u16, 1, "m"},
|
||||||
5144: {"total_power_yield_2", u32, 0.1, "kWh"},
|
5144: {"total_power_yield_2", u32, 0.1, "kWh"},
|
||||||
5148: {"frequency_2", u16, 0.01, "Hz"},
|
5148: {"frequency_2", u16, 0.01, "Hz"},
|
||||||
|
|
Loading…
Reference in a new issue