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