Initial commit

This commit is contained in:
Nise Void 2018-05-14 14:19:29 +02:00
commit 6bc66975db
Signed by: NiseVoid
GPG Key ID: FBA14AC83EA602F3
10 changed files with 407 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
api
log
**/model/tables.go

21
app/db.go Normal file
View File

@ -0,0 +1,21 @@
package app
import (
"database/sql"
"git.ultraware.nl/NiseVoid/qb/driver/autoqb"
"git.ultraware.nl/NiseVoid/qb/qbdb"
_ "github.com/lib/pq" // PostgreSQL driver
)
var db *qbdb.DB
// InitDB initializes the database connection
func InitDB() {
d, err := sql.Open(`postgres`, `host=/tmp dbname=power_quality`)
if err != nil {
panic(err)
}
db = autoqb.New(d)
}

175
app/internal/model/db.json Normal file
View File

@ -0,0 +1,175 @@
[
{
"name": "public.measurement",
"fields": [
{
"name": "c_gem_1",
"type": "double precision",
"null": false,
"size": 8
},
{
"name": "c_gem_2",
"type": "double precision",
"null": false,
"size": 8
},
{
"name": "c_gem_3",
"type": "double precision",
"null": false,
"size": 8
},
{
"name": "ep_1",
"type": "double precision",
"null": false,
"size": 8
},
{
"name": "ep_2",
"type": "double precision",
"null": false,
"size": 8
},
{
"name": "ep_3",
"type": "double precision",
"null": false,
"size": 8
},
{
"name": "i_gem_1",
"type": "double precision",
"null": false,
"size": 8
},
{
"name": "i_gem_2",
"type": "double precision",
"null": false,
"size": 8
},
{
"name": "i_gem_3",
"type": "double precision",
"null": false,
"size": 8
},
{
"name": "i_max_1",
"type": "double precision",
"null": false,
"size": 8
},
{
"name": "i_max_2",
"type": "double precision",
"null": false,
"size": 8
},
{
"name": "i_max_3",
"type": "double precision",
"null": false,
"size": 8
},
{
"name": "p_gem_1",
"type": "double precision",
"null": false,
"size": 8
},
{
"name": "p_gem_2",
"type": "double precision",
"null": false,
"size": 8
},
{
"name": "p_gem_3",
"type": "double precision",
"null": false,
"size": 8
},
{
"name": "p_max_1",
"type": "double precision",
"null": false,
"size": 8
},
{
"name": "p_max_2",
"type": "double precision",
"null": false,
"size": 8
},
{
"name": "p_max_3",
"type": "double precision",
"null": false,
"size": 8
},
{
"name": "s_gem_1",
"type": "double precision",
"null": false,
"size": 8
},
{
"name": "s_gem_2",
"type": "double precision",
"null": false,
"size": 8
},
{
"name": "s_gem_3",
"type": "double precision",
"null": false,
"size": 8
},
{
"name": "s_max_1",
"type": "double precision",
"null": false,
"size": 8
},
{
"name": "s_max_2",
"type": "double precision",
"null": false,
"size": 8
},
{
"name": "s_max_3",
"type": "double precision",
"null": false,
"size": 8
},
{
"name": "time",
"type": "timestamp with time zone",
"null": false,
"size": 8
},
{
"name": "u_gem_1",
"type": "double precision",
"null": false,
"size": 8
},
{
"name": "u_gem_2",
"type": "double precision",
"null": false,
"size": 8
},
{
"name": "u_gem_3",
"type": "double precision",
"null": false,
"size": 8
}
]
}
]

View File

@ -0,0 +1,3 @@
package model
//go:generate qb-generator db.json tables.go

71
app/stats.go Normal file
View File

