more scene stuff. There's still no command and API to push scenes and unassign (aside from setting a temporary scene and waiting it out).
continuous-integration/drone/push Build is passing

This commit is contained in:
2021-10-05 20:11:53 +02:00
parent 07173e4e56
commit 1b7e495a59
14 changed files with 416 additions and 9 deletions
+32 -1
View File
@@ -2,6 +2,7 @@ package api
import (
"git.aiterp.net/lucifer/new-server/app/config"
"git.aiterp.net/lucifer/new-server/app/services/publisher"
"git.aiterp.net/lucifer/new-server/models"
"github.com/gin-gonic/gin"
)
@@ -32,6 +33,36 @@ func Scenes(r gin.IRoutes) {
return nil, err
}
publisher.Global().UpdateScene(body)
return body, nil
}))
}
r.PUT("/:id", handler(func(c *gin.Context) (interface{}, error) {
var body models.Scene
err := parseBody(c, &body)
if err != nil {
return nil, err
}
scene, err := config.SceneRepository().Find(ctxOf(c), intParam(c, "id"))
if err != nil {
return nil, err
}
body.ID = scene.ID
err = body.Validate()
if err != nil {
return nil, err
}
err = config.SceneRepository().Save(ctxOf(c), &body)
if err != nil {
return nil, err
}
publisher.Global().UpdateScene(body)
return body, nil
}))
}
+10
View File
@@ -60,6 +60,16 @@ func (client *Client) PutDeviceTags(ctx context.Context, fetchStr string, addTag
return devices, nil
}
func (client *Client) AssignDevice(ctx context.Context, fetchStr string, assignment models.DeviceSceneAssignment) ([]models.Device, error) {
devices := make([]models.Device, 0, 16)
err := client.Fetch(ctx, "PUT", "/api/devices/"+fetchStr+"/scene", &devices, assignment)
if err != nil {
return nil, err
}
return devices, nil
}
func (client *Client) FireEvent(ctx context.Context, event models.Event) error {
err := client.Fetch(ctx, "POST", "/api/events", nil, event)
if err != nil {
+16
View File
@@ -0,0 +1,16 @@
package client
import (
"context"
"git.aiterp.net/lucifer/new-server/models"
)
func (client *Client) GetScenes(ctx context.Context) ([]models.Scene, error) {
scenes := make([]models.Scene, 0, 16)
err := client.Fetch(ctx, "GET", "/api/scenes", &scenes, nil)
if err != nil {
return nil, err
}
return scenes, nil
}
+25 -3
View File
@@ -19,6 +19,18 @@ type Publisher struct {
waiting map[int]chan struct{}
}
func (p *Publisher) UpdateScene(data models.Scene) {
p.mu.Lock()
p.sceneData[data.ID] = &data
for _, scene := range p.scenes {
if scene.data.ID == data.ID {
scene.UpdateScene(data)
}
}
p.mu.Unlock()
}
func (p *Publisher) ReloadScenes(ctx context.Context) error {
scenes, err := config.SceneRepository().FetchAll(ctx)
if err != nil {
@@ -26,8 +38,12 @@ func (p *Publisher) ReloadScenes(ctx context.Context) error {
}
p.mu.Lock()
for _, scene := range scenes {
p.sceneData[scene.ID] = &scene
for i, scene := range scenes {
p.sceneData[scene.ID] = &scenes[i]
}
for _, scene := range p.scenes {
scene.UpdateScene(*p.sceneData[scene.data.ID])
}
p.mu.Unlock()
@@ -90,10 +106,12 @@ func (p *Publisher) Run() {
p.mu.Lock()
for i, scene := range p.scenes {
if !scene.endTime.IsZero() && time.Now().After(scene.endTime) {
if (!scene.endTime.IsZero() && time.Now().After(scene.endTime)) || scene.Empty() {
deleteList = append(deleteList, i-len(deleteList))
updatedList = append(updatedList, scene.AllDevices()...)
log.Printf("Removing scene instance for %s (%d)", scene.data.Name, scene.data.ID)
for _, device := range scene.AllDevices() {
p.sceneAssignment[device.ID] = nil
}
@@ -258,6 +276,10 @@ var publisher = Publisher{
waiting: make(map[int]chan struct{}),
}
func Global() *Publisher {
return &publisher
}
func Initialize(ctx context.Context) error {
err :=publisher.ReloadScenes(ctx)
if err != nil {
+11
View File
@@ -86,6 +86,17 @@ func (s *Scene) RemoveDevice(device models.Device) {
delete(s.roleMap, device.ID)
}
func (s *Scene) Empty() bool {
for _, list := range s.roleList {
if len(list) > 0 {
return false
}
}
return true
}
func (s *Scene) Due() bool {
if s.due {
return true