solar-toolkit/cmd/daemon/main.go

100 lines
2.3 KiB
Go

package main
import (
"bytes"
"context"
"encoding/json"
"flag"
"log"
"net"
"net/http"
"os"
"time"
"git.netflux.io/rob/solar-toolkit/inverter"
)
const (
httpUserAgent = "solar-toolkit (git.netflux.io)"
httpTimeout = time.Second * 5
)
func main() {
var (
inverterAddr string
gatewayEndpoint string
gatewayUsername string
gatewayPassword string
pollInterval time.Duration
)
flag.StringVar(&inverterAddr, "inverter-addr", "", "IP+port of solar inverter")
flag.StringVar(&gatewayEndpoint, "endpoint", "", "URL to post metrics to")
flag.StringVar(&gatewayUsername, "username", "", "HTTP basic auth username")
flag.StringVar(&gatewayPassword, "password", "", "HTTP basic auth password")
flag.DurationVar(&pollInterval, "pollInterval", time.Minute, "Poll interval, example: 60s")
flag.Parse()
if gatewayEndpoint == "" || inverterAddr == "" {
flag.Usage()
os.Exit(1)
}
conn, err := net.Dial("udp", inverterAddr)
if err != nil {
log.Fatalf("error dialing: %s", err)
}
defer conn.Close()
var inv inverter.ET
ticker := time.NewTicker(pollInterval)
defer ticker.Stop()
client := http.Client{Timeout: httpTimeout}
for ; true; <-ticker.C {
runtimeData, err := inv.RuntimeData(context.Background(), conn)
if err != nil {
log.Printf("error fetching runtime data: %s", err)
continue
}
meterData, err := inv.MeterData(context.Background(), conn)
if err != nil {
log.Printf("error fetching meter data: %s", err)
continue
}
frame := inverter.ETDataFrame{ETRuntimeData: runtimeData, ETMeterData: meterData}
reqBody, err := json.Marshal(frame)
if err != nil {
log.Printf("error encoding frame: %s", err)
continue
}
req, err := http.NewRequest(http.MethodPost, gatewayEndpoint, bytes.NewReader(reqBody))
if err != nil {
log.Printf("error building request: %s", err)
continue
}
req.Header.Set("content-type", "application/json")
req.Header.Set("user-agent", httpUserAgent)
if gatewayUsername != "" && gatewayPassword != "" {
req.SetBasicAuth(gatewayUsername, gatewayPassword)
}
resp, err := client.Do(req)
if err != nil {
log.Printf("error sending request: %s", err)
continue
}
if resp.StatusCode != http.StatusOK {
log.Printf("unexpected HTTP response code: %d", resp.StatusCode)
continue
}
log.Printf("OK: %s", runtimeData.PVPower.String())
}
}