Make input registers GaugeFuncs
This commit is contained in:
parent
5fd288681b
commit
ea6f44e867
1 changed files with 34 additions and 19 deletions
53
main.go
53
main.go
|
@ -25,6 +25,7 @@ import (
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"gitea.drjosh.dev/josh/sungrow/modbus"
|
"gitea.drjosh.dev/josh/sungrow/modbus"
|
||||||
|
@ -33,12 +34,16 @@ import (
|
||||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const maxScrapeAge = 3 * time.Second
|
||||||
|
|
||||||
var (
|
var (
|
||||||
httpAddr = flag.String("http-addr", ":9455", "Address to listen on")
|
httpAddr = flag.String("http-addr", ":9455", "Address to listen on")
|
||||||
inverterAddrs = flag.String("inverter-addrs", "rakmodule_00DBC1:502,192.168.86.6:502", "Comma-separated list of inverter addresses (modbus-tcp with 'encryption')")
|
inverterAddrs = flag.String("inverter-addrs", "rakmodule_00DBC1:502,192.168.86.6:502", "Comma-separated list of inverter addresses (modbus-tcp with 'encryption')")
|
||||||
scrapeInterval = flag.Duration("scrape-interval", 15*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)
|
scrapeMu sync.Mutex
|
||||||
|
lastScrape time.Time
|
||||||
|
lastValues = make(map[uint16]float64)
|
||||||
|
|
||||||
scrapeCounter = promauto.NewCounter(prometheus.CounterOpts{
|
scrapeCounter = promauto.NewCounter(prometheus.CounterOpts{
|
||||||
Namespace: "sungrow",
|
Namespace: "sungrow",
|
||||||
|
@ -100,21 +105,13 @@ func init() {
|
||||||
},
|
},
|
||||||
func() float64 { return solarFeedInTariff.pricePerKWh(time.Now()) },
|
func() float64 { return solarFeedInTariff.pricePerKWh(time.Now()) },
|
||||||
)
|
)
|
||||||
|
|
||||||
for addr, reg := range sungrowInputRegs {
|
|
||||||
registerGauges[addr] = promauto.NewGauge(prometheus.GaugeOpts{
|
|
||||||
Namespace: "sungrow",
|
|
||||||
Subsystem: "inverter",
|
|
||||||
Name: reg.name,
|
|
||||||
Help: fmt.Sprintf("addr: %d, unit: %s", addr, reg.unit),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func statusHandler(w http.ResponseWriter, r *http.Request) {
|
func statusHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
fmt.Fprintf(w, "current time: %v\n", time.Now())
|
fmt.Fprintf(w, "current time: %v\n", time.Now())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Called under scrapeMu.
|
||||||
func readRegs(client modbus.Client, start, qty uint16) {
|
func readRegs(client modbus.Client, start, qty uint16) {
|
||||||
data, err := client.ReadInputRegisters(start, qty)
|
data, err := client.ReadInputRegisters(start, qty)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -136,16 +133,18 @@ func readRegs(client modbus.Client, start, qty uint16) {
|
||||||
log.Fatalf("Couldn't parse input register data at %d: %v", addr, err)
|
log.Fatalf("Couldn't parse input register data at %d: %v", addr, err)
|
||||||
}
|
}
|
||||||
//fmt.Printf("%s: %v %s\n", reg.name, val, reg.unit)
|
//fmt.Printf("%s: %v %s\n", reg.name, val, reg.unit)
|
||||||
registerGauges[addr].Set(val)
|
lastValues[addr] = val
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Called under scrapeMu.
|
||||||
func scrape(client modbus.Client) {
|
func scrape(client modbus.Client) {
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
scrapeStart.SetToCurrentTime()
|
scrapeStart.SetToCurrentTime()
|
||||||
readRegs(client, 5000, 100)
|
readRegs(client, 5000, 100)
|
||||||
readRegs(client, 5100, 50)
|
readRegs(client, 5100, 50)
|
||||||
scrapeEnd.SetToCurrentTime()
|
scrapeEnd.SetToCurrentTime()
|
||||||
|
lastScrape = time.Now()
|
||||||
scrapeDuration.Set(time.Since(start).Seconds())
|
scrapeDuration.Set(time.Since(start).Seconds())
|
||||||
scrapeCounter.Inc()
|
scrapeCounter.Inc()
|
||||||
}
|
}
|
||||||
|
@ -173,18 +172,34 @@ func main() {
|
||||||
http.Handle("/metrics", promhttp.Handler())
|
http.Handle("/metrics", promhttp.Handler())
|
||||||
http.HandleFunc("/", statusHandler)
|
http.HandleFunc("/", statusHandler)
|
||||||
|
|
||||||
// Modbus scrape loop
|
|
||||||
handler := modbus.TCPHandlerFromConnection(sgc)
|
handler := modbus.TCPHandlerFromConnection(sgc)
|
||||||
handler.SlaveId = 0x01
|
handler.SlaveId = 0x01
|
||||||
//handler.Connect()
|
//handler.Connect()
|
||||||
defer handler.Close()
|
defer handler.Close()
|
||||||
client := modbus.NewClient(handler)
|
client := modbus.NewClient(handler)
|
||||||
scrape(client)
|
|
||||||
// Start http interface only after first successful scrape
|
// Finally, create all the register gauges.
|
||||||
go func() {
|
// These are GaugeFuncs to more closely align Prometheus scrape time with
|
||||||
log.Fatalf("http.ListenAndServe: %v", http.ListenAndServe(*httpAddr, nil))
|
// the modbus scrape time.
|
||||||
}()
|
for addr, reg := range sungrowInputRegs {
|
||||||
for range time.Tick(*scrapeInterval) {
|
promauto.NewGaugeFunc(
|
||||||
scrape(client)
|
prometheus.GaugeOpts{
|
||||||
|
Namespace: "sungrow",
|
||||||
|
Subsystem: "inverter",
|
||||||
|
Name: reg.name,
|
||||||
|
Help: fmt.Sprintf("addr: %d, unit: %s", addr, reg.unit),
|
||||||
|
},
|
||||||
|
func() float64 {
|
||||||
|
scrapeMu.Lock()
|
||||||
|
defer scrapeMu.Unlock()
|
||||||
|
if time.Since(lastScrape) <= maxScrapeAge {
|
||||||
|
return lastValues[addr]
|
||||||
|
}
|
||||||
|
scrape(client)
|
||||||
|
return lastValues[addr]
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Fatalf("http.ListenAndServe: %v", http.ListenAndServe(*httpAddr, nil))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue