197 lines
3.6 KiB
Go
197 lines
3.6 KiB
Go
package main
|
|
|
|
import (
|
|
"database/sql"
|
|
"encoding/xml"
|
|
"fmt"
|
|
"net/http"
|
|
"strconv"
|
|
"time"
|
|
|
|
"git.fuyu.moe/5GPowerQuality/parser/internal/model"
|
|
"git.fuyu.moe/Fuyu/flog"
|
|
"git.ultraware.nl/NiseVoid/qb"
|
|
"git.ultraware.nl/NiseVoid/qb/qbdb"
|
|
"git.ultraware.nl/NiseVoid/qb/qc"
|
|
"git.ultraware.nl/NiseVoid/qb/qf"
|
|
"golang.org/x/net/html/charset"
|
|
)
|
|
|
|
var db *qbdb.DB
|
|
|
|
func main() {
|
|
defer recoverFunc()
|
|
setLogger()
|
|
|
|
flog.Info(`Starting`)
|
|
catchSignals()
|
|
|
|
initDB()
|
|
|
|
for {
|
|
fetchData()
|
|
}
|
|
}
|
|
|
|
func recoverFunc() {
|
|
v := recover()
|
|
if v != nil {
|
|
flog.Critical(`panic: `, v)
|
|
}
|
|
}
|
|
|
|
var start time.Time
|
|
|
|
func fetchData() {
|
|
defer recoverFunc()
|
|
|
|
if start.IsZero() {
|
|
start = GetStartDate()
|
|
}
|
|
|
|
end := start.Add(time.Hour)
|
|
|
|
data := GetFortopData(start, end)
|
|
ranges := map[int]map[string][]Range{}
|
|
for _, meter := range data {
|
|
mID := GetMeterID(meter.MeterID)
|
|
ranges[mID] = map[string][]Range{}
|
|
|
|
for _, v := range meter.Meetwaarde {
|
|
ranges[mID][v.Naam] = v.Range
|
|
}
|
|
}
|
|
|
|
sets := map[int]Sets{}
|
|
for meter, val := range ranges {
|
|
sets[meter] = Sets{}
|
|
|
|
for k, v := range val {
|
|
for _, r := range v {
|
|
date := time.Time(r.Date)
|
|
set, ok := sets[meter][date]
|
|
if !ok {
|
|
sets[meter][date] = Set{}
|
|
set = sets[meter][date]
|
|
}
|
|
|
|
set[k] = r.Value
|
|
}
|
|
}
|
|
}
|
|
|
|
insertSets(sets)
|
|
|
|
if end.Before(time.Now()) {
|
|
start = end.Add(time.Second)
|
|
return
|
|
}
|
|
|
|
time.Sleep(time.Minute)
|
|
|
|
start = GetStartDate()
|
|
}
|
|
|
|
// GetMeterID gets the meter ID, if there is none yet a new record is add to meter
|
|
func GetMeterID(meterID string) (id int) {
|
|
me := model.Meter()
|
|
q := me.Select(me.ID).
|
|
Where(qc.Eq(me.FortopUID, meterID))
|
|
|
|
err := db.QueryRow(q).Scan(&id)
|
|
switch err {
|
|
case nil:
|
|
case sql.ErrNoRows:
|
|
iq := me.Insert(me.Name, me.FortopUID).
|
|
Values(``, meterID)
|
|
|
|
err = db.QueryRow(qb.Returning(iq, me.ID)).Scan(&id)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
default:
|
|
panic(err)
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// GetStartDate gets the last measurement date
|
|
func GetStartDate() time.Time {
|
|
m := model.Measurement()
|
|
var t *time.Time
|
|
|
|
q := m.Select(qf.Max(m.Time))
|
|
err := db.QueryRow(q).Scan(&t)
|
|
if (err == nil && t == nil) || err == sql.ErrNoRows {
|
|
return time.Date(2018, 4, 1, 0, 0, 0, 0, time.Local)
|
|
}
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
*t = t.Add(time.Second)
|
|
|
|
return *t
|
|
}
|
|
|
|
func insertSets(sets map[int]Sets) {
|
|
if len(sets) == 0 {
|
|
return
|
|
}
|
|
|
|
m := model.Measurement()
|
|
q := m.Insert(m.Time, m.MeterID,
|
|
m.CGem1, m.CGem2, m.CGem3,
|
|
m.Ep1, m.Ep2, m.Ep3,
|
|
m.IGem1, m.IGem2, m.IGem3,
|
|
m.IMax1, m.IMax2, m.IMax3,
|
|
m.PMax1, m.PMax2, m.PMax3,
|
|
m.SMax1, m.SMax2, m.SMax3,
|
|
m.UGem1, m.UGem2, m.UGem3,
|
|
)
|
|
|
|
for meter, s := range sets {
|
|
for k, v := range s {
|
|
q.Values(k, meter,
|
|
v[`CGem1`], v[`CGem2`], v[`CGem3`],
|
|
v[`EP1`], v[`EP2`], v[`EP3`],
|
|
v[`IGem1`], v[`IGem2`], v[`IGem3`],
|
|
v[`IMax1`], v[`IMax2`], v[`IMax3`],
|
|
v[`PMax1`], v[`PMax2`], v[`PMax3`],
|
|
v[`SMax1`], v[`SMax2`], v[`SMax3`],
|
|
v[`UGem1`], v[`UGem2`], v[`UGem3`],
|
|
)
|
|
}
|
|
}
|
|
|
|
err := db.Exec(q)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
// GetFortopData retrieves data from fortop
|
|
func GetFortopData(startDate, endDate time.Time) []Meter {
|
|
url := `https://energy4all.energyportal.online/index?p5g=S_1_` + strconv.FormatInt(startDate.Unix(), 10) + `_` + strconv.FormatInt(endDate.Unix(), 10)
|
|
resp, err := http.Get(url)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
if resp.StatusCode != 200 {
|
|
fmt.Println(`Got status code:`, resp.StatusCode)
|
|
return nil
|
|
}
|
|
|
|
decoder := xml.NewDecoder(resp.Body)
|
|
decoder.CharsetReader = charset.NewReaderLabel
|
|
|
|
var data FortopFormat
|
|
err = decoder.Decode(&data)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
return data.Trafo.Meter
|
|
}
|