Gisle Aune
3 years ago
15 changed files with 763 additions and 143 deletions
-
60app/api/devices.go
-
37app/api/scenes.go
-
5app/config/db.go
-
4app/config/repo.go
-
5app/server.go
-
23app/services/events.go
-
5app/services/publish.go
-
212app/services/scene/manager.go
-
126app/services/scene/scene.go
-
28internal/mysql/devicerepo.go
-
118internal/mysql/scenerepo.go
-
2models/device.go
-
57models/scene.go
-
17scripts/20210926135923_scene.sql
-
9scripts/20210926152011_device_sceneassignment.sql
@ -0,0 +1,37 @@ |
|||
package api |
|||
|
|||
import ( |
|||
"git.aiterp.net/lucifer/new-server/app/config" |
|||
"git.aiterp.net/lucifer/new-server/models" |
|||
"github.com/gin-gonic/gin" |
|||
) |
|||
|
|||
func Scenes(r gin.IRoutes) { |
|||
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")) |
|||
})) |
|||
|
|||
r.POST("", handler(func(c *gin.Context) (interface{}, error) { |
|||
var body models.Scene |
|||
err := parseBody(c, &body) |
|||
if err != nil { |
|||
return nil, err |
|||
} |
|||
|
|||
err = body.Validate() |
|||
if err != nil { |
|||
return nil, err |
|||
} |
|||
|
|||
err = config.SceneRepository().Save(ctxOf(c), &body) |
|||
if err != nil { |
|||
return nil, err |
|||
} |
|||
|
|||
return body, nil |
|||
})) |
|||
} |
@ -0,0 +1,118 @@ |
|||
package mysql |
|||
|
|||
import ( |
|||
"context" |
|||
"encoding/json" |
|||
"git.aiterp.net/lucifer/new-server/models" |
|||
"github.com/jmoiron/sqlx" |
|||
) |
|||
|
|||
type sceneRecord struct { |
|||
ID int `db:"id"` |
|||
Name string `db:"name"` |
|||
IntervalMS int64 `db:"interval_ms"` |
|||
RoleJSON json.RawMessage `db:"roles"` |
|||
} |
|||
|
|||
type SceneRepo struct { |
|||
DBX *sqlx.DB |
|||
} |
|||
|
|||
func (r *SceneRepo) Find(ctx context.Context, id int) (*models.Scene, error) { |
|||
var scene sceneRecord |
|||
err := r.DBX.GetContext(ctx, &scene, "SELECT * FROM scene WHERE id = ?", id) |
|||
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") |
|||
if err != nil { |
|||
return nil, dbErr(err) |
|||
} |
|||
|
|||
return r.populate(scenes) |
|||
} |
|||
|
|||
func (r *SceneRepo) Save(ctx context.Context, scene *models.Scene) error { |
|||
j, err := json.Marshal(scene.Roles) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
|
|||
if scene.ID > 0 { |
|||
_, err := r.DBX.ExecContext( |
|||
ctx, |
|||
"UPDATE scene SET name = ?, interval_ms = ?, roles = ? WHERE id = ?", |
|||
scene.Name, scene.IntervalMS, j, scene.ID, |
|||
) |
|||
|
|||
if err != nil { |
|||
return dbErr(err) |
|||
} |
|||
} else { |
|||
rs, err := r.DBX.ExecContext( |
|||
ctx, |
|||
"INSERT INTO scene (name, interval_ms, roles) VALUES (?, ?, ?)", |
|||
scene.Name, scene.IntervalMS, j, |
|||
) |
|||
|
|||
if err != nil { |
|||
return dbErr(err) |
|||
} |
|||
|
|||
id, err := rs.LastInsertId() |
|||
if err != nil { |
|||
return dbErr(err) |
|||
} |
|||
|
|||
scene.ID = int(id) |
|||
} |
|||
|
|||
return nil |
|||
} |
|||
|
|||
func (r *SceneRepo) Delete(ctx context.Context, scene *models.Scene) error { |
|||
_, err := r.DBX.ExecContext(ctx, "DELETE FROM scene WHERE id = ?", scene.ID) |
|||
if err != nil { |
|||
return dbErr(err) |
|||
} |
|||
|
|||
scene.ID = 0 |
|||
return nil |
|||
} |
|||
|
|||
func (r *SceneRepo) populateOne(record *sceneRecord) (*models.Scene, error) { |
|||
records, err := r.populate([]sceneRecord{*record}) |
|||
if err != nil { |
|||
return nil, err |
|||
} |
|||
|
|||
return &records[0], nil |
|||
} |
|||
|
|||
func (r *SceneRepo) populate(records []sceneRecord) ([]models.Scene, error) { |
|||
res := make([]models.Scene, 0, len(records)) |
|||
|
|||
for _, record := range records { |
|||
scene := models.Scene{ |
|||
ID: record.ID, |
|||
Name: record.Name, |
|||
IntervalMS: record.IntervalMS, |
|||
Roles: make([]models.SceneRole, 0, 8), |
|||
} |
|||
|
|||
err := json.Unmarshal(record.RoleJSON, &scene.Roles) |
|||
if err != nil { |
|||
return nil, dbErr(err) |
|||
} |
|||
|
|||
res = append(res, scene) |
|||
} |
|||
|
|||
return res, nil |
|||
} |
@ -0,0 +1,17 @@ |
|||
-- +goose Up |
|||
-- +goose StatementBegin |
|||
CREATE TABLE scene |
|||
( |
|||
id INT NOT NULL AUTO_INCREMENT, |
|||
name VARCHAR(255) NOT NULL, |
|||
interval_ms INT NOT NULL, |
|||
roles JSON NOT NULL, |
|||
|
|||
PRIMARY KEY (id) |
|||
); |
|||
-- +goose StatementEnd |
|||
|
|||
-- +goose Down |
|||
-- +goose StatementBegin |
|||
DROP TABLE scene; |
|||
-- +goose StatementEnd |
@ -0,0 +1,9 @@ |
|||
-- +goose Up |
|||
-- +goose StatementBegin |
|||
ALTER TABLE device ADD COLUMN scene_assignments JSON NOT NULL DEFAULT ('[]'); |
|||
-- +goose StatementEnd |
|||
|
|||
-- +goose Down |
|||
-- +goose StatementBegin |
|||
ALTER TABLE device DROP COLUMN IF EXISTS scene_assignments; |
|||
-- +goose StatementEnd |
Write
Preview
Loading…
Cancel
Save
Reference in new issue