Gisle Aune
2 years ago
27 changed files with 1336 additions and 35 deletions
-
6bus.go
-
24cmd/lucifer4-color/main.go
-
8commands/assign.go
-
8commands/device.go
-
33device/pointer.go
-
2effects/serializable.go
-
21events/alias.go
-
34events/assignment.go
-
21events/device.go
-
2events/log.go
-
7events/program.go
-
9go.mod
-
4go.sum
-
47services/effectenforcer.go
-
21services/hue/bridge.go
-
16services/mysqldb/migrations/20221229182826_device_hwstate.sql
-
15services/mysqldb/migrations/20221229213541_device_assignment.sql
-
14services/mysqldb/migrations/20221230104518_device_auth.sql
-
15services/mysqldb/migrations/20221231155702_device_alias.sql
-
238services/mysqldb/mysqlgen/db.go
-
301services/mysqldb/mysqlgen/device.sql.go
-
36services/mysqldb/mysqlgen/models.go
-
74services/mysqldb/queries/device.sql
-
321services/mysqldb/service.go
-
36services/mysqldb/sqltypes/nullrawmessage.go
-
30services/resolver.go
-
28sqlc.yaml
@ -0,0 +1,24 @@ |
|||||
|
package main |
||||
|
|
||||
|
import ( |
||||
|
"fmt" |
||||
|
"git.aiterp.net/lucifer3/server/internal/color" |
||||
|
"os" |
||||
|
) |
||||
|
|
||||
|
func main() { |
||||
|
col := color.MustParse(os.Args[len(os.Args)-1]) |
||||
|
|
||||
|
if col, ok := col.ToXY(); ok { |
||||
|
fmt.Println(col.String()) |
||||
|
} |
||||
|
if col, ok := col.ToHS(); ok { |
||||
|
fmt.Println(col.String()) |
||||
|
} |
||||
|
if col, ok := col.ToHSK(); ok { |
||||
|
fmt.Println(col.String()) |
||||
|
} |
||||
|
if col, ok := col.ToRGB(); ok { |
||||
|
fmt.Println(col.String()) |
||||
|
} |
||||
|
} |
@ -0,0 +1,21 @@ |
|||||
|
package events |
||||
|
|
||||
|
import "fmt" |
||||
|
|
||||
|
type AliasAdded struct { |
||||
|
ID string |
||||
|
Alias string |
||||
|
} |
||||
|
|
||||
|
func (e AliasAdded) EventDescription() string { |
||||
|
return fmt.Sprintf("AliasAdded(id=%s, alias=%s)", e.ID, e.Alias) |
||||
|
} |
||||
|
|
||||
|
type AliasRemoved struct { |
||||
|
ID string |
||||
|
Alias string |
||||
|
} |
||||
|
|
||||
|
func (e AliasRemoved) EventDescription() string { |
||||
|
return fmt.Sprintf("AliasRemoved(id=%s, alias=%s)", e.ID, e.Alias) |
||||
|
} |
@ -0,0 +1,34 @@ |
|||||
|
package events |
||||
|
|
||||
|
import ( |
||||
|
"fmt" |
||||
|
lucifer3 "git.aiterp.net/lucifer3/server" |
||||
|
"github.com/google/uuid" |
||||
|
) |
||||
|
|
||||
|
type AssignmentCreated struct { |
||||
|
ID uuid.UUID |
||||
|
Match string |
||||
|
Effect lucifer3.Effect |
||||
|
} |
||||
|
|
||||
|
func (e AssignmentCreated) EventDescription() string { |
||||
|
return fmt.Sprintf("AssignmentCreated(id=%s, match=%s, effect=%s)", e.ID, e.Match, e.Effect.EffectDescription()) |
||||
|
} |
||||
|
|
||||
|
type AssignmentRemoved struct { |
||||
|
ID uuid.UUID |
||||
|
} |
||||
|
|
||||
|
func (e AssignmentRemoved) EventDescription() string { |
||||
|
return fmt.Sprintf("AssignmentRemoved(id=%s)", e.ID) |
||||
|
} |
||||
|
|
||||
|
type DeviceAssigned struct { |
||||
|
DeviceID string `json:"deviceId"` |
||||
|
AssignmentID *uuid.UUID `json:"assignmentId"` |
||||
|
} |
||||
|
|
||||
|
func (e DeviceAssigned) EventDescription() string { |
||||
|
return fmt.Sprintf("DeviceAssigned(device=%s, %s)", e.DeviceID, e.AssignmentID) |
||||
|
} |
@ -0,0 +1,7 @@ |
|||||
|
package events |
||||
|
|
||||
|
type Started struct{} |
||||
|
|
||||
|
func (Started) EventDescription() string { |
||||
|
return "Started()" |
||||
|
} |
@ -1,5 +1,9 @@ |
|||||
|
github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc= |
||||
|
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= |
||||
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= |
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= |
||||
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= |
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= |
||||
|
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= |
||||
|
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= |
||||
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= |
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= |
||||
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= |
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= |
||||
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= |
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= |
||||
|
@ -0,0 +1,16 @@ |
|||||
|
-- +goose Up |
||||
|
-- +goose StatementBegin |
||||
|
CREATE TABLE device_info |
||||
|
( |
||||
|
id VARCHAR(255) NOT NULL, |
||||
|
kind VARCHAR(255) NOT NULL, |
||||
|
data JSON NOT NULL, |
||||
|
|
||||
|
PRIMARY KEY (id, kind) |
||||
|
); |
||||
|
-- +goose StatementEnd |
||||
|
|
||||
|
-- +goose Down |
||||
|
-- +goose StatementBegin |
||||
|
DROP TABLE device_info; |
||||
|
-- +goose StatementEnd |
@ -0,0 +1,15 @@ |
|||||
|
-- +goose Up |
||||
|
-- +goose StatementBegin |
||||
|
CREATE TABLE device_assignment |
||||
|
( |
||||
|
id CHAR(36) NOT NULL PRIMARY KEY, |
||||
|
created_date TIMESTAMP NOT NULL, |
||||
|
`match` TEXT NOT NULL, |
||||
|
effect JSON NOT NULL |
||||
|
); |
||||
|
-- +goose StatementEnd |
||||
|
|
||||
|
-- +goose Down |
||||
|
-- +goose StatementBegin |
||||
|
DROP TABLE device_assignment; |
||||
|
-- +goose StatementEnd |
@ -0,0 +1,14 @@ |
|||||
|
-- +goose Up |
||||
|
-- +goose StatementBegin |
||||
|
CREATE TABLE device_auth |
||||
|
( |
||||
|
id VARCHAR(255) NOT NULL PRIMARY KEY, |
||||
|
api_key TEXT NOT NULL, |
||||
|
extras JSON NOT NULL |
||||
|
); |
||||
|
-- +goose StatementEnd |
||||
|
|
||||
|
-- +goose Down |
||||
|
-- +goose StatementBegin |
||||
|
DROP TABLE device_auth; |
||||
|
-- +goose StatementEnd |
@ -0,0 +1,15 @@ |
|||||
|
-- +goose Up |
||||
|
-- +goose StatementBegin |
||||
|
CREATE TABLE device_alias |
||||
|
( |
||||
|
id VARCHAR(255) NOT NULL, |
||||
|
alias VARCHAR(1023) NOT NULL, |
||||
|
|
||||
|
PRIMARY KEY (id, alias) |
||||
|
); |
||||
|
-- +goose StatementEnd |
||||
|
|
||||
|
-- +goose Down |
||||
|
-- +goose StatementBegin |
||||
|
DROP TABLE device_alias; |
||||
|
-- +goose StatementEnd |
@ -0,0 +1,238 @@ |
|||||
|
// Code generated by sqlc. DO NOT EDIT.
|
||||
|
// versions:
|
||||
|
// sqlc v1.13.0
|
||||
|
|
||||
|
package mysqlgen |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
"database/sql" |
||||
|
"fmt" |
||||
|
) |
||||
|
|
||||
|
type DBTX interface { |
||||
|
ExecContext(context.Context, string, ...interface{}) (sql.Result, error) |
||||
|
PrepareContext(context.Context, string) (*sql.Stmt, error) |
||||
|
QueryContext(context.Context, string, ...interface{}) (*sql.Rows, error) |
||||
|
QueryRowContext(context.Context, string, ...interface{}) *sql.Row |
||||
|
} |
||||
|
|
||||
|
func New(db DBTX) *Queries { |
||||
|
return &Queries{db: db} |
||||
|
} |
||||
|
|
||||
|
func Prepare(ctx context.Context, db DBTX) (*Queries, error) { |
||||
|
q := Queries{db: db} |
||||
|
var err error |
||||
|
if q.deleteDeviceAliasStmt, err = db.PrepareContext(ctx, deleteDeviceAlias); err != nil { |
||||
|
return nil, fmt.Errorf("error preparing query DeleteDeviceAlias: %w", err) |
||||
|
} |
||||
|
if q.deleteDeviceAliasByIDStmt, err = db.PrepareContext(ctx, deleteDeviceAliasByID); err != nil { |
||||
|
return nil, fmt.Errorf("error preparing query DeleteDeviceAliasByID: %w", err) |
||||
|
} |
||||
|
if q.deleteDeviceAliasByIDLikeStmt, err = db.PrepareContext(ctx, deleteDeviceAliasByIDLike); err != nil { |
||||
|
return nil, fmt.Errorf("error preparing query DeleteDeviceAliasByIDLike: %w", err) |
||||
|
} |
||||
|
if q.deleteDeviceAssignmentStmt, err = db.PrepareContext(ctx, deleteDeviceAssignment); err != nil { |
||||
|
return nil, fmt.Errorf("error preparing query DeleteDeviceAssignment: %w", err) |
||||
|
} |
||||
|
if q.deleteDeviceAuthStmt, err = db.PrepareContext(ctx, deleteDeviceAuth); err != nil { |
||||
|
return nil, fmt.Errorf("error preparing query DeleteDeviceAuth: %w", err) |
||||
|
} |
||||
|
if q.deleteDeviceInfoStmt, err = db.PrepareContext(ctx, deleteDeviceInfo); err != nil { |
||||
|
return nil, fmt.Errorf("error preparing query DeleteDeviceInfo: %w", err) |
||||
|
} |
||||
|
if q.deleteDeviceInfoByIDStmt, err = db.PrepareContext(ctx, deleteDeviceInfoByID); err != nil { |
||||
|
return nil, fmt.Errorf("error preparing query DeleteDeviceInfoByID: %w", err) |
||||
|
} |
||||
|
if q.deleteDeviceInfoLikeStmt, err = db.PrepareContext(ctx, deleteDeviceInfoLike); err != nil { |
||||
|
return nil, fmt.Errorf("error preparing query DeleteDeviceInfoLike: %w", err) |
||||
|
} |
||||
|
if q.insertDeviceAliasStmt, err = db.PrepareContext(ctx, insertDeviceAlias); err != nil { |
||||
|
return nil, fmt.Errorf("error preparing query InsertDeviceAlias: %w", err) |
||||
|
} |
||||
|
if q.listDeviceAliasesStmt, err = db.PrepareContext(ctx, listDeviceAliases); err != nil { |
||||
|
return nil, fmt.Errorf("error preparing query ListDeviceAliases: %w", err) |
||||
|
} |
||||
|
if q.listDeviceAssignmentsStmt, err = db.PrepareContext(ctx, listDeviceAssignments); err != nil { |
||||
|
return nil, fmt.Errorf("error preparing query ListDeviceAssignments: %w", err) |
||||
|
} |
||||
|
if q.listDeviceAuthStmt, err = db.PrepareContext(ctx, listDeviceAuth); err != nil { |
||||
|
return nil, fmt.Errorf("error preparing query ListDeviceAuth: %w", err) |
||||
|
} |
||||
|
if q.listDeviceInfosStmt, err = db.PrepareContext(ctx, listDeviceInfos); err != nil { |
||||
|
return nil, fmt.Errorf("error preparing query ListDeviceInfos: %w", err) |
||||
|
} |
||||
|
if q.replaceDeviceAssignmentStmt, err = db.PrepareContext(ctx, replaceDeviceAssignment); err != nil { |
||||
|
return nil, fmt.Errorf("error preparing query ReplaceDeviceAssignment: %w", err) |
||||
|
} |
||||
|
if q.replaceDeviceAuthStmt, err = db.PrepareContext(ctx, replaceDeviceAuth); err != nil { |
||||
|
return nil, fmt.Errorf("error preparing query ReplaceDeviceAuth: %w", err) |
||||
|
} |
||||
|
if q.replaceDeviceInfoStmt, err = db.PrepareContext(ctx, replaceDeviceInfo); err != nil { |
||||
|
return nil, fmt.Errorf("error preparing query ReplaceDeviceInfo: %w", err) |
||||
|
} |
||||
|
return &q, nil |
||||
|
} |
||||
|
|
||||
|
func (q *Queries) Close() error { |
||||
|
var err error |
||||
|
if q.deleteDeviceAliasStmt != nil { |
||||
|
if cerr := q.deleteDeviceAliasStmt.Close(); cerr != nil { |
||||
|
err = fmt.Errorf("error closing deleteDeviceAliasStmt: %w", cerr) |
||||
|
} |
||||
|
} |
||||
|
if q.deleteDeviceAliasByIDStmt != nil { |
||||
|
if cerr := q.deleteDeviceAliasByIDStmt.Close(); cerr != nil { |
||||
|
err = fmt.Errorf("error closing deleteDeviceAliasByIDStmt: %w", cerr) |
||||
|
} |
||||
|
} |
||||
|
if q.deleteDeviceAliasByIDLikeStmt != nil { |
||||
|
if cerr := q.deleteDeviceAliasByIDLikeStmt.Close(); cerr != nil { |
||||
|
err = fmt.Errorf("error closing deleteDeviceAliasByIDLikeStmt: %w", cerr) |
||||
|
} |
||||
|
} |
||||
|
if q.deleteDeviceAssignmentStmt != nil { |
||||
|
if cerr := q.deleteDeviceAssignmentStmt.Close(); cerr != nil { |
||||
|
err = fmt.Errorf("error closing deleteDeviceAssignmentStmt: %w", cerr) |
||||
|
} |
||||
|
} |
||||
|
if q.deleteDeviceAuthStmt != nil { |
||||
|
if cerr := q.deleteDeviceAuthStmt.Close(); cerr != nil { |
||||
|
err = fmt.Errorf("error closing deleteDeviceAuthStmt: %w", cerr) |
||||
|
} |
||||
|
} |
||||
|
if q.deleteDeviceInfoStmt != nil { |
||||
|
if cerr := q.deleteDeviceInfoStmt.Close(); cerr != nil { |
||||
|
err = fmt.Errorf("error closing deleteDeviceInfoStmt: %w", cerr) |
||||
|
} |
||||
|
} |
||||
|
if q.deleteDeviceInfoByIDStmt != nil { |
||||
|
if cerr := q.deleteDeviceInfoByIDStmt.Close(); cerr != nil { |
||||
|
err = fmt.Errorf("error closing deleteDeviceInfoByIDStmt: %w", cerr) |
||||
|
} |
||||
|
} |
||||
|
if q.deleteDeviceInfoLikeStmt != nil { |
||||
|
if cerr := q.deleteDeviceInfoLikeStmt.Close(); cerr != nil { |
||||
|
err = fmt.Errorf("error closing deleteDeviceInfoLikeStmt: %w", cerr) |
||||
|
} |
||||
|
} |
||||
|
if q.insertDeviceAliasStmt != nil { |
||||
|
if cerr := q.insertDeviceAliasStmt.Close(); cerr != nil { |
||||
|
err = fmt.Errorf("error closing insertDeviceAliasStmt: %w", cerr) |
||||
|
} |
||||
|
} |
||||
|
if q.listDeviceAliasesStmt != nil { |
||||
|
if cerr := q.listDeviceAliasesStmt.Close(); cerr != nil { |
||||
|
err = fmt.Errorf("error closing listDeviceAliasesStmt: %w", cerr) |
||||
|
} |
||||
|
} |
||||
|
if q.listDeviceAssignmentsStmt != nil { |
||||
|
if cerr := q.listDeviceAssignmentsStmt.Close(); cerr != nil { |
||||
|
err = fmt.Errorf("error closing listDeviceAssignmentsStmt: %w", cerr) |
||||
|
} |
||||
|
} |
||||
|
if q.listDeviceAuthStmt != nil { |
||||
|
if cerr := q.listDeviceAuthStmt.Close(); cerr != nil { |
||||
|
err = fmt.Errorf("error closing listDeviceAuthStmt: %w", cerr) |
||||
|
} |
||||
|
} |
||||
|
if q.listDeviceInfosStmt != nil { |
||||
|
if cerr := q.listDeviceInfosStmt.Close(); cerr != nil { |
||||
|
err = fmt.Errorf("error closing listDeviceInfosStmt: %w", cerr) |
||||
|
} |
||||
|
} |
||||
|
if q.replaceDeviceAssignmentStmt != nil { |
||||
|
if cerr := q.replaceDeviceAssignmentStmt.Close(); cerr != nil { |
||||
|
err = fmt.Errorf("error closing replaceDeviceAssignmentStmt: %w", cerr) |
||||
|
} |
||||
|
} |
||||
|
if q.replaceDeviceAuthStmt != nil { |
||||
|
if cerr := q.replaceDeviceAuthStmt.Close(); cerr != nil { |
||||
|
err = fmt.Errorf("error closing replaceDeviceAuthStmt: %w", cerr) |
||||
|
} |
||||
|
} |
||||
|
if q.replaceDeviceInfoStmt != nil { |
||||
|
if cerr := q.replaceDeviceInfoStmt.Close(); cerr != nil { |
||||
|
err = fmt.Errorf("error closing replaceDeviceInfoStmt: %w", cerr) |
||||
|
} |
||||
|
} |
||||
|
return err |
||||
|
} |
||||
|
|
||||
|
func (q *Queries) exec(ctx context.Context, stmt *sql.Stmt, query string, args ...interface{}) (sql.Result, error) { |
||||
|
switch { |
||||
|
case stmt != nil && q.tx != nil: |
||||
|
return q.tx.StmtContext(ctx, stmt).ExecContext(ctx, args...) |
||||
|
case stmt != nil: |
||||
|
return stmt.ExecContext(ctx, args...) |
||||
|
default: |
||||
|
return q.db.ExecContext(ctx, query, args...) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
func (q *Queries) query(ctx context.Context, stmt *sql.Stmt, query string, args ...interface{}) (*sql.Rows, error) { |
||||
|
switch { |
||||
|
case stmt != nil && q.tx != nil: |
||||
|
return q.tx.StmtContext(ctx, stmt).QueryContext(ctx, args...) |
||||
|
case stmt != nil: |
||||
|
return stmt.QueryContext(ctx, args...) |
||||
|
default: |
||||
|
return q.db.QueryContext(ctx, query, args...) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
func (q *Queries) queryRow(ctx context.Context, stmt *sql.Stmt, query string, args ...interface{}) *sql.Row { |
||||
|
switch { |
||||
|
case stmt != nil && q.tx != nil: |
||||
|
return q.tx.StmtContext(ctx, stmt).QueryRowContext(ctx, args...) |
||||
|
case stmt != nil: |
||||
|
return stmt.QueryRowContext(ctx, args...) |
||||
|
default: |
||||
|
return q.db.QueryRowContext(ctx, query, args...) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
type Queries struct { |
||||
|
db DBTX |
||||
|
tx *sql.Tx |
||||
|
deleteDeviceAliasStmt *sql.Stmt |
||||
|
deleteDeviceAliasByIDStmt *sql.Stmt |
||||
|
deleteDeviceAliasByIDLikeStmt *sql.Stmt |
||||
|
deleteDeviceAssignmentStmt *sql.Stmt |
||||
|
deleteDeviceAuthStmt *sql.Stmt |
||||
|
deleteDeviceInfoStmt *sql.Stmt |
||||
|
deleteDeviceInfoByIDStmt *sql.Stmt |
||||
|
deleteDeviceInfoLikeStmt *sql.Stmt |
||||
|
insertDeviceAliasStmt *sql.Stmt |
||||
|
listDeviceAliasesStmt *sql.Stmt |
||||
|
listDeviceAssignmentsStmt *sql.Stmt |
||||
|
listDeviceAuthStmt *sql.Stmt |
||||
|
listDeviceInfosStmt *sql.Stmt |
||||
|
replaceDeviceAssignmentStmt *sql.Stmt |
||||
|
replaceDeviceAuthStmt *sql.Stmt |
||||
|
replaceDeviceInfoStmt *sql.Stmt |
||||
|
} |
||||
|
|
||||
|
func (q *Queries) WithTx(tx *sql.Tx) *Queries { |
||||
|
return &Queries{ |
||||
|
db: tx, |
||||
|
tx: tx, |
||||
|
deleteDeviceAliasStmt: q.deleteDeviceAliasStmt, |
||||
|
deleteDeviceAliasByIDStmt: q.deleteDeviceAliasByIDStmt, |
||||
|
deleteDeviceAliasByIDLikeStmt: q.deleteDeviceAliasByIDLikeStmt, |
||||
|
deleteDeviceAssignmentStmt: q.deleteDeviceAssignmentStmt, |
||||
|
deleteDeviceAuthStmt: q.deleteDeviceAuthStmt, |
||||
|
deleteDeviceInfoStmt: q.deleteDeviceInfoStmt, |
||||
|
deleteDeviceInfoByIDStmt: q.deleteDeviceInfoByIDStmt, |
||||
|
deleteDeviceInfoLikeStmt: q.deleteDeviceInfoLikeStmt, |
||||
|
insertDeviceAliasStmt: q.insertDeviceAliasStmt, |
||||
|
listDeviceAliasesStmt: q.listDeviceAliasesStmt, |
||||
|
listDeviceAssignmentsStmt: q.listDeviceAssignmentsStmt, |
||||
|
listDeviceAuthStmt: q.listDeviceAuthStmt, |
||||
|
listDeviceInfosStmt: q.listDeviceInfosStmt, |
||||
|
replaceDeviceAssignmentStmt: q.replaceDeviceAssignmentStmt, |
||||
|
replaceDeviceAuthStmt: q.replaceDeviceAuthStmt, |
||||
|
replaceDeviceInfoStmt: q.replaceDeviceInfoStmt, |
||||
|
} |
||||
|
} |
@ -0,0 +1,301 @@ |
|||||
|
// Code generated by sqlc. DO NOT EDIT.
|
||||
|
// versions:
|
||||
|
// sqlc v1.13.0
|
||||
|
// source: device.sql
|
||||
|
|
||||
|
package mysqlgen |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
"encoding/json" |
||||
|
"time" |
||||
|
|
||||
|
"github.com/google/uuid" |
||||
|
) |
||||
|
|
||||
|
const deleteDeviceAlias = `-- name: DeleteDeviceAlias :exec |
||||
|
DELETE |
||||
|
FROM device_alias |
||||
|
WHERE id = ? |
||||
|
AND alias = ? |
||||
|
` |
||||
|
|
||||
|
type DeleteDeviceAliasParams struct { |
||||
|
ID string |
||||
|
Alias string |
||||
|
} |
||||
|
|
||||
|
func (q *Queries) DeleteDeviceAlias(ctx context.Context, arg DeleteDeviceAliasParams) error { |
||||
|
_, err := q.exec(ctx, q.deleteDeviceAliasStmt, deleteDeviceAlias, arg.ID, arg.Alias) |
||||
|
return err |
||||
|
} |
||||
|
|
||||
|
const deleteDeviceAliasByID = `-- name: DeleteDeviceAliasByID :exec |
||||
|
DELETE |
||||
|
FROM device_alias |
||||
|
WHERE id = ? |
||||
|
` |
||||
|
|
||||
|
func (q *Queries) DeleteDeviceAliasByID(ctx context.Context, id string) error { |
||||
|
_, err := q.exec(ctx, q.deleteDeviceAliasByIDStmt, deleteDeviceAliasByID, id) |
||||
|
return err |
||||
|
} |
||||
|
|
||||
|
const deleteDeviceAliasByIDLike = `-- name: DeleteDeviceAliasByIDLike :exec |
||||
|
DELETE |
||||
|
FROM device_alias |
||||
|
WHERE id LIKE ? |
||||
|
` |
||||
|
|
||||
|
func (q *Queries) DeleteDeviceAliasByIDLike(ctx context.Context, id string) error { |
||||
|
_, err := q.exec(ctx, q.deleteDeviceAliasByIDLikeStmt, deleteDeviceAliasByIDLike, id) |
||||
|
return err |
||||
|
} |
||||
|
|
||||
|
const deleteDeviceAssignment = `-- name: DeleteDeviceAssignment :exec |
||||
|
DELETE |
||||
|
FROM device_assignment |
||||
|
WHERE id = ? |
||||
|
` |
||||
|
|
||||
|
func (q *Queries) DeleteDeviceAssignment(ctx context.Context, id uuid.UUID) error { |
||||
|
_, err := q.exec(ctx, q.deleteDeviceAssignmentStmt, deleteDeviceAssignment, id) |
||||
|
return err |
||||
|
} |
||||
|
|
||||
|
const deleteDeviceAuth = `-- name: DeleteDeviceAuth :exec |
||||
|
DELETE |
||||
|
FROM device_auth |
||||
|
WHERE id = ? |
||||
|
` |
||||
|
|
||||
|
func (q *Queries) DeleteDeviceAuth(ctx context.Context, id string) error { |
||||
|
_, err := q.exec(ctx, q.deleteDeviceAuthStmt, deleteDeviceAuth, id) |
||||
|
return err |
||||
|
} |
||||
|
|
||||
|
const deleteDeviceInfo = `-- name: DeleteDeviceInfo :exec |
||||
|
DELETE |
||||
|
FROM device_info |
||||
|
WHERE id = ? |
||||
|
AND kind = ? |
||||
|
` |
||||
|
|
||||
|
type DeleteDeviceInfoParams struct { |
||||
|
ID string |
||||
|
Kind string |
||||
|
} |
||||
|
|
||||
|
func (q *Queries) DeleteDeviceInfo(ctx context.Context, arg DeleteDeviceInfoParams) error { |
||||
|
_, err := q.exec(ctx, q.deleteDeviceInfoStmt, deleteDeviceInfo, arg.ID, arg.Kind) |
||||
|
return err |
||||
|
} |
||||
|
|
||||
|
const deleteDeviceInfoByID = `-- name: DeleteDeviceInfoByID :exec |
||||
|
DELETE |
||||
|
FROM device_info |
||||
|
WHERE id = ? |
||||
|
` |
||||
|
|
||||
|
func (q *Queries) DeleteDeviceInfoByID(ctx context.Context, id string) error { |
||||
|
_, err := q.exec(ctx, q.deleteDeviceInfoByIDStmt, deleteDeviceInfoByID, id) |
||||
|
return err |
||||
|
} |
||||
|
|
||||
|
const deleteDeviceInfoLike = `-- name: DeleteDeviceInfoLike :exec |
||||
|
DELETE |
||||
|
FROM device_info |
||||
|
WHERE id LIKE ? |
||||
|
` |
||||
|
|
||||
|
func (q *Queries) DeleteDeviceInfoLike(ctx context.Context, id string) error { |
||||
|
_, err := q.exec(ctx, q.deleteDeviceInfoLikeStmt, deleteDeviceInfoLike, id) |
||||
|
return err |
||||
|
} |
||||
|
|
||||
|
const insertDeviceAlias = `-- name: InsertDeviceAlias :exec |
||||
|
INSERT INTO device_alias (id, alias) |
||||
|
VALUES (?, ?) |
||||
|
` |
||||
|
|
||||
|
type InsertDeviceAliasParams struct { |
||||
|
ID string |
||||
|
Alias string |
||||
|
} |
||||
|
|
||||
|
func (q *Queries) InsertDeviceAlias(ctx context.Context, arg InsertDeviceAliasParams) error { |
||||
|
_, err := q.exec(ctx, q.insertDeviceAliasStmt, insertDeviceAlias, arg.ID, arg.Alias) |
||||
|
return err |
||||
|
} |
||||
|
|
||||
|
const listDeviceAliases = `-- name: ListDeviceAliases :many |
||||
|
SELECT id, alias |
||||
|
FROM device_alias |
||||
|
` |
||||
|
|
||||
|
func (q *Queries) ListDeviceAliases(ctx context.Context) ([]DeviceAlias, error) { |
||||
|
rows, err := q.query(ctx, q.listDeviceAliasesStmt, listDeviceAliases) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
defer rows.Close() |
||||
|
items := []DeviceAlias{} |
||||
|
for rows.Next() { |
||||
|
var i DeviceAlias |
||||
|
if err := rows.Scan(&i.ID, &i.Alias); err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
items = append(items, i) |
||||
|
} |
||||
|
if err := rows.Close(); err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
if err := rows.Err(); err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
return items, nil |
||||
|
} |
||||
|
|
||||
|
const listDeviceAssignments = `-- name: ListDeviceAssignments :many |
||||
|
SELECT id, created_date, ` + "`" + `match` + "`" + `, effect |
||||
|
FROM device_assignment |
||||
|
ORDER BY created_date |
||||
|
` |
||||
|
|
||||
|
func (q *Queries) ListDeviceAssignments(ctx context.Context) ([]DeviceAssignment, error) { |
||||
|
rows, err := q.query(ctx, q.listDeviceAssignmentsStmt, listDeviceAssignments) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
defer rows.Close() |
||||
|
items := []DeviceAssignment{} |
||||
|
for rows.Next() { |
||||
|
var i DeviceAssignment |
||||
|
if err := rows.Scan( |
||||
|
&i.ID, |
||||
|
&i.CreatedDate, |
||||
|
&i.Match, |
||||
|
&i.Effect, |
||||
|
); err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
items = append(items, i) |
||||
|
} |
||||
|
if err := rows.Close(); err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
if err := rows.Err(); err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
return items, nil |
||||
|
} |
||||
|
|
||||
|
const listDeviceAuth = `-- name: ListDeviceAuth :many |
||||
|
SELECT id, api_key, extras |
||||
|
FROM device_auth |
||||
|
` |
||||
|
|
||||
|
func (q *Queries) ListDeviceAuth(ctx context.Context) ([]DeviceAuth, error) { |
||||
|
rows, err := q.query(ctx, q.listDeviceAuthStmt, listDeviceAuth) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
defer rows.Close() |
||||
|
items := []DeviceAuth{} |
||||
|
for rows.Next() { |
||||
|
var i DeviceAuth |
||||
|
if err := rows.Scan(&i.ID, &i.ApiKey, &i.Extras); err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
items = append(items, i) |
||||
|
} |
||||
|
if err := rows.Close(); err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
if err := rows.Err(); err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
return items, nil |
||||
|
} |
||||
|
|
||||
|
const listDeviceInfos = `-- name: ListDeviceInfos :many |
||||
|
SELECT id, kind, data |
||||
|
FROM device_info |
||||
|
` |
||||
|
|
||||
|
func (q *Queries) ListDeviceInfos(ctx context.Context) ([]DeviceInfo, error) { |
||||
|
rows, err := q.query(ctx, q.listDeviceInfosStmt, listDeviceInfos) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
defer rows.Close() |
||||
|
items := []DeviceInfo{} |
||||
|
for rows.Next() { |
||||
|
var i DeviceInfo |
||||
|
if err := rows.Scan(&i.ID, &i.Kind, &i.Data); err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
items = append(items, i) |
||||
|
} |
||||
|
if err := rows.Close(); err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
if err := rows.Err(); err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
return items, nil |
||||
|
} |
||||
|
|
||||
|
const replaceDeviceAssignment = `-- name: ReplaceDeviceAssignment :exec |
||||
|
REPLACE INTO device_assignment (id, created_date, ` + "`" + `match` + "`" + `, effect) |
||||
|
VALUES (?, ?, ?, ?) |
||||
|
` |
||||
|
|
||||
|
type ReplaceDeviceAssignmentParams struct { |
||||
|
ID uuid.UUID |
||||
|
CreatedDate time.Time |
||||
|
Match string |
||||
|
Effect json.RawMessage |
||||
|
} |
||||
|
|
||||
|
func (q *Queries) ReplaceDeviceAssignment(ctx context.Context, arg ReplaceDeviceAssignmentParams) error { |
||||
|
_, err := q.exec(ctx, q.replaceDeviceAssignmentStmt, replaceDeviceAssignment, |
||||
|
arg.ID, |
||||
|
arg.CreatedDate, |
||||
|
arg.Match, |
||||
|
arg.Effect, |
||||
|
) |
||||
|
return err |
||||
|
} |
||||
|
|
||||
|
const replaceDeviceAuth = `-- name: ReplaceDeviceAuth :exec |
||||
|
REPLACE INTO device_auth (id, api_key, extras) |
||||
|
VALUES (?, ?, ?) |
||||
|
` |
||||
|
|
||||
|
type ReplaceDeviceAuthParams struct { |
||||
|
ID string |
||||
|
ApiKey string |
||||
|
Extras json.RawMessage |
||||
|
} |
||||
|
|
||||
|
func (q *Queries) ReplaceDeviceAuth(ctx context.Context, arg ReplaceDeviceAuthParams) error { |
||||
|
_, err := q.exec(ctx, q.replaceDeviceAuthStmt, replaceDeviceAuth, arg.ID, arg.ApiKey, arg.Extras) |
||||
|
return err |
||||
|
} |
||||
|
|
||||
|
const replaceDeviceInfo = `-- name: ReplaceDeviceInfo :exec |
||||
|
REPLACE INTO device_info (id, kind, data) |
||||
|
VALUES (?, ?, ?) |
||||
|
` |
||||
|
|
||||
|
type ReplaceDeviceInfoParams struct { |
||||
|
ID string |
||||
|
Kind string |
||||
|
Data json.RawMessage |
||||
|
} |
||||
|
|
||||
|
func (q *Queries) ReplaceDeviceInfo(ctx context.Context, arg ReplaceDeviceInfoParams) error { |
||||
|
_, err := q.exec(ctx, q.replaceDeviceInfoStmt, replaceDeviceInfo, arg.ID, arg.Kind, arg.Data) |
||||
|
return err |
||||
|
} |
@ -0,0 +1,36 @@ |
|||||
|
// Code generated by sqlc. DO NOT EDIT.
|
||||
|
// versions:
|
||||
|
// sqlc v1.13.0
|
||||
|
|
||||
|
package mysqlgen |
||||
|
|
||||
|
import ( |
||||
|
"encoding/json" |
||||
|
"time" |
||||
|
|
||||
|
"github.com/google/uuid" |
||||
|
) |
||||
|
|
||||
|
type DeviceAlias struct { |
||||
|
ID string |
||||
|
Alias string |
||||
|
} |
||||
|
|
||||
|
type DeviceAssignment struct { |
||||
|
ID uuid.UUID |
||||
|
CreatedDate time.Time |
||||
|
Match string |
||||
|
Effect json.RawMessage |
||||
|
} |
||||
|
|
||||
|
type DeviceAuth struct { |
||||
|
ID string |
||||
|
ApiKey string |
||||
|
Extras json.RawMessage |
||||
|
} |
||||
|
|
||||
|
type DeviceInfo struct { |
||||
|
ID string |
||||
|
Kind string |
||||
|
Data json.RawMessage |
||||
|
} |
@ -0,0 +1,74 @@ |
|||||
|
-- name: ListDeviceInfos :many |
||||
|
SELECT * |
||||
|
FROM device_info; |
||||
|
|
||||
|
-- name: ListDeviceAssignments :many |
||||
|
SELECT * |
||||
|
FROM device_assignment |
||||
|
ORDER BY created_date; |
||||
|
|
||||
|
-- name: ListDeviceAuth :many |
||||
|
SELECT * |
||||
|
FROM device_auth; |
||||
|
|
||||
|
-- name: ListDeviceAliases :many |
||||
|
SELECT * |
||||
|
FROM device_alias; |
||||
|
|
||||
|
-- name: InsertDeviceAlias :exec |
||||
|
INSERT INTO device_alias (id, alias) |
||||
|
VALUES (?, ?); |
||||
|
|
||||
|
-- name: ReplaceDeviceAuth :exec |
||||
|
REPLACE INTO device_auth (id, api_key, extras) |
||||
|
VALUES (?, ?, ?); |
||||
|
|
||||
|
-- name: ReplaceDeviceInfo :exec |
||||
|
REPLACE INTO device_info (id, kind, data) |
||||
|
VALUES (?, ?, ?); |
||||
|
|
||||
|
-- name: ReplaceDeviceAssignment :exec |
||||
|
REPLACE INTO device_assignment (id, created_date, `match`, effect) |
||||
|
VALUES (?, ?, ?, ?); |
||||
|
|
||||
|
-- name: DeleteDeviceInfo :exec |
||||
|
DELETE |
||||
|
FROM device_info |
||||
|
WHERE id = ? |
||||
|
AND kind = ?; |
||||
|
|
||||
|
-- name: DeleteDeviceInfoByID :exec |
||||
|
DELETE |
||||
|
FROM device_info |
||||
|
WHERE id = ?; |
||||
|
|
||||
|
-- name: DeleteDeviceInfoLike :exec |
||||
|
DELETE |
||||
|
FROM device_info |
||||
|
WHERE id LIKE ?; |
||||
|
|
||||
|
-- name: DeleteDeviceAssignment :exec |
||||
|
DELETE |
||||
|
FROM device_assignment |
||||
|
WHERE id = ?; |
||||
|
|
||||
|
-- name: DeleteDeviceAuth :exec |
||||
|
DELETE |
||||
|
FROM device_auth |
||||
|
WHERE id = ?; |
||||
|
|
||||
|
-- name: DeleteDeviceAlias :exec |
||||
|
DELETE |
||||
|
FROM device_alias |
||||
|
WHERE id = ? |
||||
|
AND alias = ?; |
||||
|
|
||||
|
-- name: DeleteDeviceAliasByID :exec |
||||
|
DELETE |
||||
|
FROM device_alias |
||||
|
WHERE id = ?; |
||||
|
|
||||
|
-- name: DeleteDeviceAliasByIDLike :exec |
||||
|
DELETE |
||||
|
FROM device_alias |
||||
|
WHERE id LIKE ?; |
@ -0,0 +1,321 @@ |
|||||
|
package mysqldb |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
"database/sql" |
||||
|
"encoding/json" |
||||
|
"fmt" |
||||
|
lucifer3 "git.aiterp.net/lucifer3/server" |
||||
|
"git.aiterp.net/lucifer3/server/commands" |
||||
|
"git.aiterp.net/lucifer3/server/effects" |
||||
|
"git.aiterp.net/lucifer3/server/events" |
||||
|
"git.aiterp.net/lucifer3/server/internal/gentools" |
||||
|
"git.aiterp.net/lucifer3/server/services/mysqldb/mysqlgen" |
||||
|
"time" |
||||
|
|
||||
|
_ "github.com/go-sql-driver/mysql" |
||||
|
) |
||||
|
|
||||
|
type database struct { |
||||
|
db *sql.DB |
||||
|
} |
||||
|
|
||||
|
func (d *database) Active() bool { |
||||
|
return true |
||||
|
} |
||||
|
|
||||
|
func (d *database) HandleEvent(bus *lucifer3.EventBus, event lucifer3.Event) { |
||||
|
q := mysqlgen.New(d.db) |
||||
|
timeout, cancel := context.WithTimeout(context.Background(), time.Second/2) |
||||
|
defer cancel() |
||||
|
|
||||
|
switch event := event.(type) { |
||||
|
case events.Started: |
||||
|
timeout, cancel := context.WithTimeout(context.Background(), time.Second*10) |
||||
|
defer cancel() |
||||
|
|
||||
|
// Fetch all aliases first
|
||||
|
aliases, err := q.ListDeviceAliases(timeout) |
||||
|
if err != nil { |
||||
|
bus.RunEvent(events.Log{ |
||||
|
Level: "error", |
||||
|
Code: "database_could_not_list_aliases", |
||||
|
Message: "Database could not list aliases: " + err.Error(), |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
auths, err := q.ListDeviceAuth(timeout) |
||||
|
if err != nil { |
||||
|
bus.RunEvent(events.Log{ |
||||
|
Level: "error", |
||||
|
Code: "database_could_not_list_device_infos", |
||||
|
Message: "Hardware State serialization failed: " + err.Error(), |
||||
|
}) |
||||
|
} |
||||
|
for _, auth := range auths { |
||||
|
bus.RunCommand(commands.ConnectDevice{ |
||||
|
ID: auth.ID, |
||||
|
APIKey: auth.ApiKey, |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
infos, err := q.ListDeviceInfos(timeout) |
||||
|
if err != nil { |
||||
|
bus.RunEvent(events.Log{ |
||||
|
Level: "error", |
||||
|
Code: "database_could_not_list_device_infos", |
||||
|
Message: "Hardware State serialization failed: " + err.Error(), |
||||
|
}) |
||||
|
} |
||||
|
for _, info := range infos { |
||||
|
switch info.Kind { |
||||
|
case "hardware_state": |
||||
|
staleEvent := events.HardwareState{} |
||||
|
err := json.Unmarshal(info.Data, &staleEvent) |
||||
|
if err == nil { |
||||
|
bus.RunEvent(staleEvent) |
||||
|
} |
||||
|
case "hardware_metadata": |
||||
|
staleEvent := events.HardwareMetadata{} |
||||
|
err := json.Unmarshal(info.Data, &staleEvent) |
||||
|
if err == nil { |
||||
|
bus.RunEvent(staleEvent) |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// Run the aliases now
|
||||
|
for _, alias := range aliases { |
||||
|
bus.RunCommand(commands.AddAlias{ |
||||
|
Match: alias.ID, |
||||
|
Alias: alias.Alias, |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
assignments, err := q.ListDeviceAssignments(timeout) |
||||
|
if err != nil { |
||||
|
bus.RunEvent(events.Log{ |
||||
|
Level: "error", |
||||
|
Code: "database_could_not_list_assignments", |
||||
|
Message: "Database could not list assignments: " + err.Error(), |
||||
|
}) |
||||
|
} |
||||
|
for _, ass := range assignments { |
||||
|
effect := effects.Serializable{} |
||||
|
err := json.Unmarshal(ass.Effect, &effect) |
||||
|
if err != nil { |
||||
|
bus.RunEvent(events.Log{ |
||||
|
Level: "error", |
||||
|
Code: "database_could_not_deserialize_effect", |
||||
|
Message: err.Error(), |
||||
|
}) |
||||
|
continue |
||||
|
} |
||||
|
|
||||
|
bus.RunCommand(commands.Assign{ |
||||
|
ID: gentools.ShallowCopy(&ass.ID), |
||||
|
Match: ass.Match, |
||||
|
Effect: effect.Effect, |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
case events.DeviceAccepted: |
||||
|
if event.Extras == nil { |
||||
|
event.Extras = map[string]string{} |
||||
|
} |
||||
|
|
||||
|
extras, err := json.Marshal(event.Extras) |
||||
|
if err != nil { |
||||
|
extras = []byte("{}") |
||||
|
} |
||||
|
|
||||
|
err = q.ReplaceDeviceAuth(timeout, mysqlgen.ReplaceDeviceAuthParams{ |
||||
|
ID: event.ID, |
||||
|
ApiKey: event.APIKey, |
||||
|
Extras: extras, |
||||
|
}) |
||||
|
if err != nil { |
||||
|
bus.RunEvent(events.Log{ |
||||
|
Level: "error", |
||||
|
Code: "database_could_not_save_device_auth", |
||||
|
Message: "Device auth save failed: " + err.Error(), |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
case events.HardwareState: |
||||
|
if event.Stale { |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
event.Stale = true |
||||
|
serialized, err := json.Marshal(event) |
||||
|
if err != nil { |
||||
|
bus.RunEvent(events.Log{ |
||||
|
Level: "error", |
||||
|
Code: "database_could_not_serialize_hardware_state", |
||||
|
Message: "Hardware State serialization failed: " + err.Error(), |
||||
|
}) |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
err = q.ReplaceDeviceInfo(timeout, mysqlgen.ReplaceDeviceInfoParams{ |
||||
|
ID: event.ID, |
||||
|
Kind: "hardware_state", |
||||
|
Data: serialized, |
||||
|
}) |
||||
|
if err != nil { |
||||
|
bus.RunEvent(events.Log{ |
||||
|
Level: "error", |
||||
|
Code: "database_could_not_save_hardware_state", |
||||
|
Message: err.Error(), |
||||
|
}) |
||||
|
|
||||
|
return |
||||
|
} |
||||
|
|
||||
|
case events.HardwareMetadata: |
||||
|
if event.Stale { |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
event.Stale = true |
||||
|
serialized, err := json.Marshal(event) |
||||
|
if err != nil { |
||||
|
bus.RunEvent(events.Log{ |
||||
|
Level: "error", |
||||
|
Code: "database_could_not_serialize_hardware_state", |
||||
|
Message: "Hardware State serialization failed: " + err.Error(), |
||||
|
}) |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
err = q.ReplaceDeviceInfo(timeout, mysqlgen.ReplaceDeviceInfoParams{ |
||||
|
ID: event.ID, |
||||
|
Kind: "hardware_metadata", |
||||
|
Data: serialized, |
||||
|
}) |
||||
|
if err != nil { |
||||
|
bus.RunEvent(events.Log{ |
||||
|
Level: "error", |
||||
|
Code: "database_could_not_save_hardware_state", |
||||
|
Message: err.Error(), |
||||
|
}) |
||||
|
|
||||
|
return |
||||
|
} |
||||
|
|
||||
|
case events.AssignmentCreated: |
||||
|
serialized, err := json.Marshal(&effects.Serializable{Effect: event.Effect}) |
||||
|
if err != nil { |
||||
|
bus.RunEvent(events.Log{ |
||||
|
Level: "error", |
||||
|
Code: "database_could_not_serialize_effect", |
||||
|
Message: err.Error(), |
||||
|
}) |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
err = q.ReplaceDeviceAssignment(timeout, mysqlgen.ReplaceDeviceAssignmentParams{ |
||||
|
ID: event.ID, |
||||
|
CreatedDate: time.Now().UTC(), |
||||
|
Match: event.Match, |
||||
|
Effect: serialized, |
||||
|
}) |
||||
|
if err != nil { |
||||
|
bus.RunEvent(events.Log{ |
||||
|
Level: "error", |
||||
|
Code: "database_could_not_save_assignment", |
||||
|
Message: err.Error(), |
||||
|
}) |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
case events.AssignmentRemoved: |
||||
|
err := q.DeleteDeviceAssignment(timeout, event.ID) |
||||
|
if err != nil { |
||||
|
bus.RunEvent(events.Log{ |
||||
|
Level: "error", |
||||
|
Code: "database_could_not_remove_assignment", |
||||
|
Message: err.Error(), |
||||
|
}) |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
case events.AliasAdded: |
||||
|
err := q.InsertDeviceAlias(timeout, mysqlgen.InsertDeviceAliasParams{ |
||||
|
ID: event.ID, |
||||
|
Alias: event.Alias, |
||||
|
}) |
||||
|
if err != nil { |
||||
|
bus.RunEvent(events.Log{ |
||||
|
Level: "error", |
||||
|
Code: "database_could_not_remove_assignment", |
||||
|
Message: err.Error(), |
||||
|
}) |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
case events.AliasRemoved: |
||||
|
err := q.DeleteDeviceAlias(timeout, mysqlgen.DeleteDeviceAliasParams{ |
||||
|
ID: event.ID, |
||||
|
Alias: event.Alias, |
||||
|
}) |
||||
|
if err != nil { |
||||
|
bus.RunEvent(events.Log{ |
||||
|
Level: "error", |
||||
|
Code: "database_could_not_remove_assignment", |
||||
|
Message: err.Error(), |
||||
|
}) |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
case events.DeviceForgotten: |
||||
|
err := q.DeleteDeviceInfoByID(timeout, event.ID) |
||||
|
if err != nil { |
||||
|
bus.RunEvent(events.Log{ |
||||
|
Level: "error", |
||||
|
Code: "database_could_not_remove_info", |
||||
|
Message: "Failed to remove device info: " + err.Error(), |
||||
|
}) |
||||
|
} |
||||
|
_ = q.DeleteDeviceAuth(timeout, event.ID) |
||||
|
err = q.DeleteDeviceAliasByID(timeout, event.ID) |
||||
|
if err != nil { |
||||
|
bus.RunEvent(events.Log{ |
||||
|
Level: "error", |
||||
|
Code: "database_could_not_remove_aliases", |
||||
|
Message: "Failed to remove device aliases: " + err.Error(), |
||||
|
}) |
||||
|
} |
||||
|
err = q.DeleteDeviceAliasByIDLike(timeout, event.ID+":%") |
||||
|
if err != nil { |
||||
|
bus.RunEvent(events.Log{ |
||||
|
Level: "error", |
||||
|
Code: "database_could_not_remove_sub_aliases", |
||||
|
Message: "Failed to remove sub-device aliases: " + err.Error(), |
||||
|
}) |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
func (d *database) HandleCommand(*lucifer3.EventBus, lucifer3.Command) {} |
||||
|
|
||||
|
func Connect(host string, port int, username, password, dbname string) (lucifer3.ActiveService, error) { |
||||
|
db, err := sql.Open("mysql", fmt.Sprintf( |
||||
|
"%s:%s@(%s:%d)/%s?parseTime=true", username, password, host, port, dbname, |
||||
|
)) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
db.SetMaxOpenConns(10) |
||||
|
db.SetMaxIdleConns(10) |
||||
|
db.SetConnMaxIdleTime(time.Minute) |
||||
|
|
||||
|
err = db.Ping() |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
return &database{db: db}, nil |
||||
|
} |
@ -0,0 +1,36 @@ |
|||||
|
package sqltypes |
||||
|
|
||||
|
import ( |
||||
|
"database/sql/driver" |
||||
|
"encoding/json" |
||||
|
"errors" |
||||
|
) |
||||
|
|
||||
|
type NullRawMessage struct { |
||||
|
RawMessage json.RawMessage |
||||
|
Valid bool |
||||
|
} |
||||
|
|
||||
|
func (n *NullRawMessage) Scan(value interface{}) error { |
||||
|
if value == nil { |
||||
|
n.RawMessage, n.Valid = json.RawMessage{}, false |
||||
|
return nil |
||||
|
} |
||||
|
buf, ok := value.([]byte) |
||||
|
|
||||
|
if !ok { |
||||
|
return errors.New("cannot parse to bytes") |
||||
|
} |
||||
|
|
||||
|
n.RawMessage, n.Valid = buf, true |
||||
|
|
||||
|
return nil |
||||
|
} |
||||
|
|
||||
|
func (n NullRawMessage) Value() (driver.Value, error) { |
||||
|
if !n.Valid { |
||||
|
return nil, nil |
||||
|
} |
||||
|
|
||||
|
return []byte(n.RawMessage), nil |
||||
|
} |
@ -0,0 +1,28 @@ |
|||||
|
version: "1" |
||||
|
packages: |
||||
|
- name: "mysqlgen" |
||||
|
path: "./services/mysqldb/mysqlgen" |
||||
|
queries: "./services/mysqldb/queries" |
||||
|
schema: "./services/mysqldb/migrations" |
||||
|
engine: "mysql" |
||||
|
emit_prepared_queries: true |
||||
|
emit_interface: false |
||||
|
emit_exact_table_names: false |
||||
|
emit_empty_slices: true |
||||
|
emit_json_tags: false |
||||
|
overrides: |
||||
|
- go_type: "git.aiterp.net/lucifer3/server/services/mysqldb/sqltypes.NullRawMessage" |
||||
|
db_type: "json" |
||||
|
nullable: true |
||||
|
- go_type: "float64" |
||||
|
db_type: "float" |
||||
|
- go_type: "float64" |
||||
|
db_type: "float" |
||||
|
nullable: true |
||||
|
- go_type: "int" |
||||
|
db_type: "int" |
||||
|
- go_type: "github.com/google/uuid.UUID" |
||||
|
db_type: "char" |
||||
|
- go_type: "github.com/google/uuid.NullUUID" |
||||
|
db_type: "char" |
||||
|
nullable: true |
Write
Preview
Loading…
Cancel
Save
Reference in new issue