From cafbd63f983ec3f8d8ff1f50f4d31a6919530485 Mon Sep 17 00:00:00 2001 From: Finn Date: Fri, 22 Nov 2024 22:25:39 -0800 Subject: [PATCH] Add support for editing individual lock code slots --- db/lock_code_slots.sql.go | 4 +++- db/queries/lock_code_slots.sql | 2 +- frontend/header.html | 1 + frontend/lock-code-edit.html | 5 ++++- frontend/lock.html | 4 +++- httpserver/lock.go | 25 ++++++++++++++++++++++--- zwavejs/client.go | 11 ++++++++++- 7 files changed, 44 insertions(+), 8 deletions(-) diff --git a/db/lock_code_slots.sql.go b/db/lock_code_slots.sql.go index a900a5e..222e603 100644 --- a/db/lock_code_slots.sql.go +++ b/db/lock_code_slots.sql.go @@ -130,7 +130,7 @@ func (q *Queries) GetLockCodesByCode(ctx context.Context, code string) ([]LockCo } const upsertCodeSlot = `-- name: UpsertCodeSlot :exec -INSERT INTO lock_code_slots (lock, slot, code, enabled, name) VALUES (?, ?, ?, ?, "") ON CONFLICT (lock, slot) DO UPDATE SET code=excluded.code, enabled=excluded.enabled +INSERT INTO lock_code_slots (lock, slot, code, enabled, name) VALUES (?, ?, ?, ?, ?) ON CONFLICT (lock, slot) DO UPDATE SET code=excluded.code, enabled=excluded.enabled, name=excluded.name ` type UpsertCodeSlotParams struct { @@ -138,6 +138,7 @@ type UpsertCodeSlotParams struct { Slot int64 Code string Enabled bool + Name string } func (q *Queries) UpsertCodeSlot(ctx context.Context, arg UpsertCodeSlotParams) error { @@ -146,6 +147,7 @@ func (q *Queries) UpsertCodeSlot(ctx context.Context, arg UpsertCodeSlotParams) arg.Slot, arg.Code, arg.Enabled, + arg.Name, ) return err } diff --git a/db/queries/lock_code_slots.sql b/db/queries/lock_code_slots.sql index 87c51f4..f0e0236 100644 --- a/db/queries/lock_code_slots.sql +++ b/db/queries/lock_code_slots.sql @@ -1,5 +1,5 @@ -- name: UpsertCodeSlot :exec -INSERT INTO lock_code_slots (lock, slot, code, enabled, name) VALUES (?, ?, ?, ?, "") ON CONFLICT (lock, slot) DO UPDATE SET code=excluded.code, enabled=excluded.enabled; +INSERT INTO lock_code_slots (lock, slot, code, enabled, name) VALUES (?, ?, ?, ?, ?) ON CONFLICT (lock, slot) DO UPDATE SET code=excluded.code, enabled=excluded.enabled, name=excluded.name; -- name: GetLockCodeBySlot :one SELECT * FROM lock_code_slots WHERE lock = ? AND slot = ?; diff --git a/frontend/header.html b/frontend/header.html index 58e2bf2..98830cc 100644 --- a/frontend/header.html +++ b/frontend/header.html @@ -10,4 +10,5 @@
+ Home
diff --git a/frontend/lock-code-edit.html b/frontend/lock-code-edit.html index 65e1707..6cecbe6 100644 --- a/frontend/lock-code-edit.html +++ b/frontend/lock-code-edit.html @@ -1,7 +1,10 @@ {{ template "header.html" . }} -
Rename {{ if eq .Data.Name "" }}Lock #{{ .Data.ID }}{{ else }}{{ .Data.Name }}{{ end }}
+
{{ if eq .Data.Name "" }}Lock #{{ .Data.ID }}{{ else }}{{ .Data.Name }}{{ end }}
+ Code:
Name:
+ Enabled:
+
{{ template "footer.html" }} diff --git a/frontend/lock.html b/frontend/lock.html index 8eed85b..27a9c62 100644 --- a/frontend/lock.html +++ b/frontend/lock.html @@ -1,10 +1,11 @@ {{ template "header.html" . }}
{{ if eq .Data.lock.Name "" }}Lock #{{ .Data.lock.ID }}{{ else }}{{ .Data.lock.Name }}{{ end }}
-[ rename ] +[ rename ]