@ -0,0 +1,71 @@
package app
import (
"reflect"
"time"
"git.fuyu.moe/5GPowerQuality/api/app/internal/model"
"git.ultraware.nl/NiseVoid/qb"
"git.ultraware.nl/NiseVoid/qb/qc"
"git.ultraware.nl/NiseVoid/qb/qf"
)
// Count returns the number of measurements
func Count() int {
m := model.Measurement()
q := m.Select(qf.CountAll())
var count *int
err := db.QueryRow(q).Scan(&count)
if err != nil {
panic(err)
}
if count == nil {
return 0
}
return *count
}
// GetAttribute returns the specified attribute for all phases since the specified date
func GetAttribute(attr string, date time.Time) (data []Phases) {
m := model.Measurement()
f := reflect.ValueOf(m).Elem().FieldByName(attr + `1`)
if !f.IsValid() || f.Type().Name() != `Field` {
return nil
}
f1 := f.Interface().(*qb.TableField)
f2 := reflect.ValueOf(m).Elem().FieldByName(attr + `2`).Interface().(*qb.TableField)
f3 := reflect.ValueOf(m).Elem().FieldByName(attr + `3`).Interface().(*qb.TableField)
q := m.Select(m.Time, f1, f2, f3).
OrderBy(qb.Desc(m.Time)).
Where(qc.Gte(m.Time, date))
rows, err := db.Query(q)
if err != nil {
panic(err)
}
for rows.Next() {
var phases Phases
err := rows.Scan(&phases.Time, &phases.P1, &phases.P2, &phases.P3)
if err != nil {
panic(err)
}
data = append(data, phases)
}
return
}
// Phases contains data for all phases
type Phases struct {
Time time.Time `json:"time"`
P1 float64 `json:"phase_1"`
P2 float64 `json:"phase_2"`
P3 float64 `json:"phase_3"`
}

19
server/logger.go Normal file
View File

@ -0,0 +1,19 @@
package main
import (
"os"
"os/signal"
"syscall"
"git.fuyu.moe/Fuyu/flog"
)
func catchSignals() {
sc := make(chan os.Signal, 1)
signal.Notify(sc, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
go func() {
s := <-sc
flog.Info(`Stopping, signal: `, s)
os.Exit(0)
}()
}

12
server/logger_debug.go Normal file
View File

@ -0,0 +1,12 @@
// +build cgo
package main
import (
"git.fuyu.moe/Fuyu/flog"
)
func setLogger() {
flog.MinLevel = flog.LevelDebug
flog.MinStackLevel = flog.LevelWarning
}

20
server/logger_release.go Normal file
View File

@ -0,0 +1,20 @@
// +build !cgo
package main
import (
"os"
"git.fuyu.moe/Fuyu/flog"
)
func setLogger() {
f, err := os.OpenFile(`log`, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
if err != nil {
panic(err)
}
flog.Output = f
flog.MinLevel = flog.LevelInfo
flog.MinStackLevel = flog.LevelWarning
}

63
server/main.go Normal file
View File

@ -0,0 +1,63 @@
package main
import (
"strings"
"time"
"git.fuyu.moe/5GPowerQuality/api/app"
"git.fuyu.moe/Fuyu/flog"
"github.com/labstack/echo"
)
func main() {
defer func() {
v := recover()
if v != nil {
flog.Critical(`panic: `, v)
}
}()
setLogger()
flog.Info(`Starting`)
catchSignals()
app.InitDB()
e := echo.New()
e.HideBanner = true
e.Use(recoverMiddleware)
e.GET(`/count`, count)
e.GET(`/:attr/:date`, pmax)
panic(e.Start(`localhost:33333`))
}
func count(c echo.Context) error {
return c.JSON(200, app.Count())
}
func pmax(c echo.Context) error {
attr := c.Param(`attr`)
if len(attr) < 2 {
return c.NoContent(400)
}
if len(attr) == 2 {
attr = strings.ToUpper(attr[:2])
} else {
attr = strings.ToUpper(attr[:2]) + strings.ToLower(attr[2:])
}
date, err := time.Parse(time.RFC3339, c.Param(`date`))
if err != nil {
return c.NoContent(400)
}
data := app.GetAttribute(attr, date)
if data == nil {
return c.NoContent(404)
}
return c.JSON(200, data)
}

20
server/panic.go Normal file
View File

@ -0,0 +1,20 @@
package main
import (
"git.fuyu.moe/Fuyu/flog"
"github.com/labstack/echo"
)
func recoverMiddleware(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
defer func() {
v := recover()
if v != nil {
flog.Critical(`panic: `, v)
_ = c.JSON(500, `Fatal error occurred`)
}
}()
return next(c)
}
}