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"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"gitea.drjosh.dev/josh/sungrow/modbus"
|
||||
|
@ -33,12 +34,16 @@ import (
|
|||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
)
|
||||
|
||||
const maxScrapeAge = 3 * time.Second
|
||||
|
||||
var (
|
||||
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')")
|
||||
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{
|
||||
Namespace: "sungrow",
|
||||
|
@ -100,21 +105,13 @@ func init() {
|
|||
},
|
||||
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) {
|
||||
fmt.Fprintf(w, "current time: %v\n", time.Now())
|
||||
}
|
||||
|
||||
// Called under scrapeMu.
|
||||
func readRegs(client modbus.Client, start, qty uint16) {
|
||||
data, err := client.ReadInputRegisters(start, qty)
|
||||
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)
|
||||
}
|
||||
//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) {
|
||||
start := time.Now()
|
||||
scrapeStart.SetToCurrentTime()
|
||||
readRegs(client, 5000, 100)
|
||||
readRegs(client, 5100, 50)
|
||||
scrapeEnd.SetToCurrentTime()
|
||||
lastScrape = time.Now()
|
||||
scrapeDuration.Set(time.Since(start).Seconds())
|
||||
scrapeCounter.Inc()
|
||||
}
|
||||
|
@ -173,18 +172,34 @@ func main() {
|
|||
http.Handle("/metrics", promhttp.Handler())
|
||||
http.HandleFunc("/", statusHandler)
|
||||
|
||||
// Modbus scrape loop
|
||||
handler := modbus.TCPHandlerFromConnection(sgc)
|
||||
handler.SlaveId = 0x01
|
||||
//handler.Connect()
|
||||
defer handler.Close()
|
||||
client := modbus.NewClient(handler)
|
||||
scrape(client)
|
||||
// Start http interface only after first successful scrape
|
||||
go func() {
|
||||
log.Fatalf("http.ListenAndServe: %v", http.ListenAndServe(*httpAddr, nil))
|
||||
}()
|
||||
for range time.Tick(*scrapeInterval) {
|
||||
scrape(client)
|
||||
|
||||
// Finally, create all the register gauges.
|
||||
// These are GaugeFuncs to more closely align Prometheus scrape time with
|
||||
// the modbus scrape time.
|
||||
for addr, reg := range sungrowInputRegs {
|
||||
promauto.NewGaugeFunc(
|
||||
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