Added go api

This commit is contained in:
Jake Hillion 2020-05-04 01:29:45 +01:00
parent 23fc55a003
commit a1f556194e
9 changed files with 213 additions and 21 deletions

59
go/api/api.go Normal file
View File

@ -0,0 +1,59 @@
package api
import (
"context"
"dancefloor/patterns"
"fmt"
"github.com/gin-gonic/gin"
"log"
"net/http"
"time"
)
var setter func(patterns.Pattern)
var router *gin.Engine
var stop = make(chan bool)
func init() {
router = gin.Default()
router.GET("/patterns", indexPatterns)
router.PUT("/patterns/:name", putPattern)
}
func Start(setPattern func(patterns.Pattern)) {
setter = setPattern
srv := &http.Server{
Addr: fmt.Sprintf(":%d", 3000),
Handler: router,
}
go func() {
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatalf("listen: %s\n", err)
}
}()
<-stop
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := srv.Shutdown(ctx); err != nil {
stop <- false
panic(err)
}
select {
case <-ctx.Done():
//warn
fmt.Println("timeout of 5 seconds")
}
stop <- true
}
func Stop() {
stop <- false
<-stop
}

58
go/api/patterns.go Normal file
View File

@ -0,0 +1,58 @@
package api
import (
"dancefloor/patterns"
"github.com/gin-gonic/gin"
"net/http"
"reflect"
)
var all = map[string]func() patterns.Pattern{
"SolidColour": func() patterns.Pattern { return &patterns.SolidColour{} },
"SuperRgb": func() patterns.Pattern { return &patterns.SuperRgb{} },
"Character": func() patterns.Pattern { return &patterns.Character{} },
"ScrollingText": func() patterns.Pattern { return &patterns.ScrollingText{} },
}
func indexPatterns(ctx *gin.Context) {
var out []map[string]string
for _, generator := range all {
fieldsMap := make(map[string]string)
pattern := generator()
patternType := reflect.TypeOf(pattern)
if patternType.Kind() == reflect.Ptr {
patternType = reflect.Indirect(reflect.ValueOf(pattern)).Type()
}
for i := 0; i < patternType.NumField(); i++ {
field := patternType.Field(i)
if field.PkgPath == "" { // if field is exported, this is empty
fieldsMap[field.Name] = field.Type.Name()
}
}
out = append(out, fieldsMap)
}
ctx.JSON(200, out)
}
func putPattern(ctx *gin.Context) {
query := ctx.Param("name")
generator, ok := all[query]
if !ok {
ctx.AbortWithStatus(http.StatusNotFound)
return
}
pattern := generator()
err := ctx.BindJSON(pattern)
if err != nil {
ctx.AbortWithStatus(http.StatusBadRequest)
return
}
setter(pattern)
ctx.Status(http.StatusNoContent)
}

View File

@ -1,3 +1,5 @@
module dancefloor module dancefloor
go 1.14 go 1.14
require github.com/gin-gonic/gin v1.6.3

View File

@ -0,0 +1,47 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14=
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY=
github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42 h1:vEOn+mP2zCOVzKckCZy6YsCtDblrpj/w7B9nxGNELpg=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

View File

@ -2,34 +2,54 @@ package main
import ( import (
"bytes" "bytes"
"dancefloor/api"
"dancefloor/patterns" "dancefloor/patterns"
"encoding/json" "encoding/json"
"fmt"
"net/http" "net/http"
"os"
"strconv"
"sync" "sync"
"time"
) )
var client http.Client var client http.Client
var lock sync.Mutex var lock sync.Mutex
var pattern Pattern var pattern patterns.Pattern
var address string
var width, height int var width, height int
func main() { func main() {
var err error
address = os.Getenv("ADDRESS")
if address == "" {
fmt.Println("no address provided")
os.Exit(1)
return
}
width, err = strconv.Atoi(os.Getenv("WIDTH"))
if err != nil {
width = 6 width = 6
err = nil
}
height, err = strconv.Atoi(os.Getenv("HEIGHT"))
if err != nil {
height = 5 height = 5
err = nil
}
SetPattern(&patterns.SuperRgb{Brightness: 128})
go api.Start(SetPattern)
defer api.Stop()
go drawLoop() go drawLoop()
SetPattern(&patterns.ScrollingText{Text: "Jake is the best!", Colour: [3]uint8{0, 0, 255}, Background: [3]uint8{24, 24, 24}})
select {} select {}
} }
type Pattern interface { func SetPattern(new patterns.Pattern) {
Draw(width, height int) *[][]patterns.Colour
}
func SetPattern(new Pattern) {
lock.Lock() lock.Lock()
defer lock.Unlock() defer lock.Unlock()
pattern = new pattern = new
@ -52,7 +72,7 @@ func render(data *[][]patterns.Colour) {
panic(err) panic(err)
} }
req, err := http.NewRequest("PUT", "http://10.10.0.26:5000/update", bytes.NewReader(content)) req, err := http.NewRequest("PUT", fmt.Sprintf("http://%s:5000/update", address), bytes.NewReader(content))
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -60,7 +80,8 @@ func render(data *[][]patterns.Colour) {
_, err = client.Do(req) _, err = client.Do(req)
if err != nil { if err != nil {
panic(err) fmt.Println("render request failed")
time.Sleep(time.Second)
} }
} }

View File

@ -1,3 +1,7 @@
package patterns package patterns
type Colour [3]uint8 type Colour [3]uint8
type Pattern interface {
Draw(width, height int) *[][]Colour
}

View File

@ -1,9 +1,9 @@
package patterns package patterns
type ScrollingText struct { type ScrollingText struct {
Text string Text string `binding:"required"`
Colour Colour Foreground Colour `binding:"required_without=Background"`
Background Colour Background Colour `binding:"required_without=Foreground"`
initiated bool initiated bool
fullRender [][]Colour fullRender [][]Colour
@ -36,7 +36,7 @@ func (s *ScrollingText) init(width, height int) {
var c rune var c rune
for _, c = range s.Text { for _, c = range s.Text {
subpattern := Character{Character: c, Colour: s.Colour, Background: s.Background} subpattern := Character{Character: c, Colour: s.Foreground, Background: s.Background}
drawnSubpattern := subpattern.Draw(0, height) drawnSubpattern := subpattern.Draw(0, height)
for _, v := range *drawnSubpattern { for _, v := range *drawnSubpattern {
s.fullRender = append(s.fullRender, v) s.fullRender = append(s.fullRender, v)

View File

@ -1,13 +1,13 @@
package patterns package patterns
type SolidColour struct { type SolidColour struct {
Colour Colour Colour
} }
func (p *SolidColour) Draw(width, height int) *[][][3]uint8 { func (p *SolidColour) Draw(width, height int) *[][]Colour {
out := make([][][3]uint8, width) out := make([][]Colour, width)
for i := 0; i < width; i++ { for i := 0; i < width; i++ {
out[i] = make([][3]uint8, height) out[i] = make([]Colour, height)
for j := 0; j < height; j++ { for j := 0; j < height; j++ {
out[i][j] = p.Colour out[i][j] = p.Colour
} }

View File

@ -2,6 +2,7 @@ package patterns
type SuperRgb struct { type SuperRgb struct {
Brightness uint8 Brightness uint8
iteration int iteration int
} }