gyrogpsc/web/http.go
2020-12-13 03:23:18 +01:00

235 lines
6.4 KiB
Go

package web
import (
"git.timovolkmann.de/gyrogpsc/core"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/template/html"
"github.com/gofiber/websocket/v2"
"github.com/sirupsen/logrus"
)
func CreateServer(s core.Service, sub core.Subscriber, c *core.Configuration) {
app := fiber.New(fiber.Config{
Views: fiberTemplateEngine(c),
})
app.Static("/static", "static")
// Application Main Page
app.Get("/", fiberHomeHandler)
// Websocket
app.Get("/ws", websocket.New(createFiberWebsocketHandler(sub)))
// TODO: Get all SerialPorts
// app.Get("/serialports")
// Tracking persistence controls HTTP JSON RPC API
trackings := app.Group("/trackings")
trackings.Get("/", allTrackingsHandler(s, c)) // Get all trackings Metadata
trackings.Post("/", startPipelineHandler(s, c)) // Initialize new tracking, open websocket and prepare for automatic recording. Toggle ?serial=true and ?tcp=true. Returns trackingId
trackings.Patch("/", startRecordingHandler(s, c)) // Starts recording
trackings.Put("/", stopRecordingHandler(s, c)) // Stops current recording. Returns trackingId if record was successful
trackings.Delete("/", stopAllHandler(s, c)) // Stops websocket connection, pipelines and collectors
trackings.Get("/:trackingId", stubhander()) // Gets Tracking Metadata and loads sensorRecords from storage.
trackings.Delete("/:trackingId", stubhander()) // Deletes Tracking from storage
trackings.Post("/current", stubhander()) // Starts Replay.
trackings.Patch("/current", stubhander()) // Pauses Replay.
trackings.Put("/current", stubhander()) // Stops Replay.
logrus.Fatal(app.Listen(c.Webserver.Port))
}
func stubhander() fiber.Handler {
return func(ctx *fiber.Ctx) error {
return nil
}
}
func allTrackingsHandler(s core.Service, c *core.Configuration) fiber.Handler {
return func(ctx *fiber.Ctx) error {
trackings, err := s.AllTrackings()
if err != nil {
//ctx.Status(500).JSON(err)
//return err
}
prepres := map[string]interface{}{}
prepres["data"] = trackings
if err != nil {
prepres["error"] = err.Error()
}
err2 := ctx.JSON(prepres)
if err2 != nil {
ctx.Status(500).JSON(err2)
return err2
}
return nil
}
}
func startPipelineHandler(s core.Service, c *core.Configuration) fiber.Handler {
return func(ctx *fiber.Ctx) error {
var collecs []core.CollectorType
ser := ctx.Params("serial", "true")
if ser == "true" {
collecs = append(collecs, core.SERIAL)
} else if ser != "false" && ser != "" {
collecs = append(collecs, core.CollectorType(ser)) // TODO: allow passing serial port as url parameter
}
tcp := ctx.Params("tcp", "true")
if tcp == "true" {
collecs = append(collecs, core.TCP)
}
res, err := s.StartPipeline(collecs...)
if err != nil {
//ctx.Status(500).JSON(err)
//return err
}
prepres := map[string]interface{}{}
prepres["tracking_state"] = res
//prepres["data"] = res
if err != nil {
prepres["error"] = err.Error()
}
err2 := ctx.JSON(prepres)
if err2 != nil {
ctx.Status(500).JSON(err2)
return err2
}
return nil
}
}
func startRecordingHandler(s core.Service, c *core.Configuration) fiber.Handler {
return func(ctx *fiber.Ctx) error {
rec, err := s.StartRecord()
if err != nil {
//ctx.Status(500).JSON(err)
//return err
}
prepres := map[string]interface{}{}
prepres["tracking_state"] = "RECORD"
prepres["data"] = rec
if err != nil {
prepres["error"] = err.Error()
}
err2 := ctx.JSON(prepres)
if err2 != nil {
ctx.Status(500).JSON(err2)
return err2
}
return nil
}
}
func stopRecordingHandler(s core.Service, c *core.Configuration) fiber.Handler {
return func(ctx *fiber.Ctx) error {
rec, err := s.StopRecord()
if err != nil {
//ctx.Status(500).JSON(err)
//return err
}
prepres := map[string]interface{}{}
prepres["tracking_state"] = "LIVE"
prepres["data"] = rec
if err != nil {
prepres["error"] = err.Error()
}
err2 := ctx.JSON(prepres)
if err2 != nil {
ctx.Status(500).JSON(err2)
return err2
}
return nil
}
}
func stopAllHandler(s core.Service, c *core.Configuration) fiber.Handler {
return func(ctx *fiber.Ctx) error {
rec, err := s.StopAll()
if err != nil {
//ctx.Status(500).JSON(err)
//return err
}
prepres := map[string]interface{}{}
prepres["tracking_state"] = "STOPPED"
prepres["data"] = rec
if err != nil {
prepres["error"] = err.Error()
}
err2 := ctx.JSON(prepres)
if err2 != nil {
ctx.Status(500).JSON(err2)
return err2
}
return nil
}
}
func createFiberWebsocketHandler(s core.Subscriber) func(conn *websocket.Conn) {
return func(c *websocket.Conn) {
logrus.Info("new websocket client")
// Handle and discard inbound messages
go func() {
for {
if _, _, err := c.NextReader(); err != nil {
c.Close()
break
}
}
}()
dispatcherId, channel := s.Subscribe()
defer s.Unsubscribe(dispatcherId)
for {
cmsg := <-channel
err := c.WriteMessage(websocket.TextMessage, []byte(cmsg))
if err != nil {
logrus.Info("close websocket connection")
c.Close()
break
}
}
}
}
func fiberTemplateEngine(c *core.Configuration) *html.Engine {
// Create a new engine by passing the template folder
// and template extension using <engine>.New(dir, ext string)
engine := html.New("./templates", ".html")
// We also support the http.FileSystem interface
// See examples below to load templates from embedded files
// engine := html.NewFileSystem(http.Dir("./views"), ".html")
// Reload the templates on each render, good for development
//engine.Reload(strings.ToLower(c.Debuglevel) == "debug") // Optional. Default: false
engine.Reload(true) // Optional. Default: false
// Debug will print each template that is parsed, good for debugging
//engine.Debug(strings.ToLower(c.Debuglevel) == "debug") // Optional. Default: false
engine.Debug(true) // Optional. Default: false
// Layout defines the variable name that is used to yield templates within layouts
//engine.Layout("embed") // Optional. Default: "embed"
// Delims sets the action delimiters to the specified strings
//engine.Delims("{{", "}}") // Optional. Default: engine delimiters
// AddFunc adds a function to the template's global function map.
//engine.AddFunc("greet", func(name string) string {
// return "Hello, " + name + "!"
//})
return engine
}
func fiberHomeHandler(c *fiber.Ctx) error {
// Render index template
return c.Render("index", "ws://"+c.Hostname()+"/ws")
}