Initial commit — energy collector (AlphaEss + SDM630 → TimescaleDB)
This commit is contained in:
105
main.go
Normal file
105
main.go
Normal file
@@ -0,0 +1,105 @@
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user