From cedd0d1d28583dce005c106cd29100bce8ec6632 Mon Sep 17 00:00:00 2001 From: Gisle Aune Date: Sat, 12 Feb 2022 11:36:15 +0100 Subject: [PATCH] add support for invoking and assigning scenes by name. --- app/api/devices.go | 28 +++++++++++++++++++++------- app/api/scenes.go | 16 ++++++++++++++-- cmd/lucy/scenecmd.go | 17 ++++++++++++----- internal/drivers/hue/driver.go | 4 ++-- internal/mysql/scenerepo.go | 10 ++++++++++ models/scene.go | 2 ++ 6 files changed, 61 insertions(+), 16 deletions(-) diff --git a/app/api/devices.go b/app/api/devices.go index 9662934..afba0c6 100644 --- a/app/api/devices.go +++ b/app/api/devices.go @@ -218,14 +218,28 @@ func Devices(r gin.IRoutes) { return []models.Device{}, nil } - _, err = config.SceneRepository().Find(ctxOf(c), body.SceneID) - if err != nil { - return nil, err - } - if body.DurationMS < 0 { - body.DurationMS = 0 + var scene *models.Scene + if body.SceneName != "" { + scene, err = config.SceneRepository().FindName(ctxOf(c), body.SceneName) + if err != nil { + return nil, err + } + if body.DurationMS < 0 { + body.DurationMS = 0 + } + body.StartTime = time.Now() + body.SceneID = scene.ID + } else { + scene, err = config.SceneRepository().Find(ctxOf(c), body.SceneID) + if err != nil { + return nil, err + } + if body.DurationMS < 0 { + body.DurationMS = 0 + } + body.StartTime = time.Now() + body.SceneName = scene.Name } - body.StartTime = time.Now() pushMode := c.Query("push") == "true" for i := range devices { diff --git a/app/api/scenes.go b/app/api/scenes.go index 44c2f1f..9a00e65 100644 --- a/app/api/scenes.go +++ b/app/api/scenes.go @@ -5,15 +5,27 @@ import ( "git.aiterp.net/lucifer/new-server/app/services/publisher" "git.aiterp.net/lucifer/new-server/models" "github.com/gin-gonic/gin" + "regexp" ) func Scenes(r gin.IRoutes) { + nonNumericRegex := regexp.MustCompile("[a-zA-Z ]") + + findScene := func(c *gin.Context) (*models.Scene, error) { + param := c.Param("id") + if nonNumericRegex.MatchString(param) { + return config.SceneRepository().FindName(ctxOf(c), param) + } else { + return config.SceneRepository().Find(ctxOf(c), intParam(c, "id")) + } + } + r.GET("", handler(func(c *gin.Context) (interface{}, error) { return config.SceneRepository().FetchAll(ctxOf(c)) })) r.GET("/:id", handler(func(c *gin.Context) (interface{}, error) { - return config.SceneRepository().Find(ctxOf(c), intParam(c, "id")) + return findScene(c) })) r.POST("", handler(func(c *gin.Context) (interface{}, error) { @@ -45,7 +57,7 @@ func Scenes(r gin.IRoutes) { return nil, err } - scene, err := config.SceneRepository().Find(ctxOf(c), intParam(c, "id")) + scene, err := findScene(c) if err != nil { return nil, err } diff --git a/cmd/lucy/scenecmd.go b/cmd/lucy/scenecmd.go index 7ff4581..7096181 100644 --- a/cmd/lucy/scenecmd.go +++ b/cmd/lucy/scenecmd.go @@ -93,15 +93,22 @@ func sceneCmd( { fetch := cmd.Params.Get(0).String() id := cmd.Params.Get(1).Int() - if fetch == nil || id == nil { - log.Println("Usage: lucy scene assign ") + name := cmd.Params.Get(1).String() + if fetch == nil || (id == nil && name == nil) { + log.Println("Usage: lucy scene assign ") } - devices, err := c.AssignDevice(ctx, *fetch, cmd.Name == "push", models.DeviceSceneAssignment{ - SceneID: *id, + assignment := models.DeviceSceneAssignment{ Group: cmd.Params.Get("group").StringOr(*fetch), DurationMS: int64(cmd.Params.Get("duration").IntOr(0)), - }) + } + if id != nil { + assignment.SceneID = *id + } else { + assignment.SceneName = *name + } + + devices, err := c.AssignDevice(ctx, *fetch, cmd.Name == "push", assignment) if err != nil { log.Println("Could not assign devices:", err) return diff --git a/internal/drivers/hue/driver.go b/internal/drivers/hue/driver.go index 9da87cf..2f1df8e 100644 --- a/internal/drivers/hue/driver.go +++ b/internal/drivers/hue/driver.go @@ -322,8 +322,8 @@ func (d *Driver) Run(ctx context.Context, bridge models.Bridge, ch chan<- models return err } - fastTicker := time.NewTicker(time.Second / 10) - slowTicker := time.NewTicker(time.Second / 3) + fastTicker := time.NewTicker(time.Second / 5) + slowTicker := time.NewTicker(time.Second / 2) selectedTicker := fastTicker ticksUntilRefresh := 0 ticksSinceChange := 0 diff --git a/internal/mysql/scenerepo.go b/internal/mysql/scenerepo.go index b8db256..d54701b 100644 --- a/internal/mysql/scenerepo.go +++ b/internal/mysql/scenerepo.go @@ -29,6 +29,16 @@ func (r *SceneRepo) Find(ctx context.Context, id int) (*models.Scene, error) { return r.populateOne(&scene) } +func (r *SceneRepo) FindName(ctx context.Context, name string) (*models.Scene, error) { + var scene sceneRecord + err := r.DBX.GetContext(ctx, &scene, "SELECT * FROM scene WHERE name = ?", name) + if err != nil { + return nil, dbErr(err) + } + + return r.populateOne(&scene) +} + func (r *SceneRepo) FetchAll(ctx context.Context) ([]models.Scene, error) { scenes := make([]sceneRecord, 0, 8) err := r.DBX.SelectContext(ctx, &scenes, "SELECT * FROM scene") diff --git a/models/scene.go b/models/scene.go index 09cf68c..63d1dba 100644 --- a/models/scene.go +++ b/models/scene.go @@ -299,6 +299,7 @@ const ( // instance is created for the group. type DeviceSceneAssignment struct { SceneID int `json:"sceneId"` + SceneName string `json:"sceneName"` Group string `json:"group"` StartTime time.Time `json:"start"` DurationMS int64 `json:"durationMs"` @@ -306,6 +307,7 @@ type DeviceSceneAssignment struct { type SceneRepository interface { Find(ctx context.Context, id int) (*Scene, error) + FindName(ctx context.Context, name string) (*Scene, error) FetchAll(ctx context.Context) ([]Scene, error) Save(ctx context.Context, bridge *Scene) error Delete(ctx context.Context, bridge *Scene) error