HTTP endpoints to get and set codes
This commit is contained in:
parent
47a45b8000
commit
7fdd02bd33
17 changed files with 914 additions and 141 deletions
53
httpserver/server.go
Normal file
53
httpserver/server.go
Normal file
|
@ -0,0 +1,53 @@
|
|||
package httpserver
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
echo "github.com/labstack/echo/v4"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
"git.janky.solutions/finn/lockserver/config"
|
||||
"git.janky.solutions/finn/lockserver/openapi"
|
||||
"git.janky.solutions/finn/lockserver/zwavejs"
|
||||
)
|
||||
|
||||
var server *echo.Echo
|
||||
|
||||
type lockserver struct {
|
||||
ZWaveJS *zwavejs.Client
|
||||
}
|
||||
|
||||
func ListenAndServe(client *zwavejs.Client) {
|
||||
server = echo.New()
|
||||
server.HideBanner = true
|
||||
server.HidePort = true
|
||||
server.HTTPErrorHandler = handleError
|
||||
|
||||
openapi.RegisterHandlersWithBaseURL(server, lockserver{ZWaveJS: client}, "/api")
|
||||
|
||||
err := server.Start(config.C.HTTPBind)
|
||||
if err != http.ErrServerClosed {
|
||||
logrus.WithError(err).Fatal("error starting http server")
|
||||
}
|
||||
}
|
||||
|
||||
func handleError(err error, c echo.Context) {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
_ = c.JSON(http.StatusNotFound, map[string]string{"error": "not found"})
|
||||
return
|
||||
}
|
||||
|
||||
logrus.WithError(err).Error("error handling request")
|
||||
_ = c.JSON(http.StatusInternalServerError, map[string]string{"error": "internal server error"})
|
||||
}
|
||||
|
||||
func Shutdown(ctx context.Context) error {
|
||||
if server == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return server.Shutdown(ctx)
|
||||
}
|
112
httpserver/slots.go
Normal file
112
httpserver/slots.go
Normal file
|
@ -0,0 +1,112 @@
|
|||
package httpserver
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
echo "github.com/labstack/echo/v4"
|
||||
|
||||
"git.janky.solutions/finn/lockserver/db"
|
||||
"git.janky.solutions/finn/lockserver/openapi"
|
||||
"git.janky.solutions/finn/lockserver/zwavejs"
|
||||
)
|
||||
|
||||
func (lockserver) GetLockCodeSlot(c echo.Context, lock int, slot int) error {
|
||||
queries, dbc, err := db.Get()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer dbc.Close()
|
||||
|
||||
slotData, err := queries.GetLockCodeBySlot(c.Request().Context(), db.GetLockCodeBySlotParams{
|
||||
Lock: int64(lock),
|
||||
Slot: int64(slot),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.JSON(http.StatusFound, slotData.OpenAPI())
|
||||
}
|
||||
|
||||
func (l lockserver) PutLockCodeSlot(c echo.Context, lockID int, slot int) error {
|
||||
queries, dbc, err := db.Get()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer dbc.Close()
|
||||
|
||||
var body openapi.LockCodeSlot
|
||||
if err := c.Bind(&body); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctx := c.Request().Context()
|
||||
|
||||
lock, err := queries.GetLock(ctx, int64(lockID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// sample from https://github.com/FutureTense/keymaster/blob/f4f1046bddb7901cbd3ce7820886be1ff7895fe7/tests/test_services.py#L88
|
||||
//
|
||||
// {
|
||||
// "ccVersion": 1,
|
||||
// "commandClassName": "User Code",
|
||||
// "commandClass": 99,
|
||||
// "endpoint": 0,
|
||||
// "property": "userCode",
|
||||
// "propertyName": "userCode",
|
||||
// "propertyKey": 1,
|
||||
// "propertyKeyName": "1",
|
||||
// "metadata": {
|
||||
// "type": "string",
|
||||
// "readable": True,
|
||||
// "writeable": True,
|
||||
// "minLength": 4,
|
||||
// "maxLength": 10,
|
||||
// "label": "User Code (1)",
|
||||
// },
|
||||
// "value": "123456",
|
||||
// }
|
||||
err = l.ZWaveJS.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.PropertyUserCode)},
|
||||
PropertyName: zwavejs.AnyType{Type: zwavejs.AnyTypeString, String: string(zwavejs.PropertyUserCode)},
|
||||
PropertyKey: zwavejs.AnyType{Type: zwavejs.AnyTypeInt, Int: slot},
|
||||
}, zwavejs.AnyType{Type: zwavejs.AnyTypeString, String: body.Code})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
enabled := 0
|
||||
if body.Enabled {
|
||||
enabled = 1
|
||||
}
|
||||
err = l.ZWaveJS.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: slot},
|
||||
}, zwavejs.AnyType{Type: zwavejs.AnyTypeInt, Int: enabled})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = queries.UpsertCodeSlot(ctx, db.UpsertCodeSlotParams{
|
||||
Lock: lock.ID,
|
||||
Slot: int64(slot),
|
||||
Code: body.Code,
|
||||
Enabled: body.Enabled,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.JSON(http.StatusOK, body)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue