Add gateway and daemon boilerplate

This commit is contained in:
Rob Watson 2022-07-13 19:01:09 +02:00
parent bcb15b75e8
commit 72b0a690a6
6 changed files with 189 additions and 0 deletions

93
cmd/daemon/main.go Normal file
View File

@ -0,0 +1,93 @@
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 == "" {
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
}
reqBody, err := json.Marshal(runtimeData)
if err != nil {
log.Printf("error encoding runtime data: %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("Sent: %+v", runtimeData)
}
}

46
cmd/gateway/main.go Normal file
View File

@ -0,0 +1,46 @@
package main
import (
"log"
"net/http"
"os"
"time"
"git.netflux.io/rob/solar-toolkit/gateway/handler"
"git.netflux.io/rob/solar-toolkit/gateway/store"
"github.com/jmoiron/sqlx"
_ "github.com/lib/pq"
)
const defaultBindAddr = ":8888"
func main() {
databaseURL := os.Getenv("DATABASE_URL")
if databaseURL == "" {
log.Fatal("missing configuration DATABASE_URL")
}
bindAddr := os.Getenv("BIND_ADDR")
if bindAddr == "" {
bindAddr = defaultBindAddr
}
db, err := sqlx.Connect("postgres", databaseURL)
if err != nil {
log.Fatalf("could not connect to database: %s", err)
}
store := store.NewSQL(db)
handler := handler.NewHandler(store)
srv := http.Server{
ReadTimeout: time.Second * 3,
WriteTimeout: time.Second * 3,
Handler: handler,
Addr: bindAddr,
}
log.Printf("Listening on %s...", bindAddr)
if err := srv.ListenAndServe(); err != nil {
log.Fatal(err)
}
}

View File

@ -0,0 +1,21 @@
package handler
import (
"net/http"
"git.netflux.io/rob/solar-toolkit/inverter"
)
type Store interface {
InsertETRuntimeData(*inverter.ETRuntimeData) error
}
type Handler struct {
store Store
}
func NewHandler(store Store) *Handler { return &Handler{store: store} }
func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
}

18
gateway/store/store.go Normal file
View File

@ -0,0 +1,18 @@
package store
import (
"git.netflux.io/rob/solar-toolkit/inverter"
"github.com/jmoiron/sqlx"
)
type PostgresStore struct {
db *sqlx.DB
}
func NewSQL(db *sqlx.DB) *PostgresStore {
return &PostgresStore{db: db}
}
func (s *PostgresStore) InsertETRuntimeData(runtimeData *inverter.ETRuntimeData) error {
return nil
}

2
go.mod
View File

@ -3,6 +3,8 @@ module git.netflux.io/rob/solar-toolkit
go 1.18 go 1.18
require ( require (
github.com/jmoiron/sqlx v1.3.5
github.com/lib/pq v1.10.6
github.com/stretchr/testify v1.8.0 github.com/stretchr/testify v1.8.0
golang.org/x/exp v0.0.0-20220706164943-b4a6d9510983 golang.org/x/exp v0.0.0-20220706164943-b4a6d9510983
) )

9
go.sum
View File

@ -1,6 +1,15 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g=
github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.10.6 h1:jbk+ZieJ0D7EVGJYpL9QTz7/YW6UHbmdnZWYyK5cdBs=
github.com/lib/pq v1.10.6/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg=
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=