From 060b5705c8d548146479121723dae74ec05c1dd6 Mon Sep 17 00:00:00 2001 From: Finn Date: Sat, 23 Nov 2024 17:01:50 -0800 Subject: [PATCH 1/9] Fix version --- .forgejo/workflows/build-and-release.yaml | 2 ++ Containerfile | 3 ++- config/version.go | 30 +++++++++++++++++++++++ frontend/frontend.go | 5 +++- 4 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 config/version.go diff --git a/.forgejo/workflows/build-and-release.yaml b/.forgejo/workflows/build-and-release.yaml index 83131e2..3351bbe 100644 --- a/.forgejo/workflows/build-and-release.yaml +++ b/.forgejo/workflows/build-and-release.yaml @@ -21,6 +21,8 @@ jobs: labels: ${{ steps.meta.outputs.labels }} platforms: linux/amd64,linux/arm64,linux/arm/v7 push: true + build-args: | + VERSION_STRING=${{ env.GITHUB_REF_NAME }} - name: update hassio-addons if: startsWith(github.ref, 'refs/tags/v') run: | diff --git a/Containerfile b/Containerfile index 35afa7a..67272bd 100644 --- a/Containerfile +++ b/Containerfile @@ -18,7 +18,8 @@ FROM alpine:latest AS build RUN apk add --no-cache go ADD . /go/lockserver WORKDIR /go/lockserver -RUN CGO_ENABLED=0 go build ./cmd/lockserver +ARG VERSION_STRING +RUN CGO_ENABLED=0 go build -ldflags "-X git.devhack.net/devhack/member-services/config.Version=${VERSION_STRING}" ./cmd/lockserver FROM scratch COPY --from=build /go/lockserver/lockserver /lockserver diff --git a/config/version.go b/config/version.go new file mode 100644 index 0000000..d611b7c --- /dev/null +++ b/config/version.go @@ -0,0 +1,30 @@ +package config + +import ( + "runtime/debug" + + "github.com/sirupsen/logrus" +) + +var ( + BuildInfo *debug.BuildInfo + Version string +) + +func init() { + var ok bool + BuildInfo, ok = debug.ReadBuildInfo() + if !ok { + logrus.Error("failed to read build info") + return + } + + if Version == "" { + for _, setting := range BuildInfo.Settings { + if setting.Key == "vcs.revision" { + Version = setting.Value + break + } + } + } +} diff --git a/frontend/frontend.go b/frontend/frontend.go index eb6b1f2..a57ea99 100644 --- a/frontend/frontend.go +++ b/frontend/frontend.go @@ -2,8 +2,11 @@ package frontend import ( "embed" + "fmt" "html/template" "io/fs" + + "git.janky.solutions/finn/lockserver/config" ) var ( @@ -16,7 +19,7 @@ var ( Templates *template.Template funcs = template.FuncMap{ - "version": func() string { return "better-zwave-locks v0.x.x aaaaaaaa" }, + "version": func() string { return fmt.Sprintf("better-zwave-locks %s", config.Version) }, } ) From a26b9cc63e306f15a5b15997e4690dbda01a4001 Mon Sep 17 00:00:00 2001 From: Finn Date: Sun, 24 Nov 2024 16:08:06 -0800 Subject: [PATCH 2/9] Show logs when editing a code --- db/helpers.go | 9 +++-- db/lock_log.sql.go | 76 ++++++++++++++++++++++++++++++++++++ db/queries/lock_log.sql | 6 +++ frontend/frontend.go | 4 +- frontend/lock-code-edit.html | 7 ++++ frontend/lock.html | 3 ++ httpserver/lock.go | 13 ++++++ 7 files changed, 113 insertions(+), 5 deletions(-) diff --git a/db/helpers.go b/db/helpers.go index a6c1062..85c135e 100644 --- a/db/helpers.go +++ b/db/helpers.go @@ -49,10 +49,11 @@ func Migrate() error { } func NullString(s string) sql.NullString { - return sql.NullString{ - Valid: s != "", - String: s, - } + return sql.NullString{Valid: s != "", String: s} +} + +func NullInt64(i int64) sql.NullInt64 { + return sql.NullInt64{Valid: true, Int64: i} } type loggingDBTX struct { diff --git a/db/lock_log.sql.go b/db/lock_log.sql.go index b777285..5507db2 100644 --- a/db/lock_log.sql.go +++ b/db/lock_log.sql.go @@ -25,6 +25,44 @@ func (q *Queries) AddLogEntry(ctx context.Context, arg AddLogEntryParams) error return err } +const getLastLogForSlot = `-- name: GetLastLogForSlot :many +SELECT lock, timestamp, state, code, issued_code FROM lock_log WHERE lock = ? AND code = ? ORDER BY timestamp DESC LIMIT 1 +` + +type GetLastLogForSlotParams struct { + Lock int64 + Code sql.NullInt64 +} + +func (q *Queries) GetLastLogForSlot(ctx context.Context, arg GetLastLogForSlotParams) ([]LockLog, error) { + rows, err := q.db.QueryContext(ctx, getLastLogForSlot, arg.Lock, arg.Code) + if err != nil { + return nil, err + } + defer rows.Close() + var items []LockLog + for rows.Next() { + var i LockLog + if err := rows.Scan( + &i.Lock, + &i.Timestamp, + &i.State, + &i.Code, + &i.IssuedCode, + ); 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 getLogForLock = `-- name: GetLogForLock :many SELECT lock, timestamp, state, code, issued_code FROM lock_log WHERE lock = ? ORDER BY timestamp DESC ` @@ -57,3 +95,41 @@ func (q *Queries) GetLogForLock(ctx context.Context, lock int64) ([]LockLog, err } return items, nil } + +const getLogForSlot = `-- name: GetLogForSlot :many +SELECT lock, timestamp, state, code, issued_code FROM lock_log WHERE lock = ? AND code = ? ORDER BY timestamp DESC +` + +type GetLogForSlotParams struct { + Lock int64 + Code sql.NullInt64 +} + +func (q *Queries) GetLogForSlot(ctx context.Context, arg GetLogForSlotParams) ([]LockLog, error) { + rows, err := q.db.QueryContext(ctx, getLogForSlot, arg.Lock, arg.Code) + if err != nil { + return nil, err + } + defer rows.Close() + var items []LockLog + for rows.Next() { + var i LockLog + if err := rows.Scan( + &i.Lock, + &i.Timestamp, + &i.State, + &i.Code, + &i.IssuedCode, + ); 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 +} diff --git a/db/queries/lock_log.sql b/db/queries/lock_log.sql index adfe54f..6fda69a 100644 --- a/db/queries/lock_log.sql +++ b/db/queries/lock_log.sql @@ -3,3 +3,9 @@ INSERT INTO lock_log (lock, state, code) VALUES (?, ?, ?); -- name: GetLogForLock :many SELECT * FROM lock_log WHERE lock = ? ORDER BY timestamp DESC; + +-- name: GetLogForSlot :many +SELECT * FROM lock_log WHERE lock = ? AND code = ? ORDER BY timestamp DESC; + +-- name: GetLastLogForSlot :many +SELECT * FROM lock_log WHERE lock = ? AND code = ? ORDER BY timestamp DESC LIMIT 1; diff --git a/frontend/frontend.go b/frontend/frontend.go index a57ea99..526381c 100644 --- a/frontend/frontend.go +++ b/frontend/frontend.go @@ -5,6 +5,7 @@ import ( "fmt" "html/template" "io/fs" + "time" "git.janky.solutions/finn/lockserver/config" ) @@ -19,7 +20,8 @@ var ( Templates *template.Template funcs = template.FuncMap{ - "version": func() string { return fmt.Sprintf("better-zwave-locks %s", config.Version) }, + "version": func() string { return fmt.Sprintf("better-zwave-locks %s", config.Version) }, + "time_since": func(t time.Time) string { return time.Since(t).Round(time.Second).String() }, } ) diff --git a/frontend/lock-code-edit.html b/frontend/lock-code-edit.html index 4faa47c..e996ff3 100644 --- a/frontend/lock-code-edit.html +++ b/frontend/lock-code-edit.html @@ -8,4 +8,11 @@
+

+ + {{ template "footer.html" }} diff --git a/frontend/lock.html b/frontend/lock.html index 1da075a..af71153 100644 --- a/frontend/lock.html +++ b/frontend/lock.html @@ -20,4 +20,7 @@ {{ end }} + +

+ {{ template "footer.html" }} diff --git a/httpserver/lock.go b/httpserver/lock.go index c5ef1da..192fa38 100644 --- a/httpserver/lock.go +++ b/httpserver/lock.go @@ -1,6 +1,8 @@ package httpserver import ( + "database/sql" + "errors" "fmt" "net/http" "strconv" @@ -8,6 +10,7 @@ import ( "git.janky.solutions/finn/lockserver/db" "git.janky.solutions/finn/lockserver/zwavejs" echo "github.com/labstack/echo/v4" + "github.com/sirupsen/logrus" ) func lockHandler(c echo.Context) error { @@ -109,9 +112,19 @@ func lockCodeEditHandler(c echo.Context) error { } if c.Request().Method == http.MethodGet { + logrus.WithField("lock", lockID).WithField("code", code.ID).Debug("querying logs") + log, err := queries.GetLogForSlot(ctx, db.GetLogForSlotParams{ + Lock: lockID, + Code: db.NullInt64(code.ID), + }) + if err != nil && !errors.Is(err, sql.ErrNoRows) { + return err + } + return c.Render(http.StatusFound, "lock-code-edit.html", map[string]interface{}{ "lock": lock, "code": code, + "log": log, }) } From 01b77502591beadbef7a8fc31f0f53020befdefd Mon Sep 17 00:00:00 2001 From: Finn Date: Sun, 24 Nov 2024 16:21:08 -0800 Subject: [PATCH 3/9] improve table display --- frontend/lock.html | 2 +- frontend/static/main.css | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/frontend/lock.html b/frontend/lock.html index af71153..50a9dcd 100644 --- a/frontend/lock.html +++ b/frontend/lock.html @@ -2,7 +2,7 @@
{{ if eq .Data.lock.Name "" }}Lock #{{ .Data.lock.ID }}{{ else }}{{ .Data.lock.Name }}{{ end }}
[ rename ]

- +
diff --git a/frontend/static/main.css b/frontend/static/main.css index 48da457..dc46de5 100644 --- a/frontend/static/main.css +++ b/frontend/static/main.css @@ -30,3 +30,7 @@ header { .code-enabled { background-color: #0a0; } + +.table { + width: 100%; +} From 4627ae91b30ddc7af9a9a0316e46970d1ee2ab5d Mon Sep 17 00:00:00 2001 From: Finn Date: Sun, 24 Nov 2024 16:36:18 -0800 Subject: [PATCH 4/9] add readme and limit log entry counts displayed --- README.md | 18 ++++++++++++++++++ db/lock_log.sql.go | 2 +- db/queries/lock_log.sql | 2 +- 3 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..9f62cb6 --- /dev/null +++ b/README.md @@ -0,0 +1,18 @@ +# lockserver + +_better Z-Wave Lock management for Home Assistant_ + +## Status + +This is a work in progress. I have some ideas of where I want it to go, but I'm mostly experimenting with my own needs. + +## Install + +To add to Home Assistant, add my hassio-addons repo by clicking the button below, then search for and install the "LockServer" addon. + +[![Add to Home Assistant.](https://my.home-assistant.io/badges/supervisor_add_addon_repository.svg)](https://my.home-assistant.io/redirect/supervisor_add_addon_repository/?repository_url=https%3A%2F%2Fgit.janky.solutions%2Ffinn%2Fhassio-addons) + + +## Usage + +When you open the addon's web UI, it will show a list of Z-Wave locks. Clicking a lock shows all codes slots for that lock. Clicking edit on each slot allows changing the code, changing the name, enabling or disabling the slot, and seeing a log of recent uses of that code. diff --git a/db/lock_log.sql.go b/db/lock_log.sql.go index 5507db2..b6c4385 100644 --- a/db/lock_log.sql.go +++ b/db/lock_log.sql.go @@ -97,7 +97,7 @@ func (q *Queries) GetLogForLock(ctx context.Context, lock int64) ([]LockLog, err } const getLogForSlot = `-- name: GetLogForSlot :many -SELECT lock, timestamp, state, code, issued_code FROM lock_log WHERE lock = ? AND code = ? ORDER BY timestamp DESC +SELECT lock, timestamp, state, code, issued_code FROM lock_log WHERE lock = ? AND code = ? ORDER BY timestamp DESC LIMIT 100 ` type GetLogForSlotParams struct { diff --git a/db/queries/lock_log.sql b/db/queries/lock_log.sql index 6fda69a..0106b03 100644 --- a/db/queries/lock_log.sql +++ b/db/queries/lock_log.sql @@ -5,7 +5,7 @@ INSERT INTO lock_log (lock, state, code) VALUES (?, ?, ?); SELECT * FROM lock_log WHERE lock = ? ORDER BY timestamp DESC; -- name: GetLogForSlot :many -SELECT * FROM lock_log WHERE lock = ? AND code = ? ORDER BY timestamp DESC; +SELECT * FROM lock_log WHERE lock = ? AND code = ? ORDER BY timestamp DESC LIMIT 100; -- name: GetLastLogForSlot :many SELECT * FROM lock_log WHERE lock = ? AND code = ? ORDER BY timestamp DESC LIMIT 1; From 7a0420bb46df84e3e3285719183f94287b37f06e Mon Sep 17 00:00:00 2001 From: Finn Date: Sun, 24 Nov 2024 19:42:53 -0800 Subject: [PATCH 5/9] Update CSS --- Containerfile | 2 +- frontend/static/main.css | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Containerfile b/Containerfile index 67272bd..1ac589c 100644 --- a/Containerfile +++ b/Containerfile @@ -19,7 +19,7 @@ RUN apk add --no-cache go ADD . /go/lockserver WORKDIR /go/lockserver ARG VERSION_STRING -RUN CGO_ENABLED=0 go build -ldflags "-X git.devhack.net/devhack/member-services/config.Version=${VERSION_STRING}" ./cmd/lockserver +RUN CGO_ENABLED=0 go build -ldflags "-X git.janky.solutions/finn/lockserver/config.Version=${VERSION_STRING}" ./cmd/lockserver FROM scratch COPY --from=build /go/lockserver/lockserver /lockserver diff --git a/frontend/static/main.css b/frontend/static/main.css index dc46de5..321d64d 100644 --- a/frontend/static/main.css +++ b/frontend/static/main.css @@ -16,6 +16,8 @@ a { flex-direction: column; row-gap: 1em; padding: 1em; + margin: auto; + max-width: 1000px; } #main { From 1340b3167f19042be825dd91bf68768db79dc53d Mon Sep 17 00:00:00 2001 From: Finn Date: Mon, 25 Nov 2024 14:38:51 -0800 Subject: [PATCH 6/9] Add a button to generate codes --- frontend/lock-code-edit.html | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/frontend/lock-code-edit.html b/frontend/lock-code-edit.html index e996ff3..cf2298c 100644 --- a/frontend/lock-code-edit.html +++ b/frontend/lock-code-edit.html @@ -2,7 +2,7 @@
{{ if eq .Data.lock.Name "" }}Lock #{{ .Data.lock.ID }}{{ else }}{{ .Data.lock.Name }}{{ end }} Slot #{{ .Data.code.Slot }}

- Code:
+ Code: 🔄
Name:
Enabled:

@@ -15,4 +15,14 @@
  • {{ $entry.State }} ({{ $entry.Timestamp | time_since }} ago)
  • {{ end }} + + {{ template "footer.html" }} From 6920f9ee24e24e1834dd685ee5238f2f658f29f2 Mon Sep 17 00:00:00 2001 From: Finn Date: Tue, 26 Nov 2024 13:48:19 -0800 Subject: [PATCH 7/9] drop max code length to 4 --- frontend/lock-code-edit.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/lock-code-edit.html b/frontend/lock-code-edit.html index cf2298c..12750fa 100644 --- a/frontend/lock-code-edit.html +++ b/frontend/lock-code-edit.html @@ -19,7 +19,7 @@
    Slot Name