+ @@ -12,6 +13,7 @@ {{ range $_, $code := .Data.codes }} + diff --git a/httpserver/lock.go b/httpserver/lock.go index 2de6c17..8e5b8bb 100644 --- a/httpserver/lock.go +++ b/httpserver/lock.go @@ -111,9 +111,27 @@ func lockCodeEditHandler(c echo.Context) error { return err } - newCode := c.FormValue("code") - zwaveClient := c.Get(contextKeyZWaveClient).(*zwavejs.Client) + + enabled := c.FormValue("enabled") == "on" + enabledInt := 0 + if enabled { + enabledInt = 1 + } + err = zwaveClient.SetNodeValue(ctx, int(lock.ZwaveDeviceID), zwavejs.NodeValue{ + CCVersion: 1, + CommandClassName: zwavejs.CommandClassNameUserCode, + CommandClass: zwavejs.CommandClassUserCode, + Endpoint: 0, + Property: zwavejs.AnyType{Type: zwavejs.AnyTypeString, String: string(zwavejs.PropertyUserIDStatus)}, + PropertyName: zwavejs.AnyType{Type: zwavejs.AnyTypeString, String: string(zwavejs.PropertyUserIDStatus)}, + PropertyKey: zwavejs.AnyType{Type: zwavejs.AnyTypeInt, Int: int(slot)}, + }, zwavejs.AnyType{Type: zwavejs.AnyTypeInt, Int: enabledInt}) + if err != nil { + return fmt.Errorf("error pushing enabled state to lock %s (ZWaveDeviceID=%d ID=%d): %v", lock.Name, lock.ZwaveDeviceID, lock.ID, err) + } + + newCode := c.FormValue("code") err = zwaveClient.SetNodeValue(ctx, int(lock.ZwaveDeviceID), zwavejs.NodeValue{ CCVersion: 1, CommandClassName: zwavejs.CommandClassNameUserCode, @@ -131,7 +149,8 @@ func lockCodeEditHandler(c echo.Context) error { Lock: lockID, Slot: slot, Code: newCode, - Enabled: true, + Name: c.FormValue("name"), + Enabled: enabled, }) if err != nil { return err diff --git a/zwavejs/client.go b/zwavejs/client.go index 636ed06..60be1eb 100644 --- a/zwavejs/client.go +++ b/zwavejs/client.go @@ -43,8 +43,10 @@ func (c *Client) DialAndListen(ctx context.Context) { for { logrus.WithField("server", c.Server).Info("connecting to zwave-js server") + ctxWithTimeout, cancel := context.WithTimeout(ctx, time.Second*5) + defer cancel() conn, err := failsafe.Get(func() (*websocket.Conn, error) { - conn, _, err := websocket.DefaultDialer.DialContext(ctx, c.Server, nil) + conn, _, err := websocket.DefaultDialer.DialContext(ctxWithTimeout, c.Server, nil) return conn, err }, connectRetryPolicy) if err != nil { @@ -63,6 +65,7 @@ func (c *Client) DialAndListen(ctx context.Context) { continue } _ = c.conn.Close() + cancel() } } @@ -234,6 +237,8 @@ func (c *Client) handleCallback(messageID string, result Result) error { c.callbacksLock.Lock() defer c.callbacksLock.Unlock() + logrus.WithField("message_id", messageID).Debug(fmt.Sprintf("%+v", result)) + cb, ok := c.callbacks[messageID] if !ok { logrus.WithField("message_id", messageID).Warn("got response to a message we didn't send") @@ -255,6 +260,10 @@ func (c *Client) sendMessage(message OutgoingMessageIface) (Result, error) { c.callbacks[messageID] = ch c.callbacksLock.Unlock() + // w := logrus.WithField("message_id", messageID).Writer() + // json.NewEncoder(w).Encode(message) + // w.Close() + if err := c.conn.WriteJSON(message); err != nil { return Result{}, err }
SlotName Code Enabled? Actions
{{ $code.Slot }}{{ $code.Name }} {{ $code.Code }} {{ if $code.Enabled }}enabled{{ else }}disabled{{ end }} [ edit ]