Files
energy-collector/main.go

106 lines
2.1 KiB
Go

package main
import (
"context"
"flag"
"log"
"os"
"os/signal"
"sync"
"syscall"
"time"
)
var logger = log.New(os.Stderr, "", log.Ltime|log.Lshortfile)
func main() {
cfgPath := flag.String("c", "/srv/energy/collector/config.json", "path to config file")
flag.Parse()
cfg, err := loadConfig(*cfgPath)
if err != nil {
log.Fatalf("config: %v", err)
}
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
db, err := NewDB(ctx, cfg.DB.DSN)
if err != nil {
log.Fatalf("db: %v", err)
}
defer db.Close()
alpha, err := NewAlphaEss(cfg.AlphaEss)
if err != nil {
log.Fatalf("alphaess: %v", err)
}
defer alpha.Close()
meters, err := NewMeterPoller(cfg.MQTT)
if err != nil {
log.Fatalf("meters: %v", err)
}
defer meters.Close()
interval := time.Duration(cfg.SampleRate) * time.Second
go runPollLoop(ctx, alpha, meters, db, interval)
sig := make(chan os.Signal, 1)
signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM)
<-sig
logger.Println("shutting down")
}
func runPollLoop(ctx context.Context, alpha *AlphaEss, meters *MeterPoller, db *DB, interval time.Duration) {
ticker := time.NewTicker(interval)
defer ticker.Stop()
for {
select {
case <-ctx.Done():
return
case <-ticker.C:
poll(ctx, alpha, meters, db)
}
}
}
func poll(ctx context.Context, alpha *AlphaEss, meters *MeterPoller, db *DB) {
t := time.Now()
// Poll AlphaEss and all SDM630 meters in parallel.
var (
inverterData *InverterData
meterData []MeterReading
wg sync.WaitGroup
)
wg.Add(2)
go func() {
defer wg.Done()
d, err := alpha.Poll()
if err != nil {
logger.Printf("alphaess: %v", err)
return
}
inverterData = d
}()
go func() {
defer wg.Done()
meterData = meters.PollAll()
}()
wg.Wait()
// Write everything with the same timestamp t.
if inverterData != nil {
if err := db.WriteInverter(ctx, t, inverterData); err != nil {
logger.Printf("write inverter: %v", err)
}
}
for _, r := range meterData {
if err := db.WriteMeter(ctx, t, r); err != nil {
logger.Printf("write meter %s: %v", r.Device, err)
}
}
}