Browse Source

color api

pull/1/head
Stian Fredrik Aune 4 years ago
parent
commit
f045bc0f4d
  1. 4
      app/api/bridges.go
  2. 83
      app/api/presets.go
  3. 4
      app/config/driver.go
  4. 9
      app/config/repo.go
  5. 1
      app/server.go
  6. 2
      cmd/bridgetest/main.go
  7. 2
      cmd/goose/main.go
  8. 10
      internal/drivers/provider.go
  9. 2
      internal/mysql/bridgerepo.go
  10. 99
      internal/mysql/presetrepo.go
  11. 26
      models/colorpreset.go
  12. 17
      scripts/20210523175111_color_preset.sql
  13. 11
      scripts/20210523175425_color_preset_name.sql

4
app/api/bridges.go

@ -12,6 +12,10 @@ func Bridges(r gin.IRoutes) {
return config.BridgeRepository().FetchAll(ctxOf(c)) return config.BridgeRepository().FetchAll(ctxOf(c))
})) }))
r.GET("/:id", handler(func(c *gin.Context) (interface{}, error) {
return config.BridgeRepository().Find(ctxOf(c), intParam(c, "id"))
}))
r.POST("", handler(func(c *gin.Context) (interface{}, error) { r.POST("", handler(func(c *gin.Context) (interface{}, error) {
var body struct { var body struct {
Driver models.DriverKind `json:"driver"` Driver models.DriverKind `json:"driver"`

83
app/api/presets.go

@ -0,0 +1,83 @@
package api
import (
"git.aiterp.net/lucifer/new-server/app/config"
"git.aiterp.net/lucifer/new-server/models"
"github.com/gin-gonic/gin"
)
func ColorPresets(r gin.IRoutes) {
r.GET("", handler(func(c *gin.Context) (interface{}, error) {
return config.ColorPresetRepository().FetchAll(ctxOf(c))
}))
r.GET("/:id", handler(func(c *gin.Context) (interface{}, error) {
return config.ColorPresetRepository().Find(ctxOf(c), intParam(c, "id"))
}))
r.POST("", handler(func(c *gin.Context) (interface{}, error) {
var body struct {
Name string `json:"name"`
ColorString string `json:"colorString"`
}
err := parseBody(c, &body)
if err != nil {
return nil, err
}
newColor, err := models.ParseColorValue(body.ColorString)
if err != nil {
return nil, err
}
preset := models.ColorPreset{
Name: body.Name,
Value: newColor,
}
preset.Validate()
err = config.ColorPresetRepository().Save(ctxOf(c), &preset)
if err != nil {
return nil, err
}
return preset, nil
}))
r.PUT("/:id", handler(func(c *gin.Context) (interface{}, error) {
var body struct {
Name *string `json:"name"`
ColorString *string `json:"colorString"`
}
err := parseBody(c, &body)
if err != nil {
return nil, err
}
preset, err := config.ColorPresetRepository().Find(ctxOf(c), intParam(c, "id"))
if err != nil {
return nil, err
}
if body.Name != nil {
preset.Name = *body.Name
}
if body.ColorString != nil {
newColor, err := models.ParseColorValue(*body.ColorString)
if err != nil {
return nil, err
}
preset.Value = newColor
}
preset.Validate()
err = config.ColorPresetRepository().Save(ctxOf(c), &preset)
if err != nil {
return nil, err
}
return preset, nil
}))
}

4
app/config/driver.go

@ -15,9 +15,9 @@ func DriverProvider() models.DriverProvider {
defer dpMutex.Unlock() defer dpMutex.Unlock()
if dp == nil { if dp == nil {
dp = &drivers.MapBasedDriverProvider{Data: map[models.DriverKind]models.Driver{
dp = drivers.DriverMap{
models.DTNanoLeaf: &nanoleaf.Driver{}, models.DTNanoLeaf: &nanoleaf.Driver{},
}}
}
} }
return dp return dp

9
app/config/repo.go

@ -7,6 +7,7 @@ import (
var ( var (
bRepo models.BridgeRepository bRepo models.BridgeRepository
cpRepo models.ColorPresetRepository
dRepo models.DeviceRepository dRepo models.DeviceRepository
ehRepo models.EventHandlerRepository ehRepo models.EventHandlerRepository
) )
@ -19,6 +20,14 @@ func BridgeRepository() models.BridgeRepository {
return bRepo return bRepo
} }
func ColorPresetRepository() models.ColorPresetRepository {
if cpRepo == nil {
cpRepo = &mysql.ColorPresetRepo{DBX: DBX()}
}
return cpRepo
}
func DeviceRepository() models.DeviceRepository { func DeviceRepository() models.DeviceRepository {
if dRepo == nil { if dRepo == nil {
panic("panik") panic("panik")

1
app/server.go

@ -17,6 +17,7 @@ func StartServer() {
apiGin := ginny.Group("/api") apiGin := ginny.Group("/api")
api.Bridges(apiGin.Group("/bridges")) api.Bridges(apiGin.Group("/bridges"))
api.ColorPresets(apiGin.Group("/color-presets"))
api.DriverKinds(apiGin.Group("/driver-kinds")) api.DriverKinds(apiGin.Group("/driver-kinds"))
api.Events(apiGin.Group("/events")) api.Events(apiGin.Group("/events"))

2
cmd/bridgetest/main.go

@ -65,7 +65,7 @@ func main() {
_ = driver.Publish(context.Background(), bridge, devices) _ = driver.Publish(context.Background(), bridge, devices)
ch := make(chan models.Event)
ch := config.EventChannel
go func() { go func() {
err := driver.Run(context.Background(), bridge, ch) err := driver.Run(context.Background(), bridge, ch)
if err != nil { if err != nil {

2
cmd/goose/main.go

@ -4,11 +4,13 @@ import (
"git.aiterp.net/lucifer/new-server/app/config" "git.aiterp.net/lucifer/new-server/app/config"
"github.com/pressly/goose" "github.com/pressly/goose"
"log" "log"
"time"
) )
func main() { func main() {
db := config.DBX().DB db := config.DBX().DB
log.Printf("Target version: %s",time.Now().Format("20060102150405"))
log.Printf("Database: %s:%d/%s", config.MySqlHost(), config.MySqlPort(), config.MySqlSchema()) log.Printf("Database: %s:%d/%s", config.MySqlHost(), config.MySqlPort(), config.MySqlSchema())
log.Printf("Authenticating as: %s", config.MySqlUsername()) log.Printf("Authenticating as: %s", config.MySqlUsername())

10
internal/drivers/provider.go

@ -2,15 +2,13 @@ package drivers
import "git.aiterp.net/lucifer/new-server/models" import "git.aiterp.net/lucifer/new-server/models"
type MapBasedDriverProvider struct {
Data map[models.DriverKind]models.Driver
}
type DriverMap map[models.DriverKind]models.Driver
func (m *MapBasedDriverProvider) Provide(kind models.DriverKind) (models.Driver, error) {
if m.Data[kind] == nil {
func (m DriverMap) Provide(kind models.DriverKind) (models.Driver, error) {
if m[kind] == nil {
return nil, models.ErrUnknownDriver return nil, models.ErrUnknownDriver
} }
return m.Data[kind], nil
return m[kind], nil
} }

2
internal/mysql/bridgerepo.go

@ -22,7 +22,7 @@ func (b *BridgeRepo) Find(ctx context.Context, id int) (models.Bridge, error) {
func (b *BridgeRepo) FetchAll(ctx context.Context) ([]models.Bridge, error) { func (b *BridgeRepo) FetchAll(ctx context.Context) ([]models.Bridge, error) {
bridges := make([]models.Bridge, 0, 8) bridges := make([]models.Bridge, 0, 8)
err := b.DBX.GetContext(ctx, bridges, "SELECT * FROM bridge")
err := b.DBX.GetContext(ctx, &bridges, "SELECT * FROM bridge")
if err != nil { if err != nil {
return nil, dbErr(err) return nil, dbErr(err)
} }

99
internal/mysql/presetrepo.go

@ -0,0 +1,99 @@
package mysql
import (
"context"
"git.aiterp.net/lucifer/new-server/models"
"github.com/jmoiron/sqlx"
)
type presetRecord struct {
ID int `db:"id"`
Name string `db:"name"`
Hue float64 `db:"hue"`
Saturation float64 `db:"saturation"`
Kelvin int `db:"kelvin"`
}
type ColorPresetRepo struct {
DBX *sqlx.DB
}
func (c *ColorPresetRepo) Find(ctx context.Context, id int) (models.ColorPreset, error) {
var record presetRecord
err := c.DBX.GetContext(ctx, &record, "SELECT * FROM color_preset WHERE id = ?", id)
if err != nil {
return models.ColorPreset{}, dbErr(err)
}
return c.fromRecords(record)[0], nil
}
func (c *ColorPresetRepo) FetchAll(ctx context.Context) ([]models.ColorPreset, error) {
records := make([]presetRecord, 0, 16)
err := c.DBX.SelectContext(ctx, &records, "SELECT * FROM color_preset")
if err != nil {
return nil, dbErr(err)
}
return c.fromRecords(records...), nil
}
func (c *ColorPresetRepo) Save(ctx context.Context, preset *models.ColorPreset) error {
if preset.ID > 0 {
_, err := c.DBX.ExecContext(
ctx,
"UPDATE color_preset SET name = ?, hue = ?, saturation = ?, kelvin = ? WHERE id = ?",
preset.Name, preset.Value.Hue, preset.Value.Saturation, preset.Value.Kelvin, preset.ID,
)
if err != nil {
return dbErr(err)
}
} else {
rs, err := c.DBX.ExecContext(
ctx,
"INSERT INTO color_preset (name, hue, saturation, kelvin) VALUES (?, ?, ?, ?)",
preset.Name, preset.Value.Hue, preset.Value.Saturation, preset.Value.Kelvin,
)
if err != nil {
return dbErr(err)
}
id, err := rs.LastInsertId()
if err != nil {
return dbErr(err)
}
preset.ID = int(id)
}
return nil
}
func (c *ColorPresetRepo) Delete(ctx context.Context, preset *models.ColorPreset) error {
_, err := c.DBX.ExecContext(ctx, "DELETE FROM color_preset WHERE id = ?", preset.ID)
if err != nil {
return dbErr(err)
}
preset.ID = 0
return nil
}
func (c *ColorPresetRepo) fromRecords(records ...presetRecord) []models.ColorPreset {
newList := make([]models.ColorPreset, len(records), len(records))
for i, record := range records {
newList[i] = models.ColorPreset{
ID: record.ID,
Name: record.Name,
Value: models.ColorValue{
Hue: record.Hue,
Saturation: record.Saturation,
Kelvin: record.Kelvin,
},
}
}
return newList
}

26
models/colorpreset.go

@ -0,0 +1,26 @@
package models
import (
"context"
"strings"
)
type ColorPreset struct {
ID int `json:"id"`
Name string `json:"name"`
Value ColorValue `json:"value"`
}
type ColorPresetRepository interface {
Find(ctx context.Context, id int) (ColorPreset, error)
FetchAll(ctx context.Context) ([]ColorPreset, error)
Save(ctx context.Context, preset *ColorPreset) error
Delete(ctx context.Context, preset *ColorPreset) error
}
func (c *ColorPreset) Validate() {
c.Name = strings.Trim(c.Name, " \t\n")
if len(c.Name) == 0 {
c.Name = c.Value.String()
}
}

17
scripts/20210523175111_color_preset.sql

@ -0,0 +1,17 @@
-- +goose Up
-- +goose StatementBegin
CREATE TABLE color_preset
(
id INT NOT NULL AUTO_INCREMENT,
hue DOUBLE NOT NULL,
saturation DOUBLE NOT NULL,
kelvin INT NOT NULL,
PRIMARY KEY (id)
);
-- +goose StatementEnd
-- +goose Down
-- +goose StatementBegin
DROP TABLE color_preset;
-- +goose StatementEnd

11
scripts/20210523175425_color_preset_name.sql

@ -0,0 +1,11 @@
-- +goose Up
-- +goose StatementBegin
ALTER TABLE color_preset
ADD COLUMN name VARCHAR(255) NOT NULL DEFAULT 'Unnamed';
-- +goose StatementEnd
-- +goose Down
-- +goose StatementBegin
ALTER TABLE color_preset
DROP COLUMN name;
-- +goose StatementEnd
Loading…
Cancel
Save