Adds fetching and toggling alerts
All checks were successful
Gitea Build Action / build-go (push) Successful in 28s
Gitea Build Action / build-nuxt (push) Successful in 10m8s

This commit is contained in:
Daniel Svitan 2025-06-07 08:59:34 +02:00
parent ae7db8290c
commit 000c12845c
6 changed files with 159 additions and 105 deletions

View File

@ -9,6 +9,7 @@ require (
)
require (
github.com/gorilla/websocket v1.5.3 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect

View File

@ -1,5 +1,7 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/labstack/echo/v4 v4.13.3 h1:pwhpCPrTl5qry5HRdM5FwdXnhXSLSY+WE+YQSeCaafY=

View File

@ -24,12 +24,13 @@ var token string
// the condition is: distance >= threshold (is door open)
var opened bool
var openedChange = make(chan bool)
// is door locked
var locked bool = false
// alert the user when door locked and but open?
var alert bool = false
// alerts the user when door locked and but open?
var alerts bool = false
var gotifyToken string
var gotifyURL string
@ -44,7 +45,7 @@ type ChangeLockReq struct {
}
type ChangeAlertReq struct {
Alert bool `json:"alert"`
Alerts bool `json:"alerts"`
For int `json:"for"`
}
@ -52,15 +53,15 @@ func main() {
_ = godotenv.Load()
token = os.Getenv("TOKEN")
alertRaw := strings.ToLower(os.Getenv("USE_ALERTS"))
alert = alertRaw == "true" || alertRaw == "t" || alertRaw == "1" || alertRaw == "y" || alertRaw == "yes"
alertsRaw := strings.ToLower(os.Getenv("USE_ALERTS"))
alerts = alertsRaw == "true" || alertsRaw == "t" || alertsRaw == "1" || alertsRaw == "y" || alertsRaw == "yes"
gotifyToken = os.Getenv("GOTIFY_TOKEN")
gotifyURL = os.Getenv("GOTIFY_URL")
if alert && gotifyToken == "" {
if alerts && gotifyToken == "" {
log.Fatal("GOTIFY_TOKEN can't be empty when alerts are enabled")
}
if alert && gotifyURL == "" {
if alerts && gotifyURL == "" {
log.Fatal("GOTIFY_URL can't be empty when alerts are enabled")
}
@ -114,103 +115,17 @@ func main() {
}
}
app.GET("/", func(c echo.Context) error {
return c.JSON(http.StatusOK, "Hello world!")
})
app.GET("/", helloWorld)
app.GET("/open", authed(func(c echo.Context) error {
mut.Lock()
o := opened
mut.Unlock()
app.GET("/opened", authed(getOpened))
app.GET("/opened/ws", authed(getOpenedWs))
app.POST("/opened", authed(setOpened))
return c.JSON(http.StatusOK, o)
}))
app.GET("/locked", authed(getLocked))
app.POST("/locked", authed(setLocked))
app.POST("/open", authed(func(c echo.Context) error {
var data ChangeOpenReq
err := c.Bind(&data)
if err != nil {
return c.NoContent(http.StatusBadRequest)
}
if data.Opened == opened {
return c.NoContent(http.StatusOK)
}
mut.Lock()
opened = data.Opened
if locked && alert {
var action string
if opened {
action = "opened"
} else {
action = "closed"
}
go sendAlert(action)
}
mut.Unlock()
return c.NoContent(http.StatusOK)
}))
app.GET("/lock", authed(func(c echo.Context) error {
mut.Lock()
l := locked
mut.Unlock()
return c.JSON(http.StatusOK, l)
}))
app.POST("/lock", authed(func(c echo.Context) error {
var data ChangeLockReq
err := c.Bind(&data)
if err != nil {
return err
}
if data.Locked == locked {
return c.NoContent(http.StatusOK)
}
mut.Lock()
locked = data.Locked
mut.Unlock()
return c.NoContent(http.StatusOK)
}))
app.GET("/alert", authed(func(c echo.Context) error {
mut.Lock()
a := alert
mut.Unlock()
return c.JSON(http.StatusOK, a)
}))
app.POST("/alert", authed(func(c echo.Context) error {
var data ChangeAlertReq
err := c.Bind(&data)
if err != nil {
return err
}
if data.For > 0 {
go func() {
time.Sleep(time.Duration(data.For) * time.Second)
mut.Lock()
alert = !data.Alert
mut.Unlock()
}()
}
mut.Lock()
alert = data.Alert
mut.Unlock()
return c.NoContent(http.StatusOK)
}))
app.GET("/alerts", authed(getAlerts))
app.POST("/alerts", authed(setAlerts))
log.Fatal(app.Start(":1323"))
}

110
server/routes.go Normal file
View File

@ -0,0 +1,110 @@
package main
import (
"github.com/labstack/echo/v4"
"net/http"
"time"
)
func helloWorld(c echo.Context) error {
return c.JSON(http.StatusOK, "Hello world!")
}
func getOpened(c echo.Context) error {
mut.Lock()
o := opened
mut.Unlock()
return c.JSON(http.StatusOK, o)
}
func getOpenedWs(c echo.Context) error {
return nil
}
func setOpened(c echo.Context) error {
var data ChangeOpenReq
err := c.Bind(&data)
if err != nil {
return c.NoContent(http.StatusBadRequest)
}
if data.Opened == opened {
return c.NoContent(http.StatusOK)
}
mut.Lock()
opened = data.Opened
if locked && alerts {
var action string
if opened {
action = "opened"
} else {
action = "closed"
}
go sendAlert(action)
}
openedChange <- true
mut.Unlock()
return c.NoContent(http.StatusOK)
}
func getLocked(c echo.Context) error {
mut.Lock()
l := locked
mut.Unlock()
return c.JSON(http.StatusOK, l)
}
func setLocked(c echo.Context) error {
var data ChangeLockReq
err := c.Bind(&data)
if err != nil {
return err
}
if data.Locked == locked {
return c.NoContent(http.StatusOK)
}
mut.Lock()
locked = data.Locked
mut.Unlock()
return c.NoContent(http.StatusOK)
}
func getAlerts(c echo.Context) error {
mut.Lock()
a := alerts
mut.Unlock()
return c.JSON(http.StatusOK, a)
}
func setAlerts(c echo.Context) error {
var data ChangeAlertReq
err := c.Bind(&data)
if err != nil {
return err
}
if data.For > 0 {
go func() {
time.Sleep(time.Duration(data.For) * time.Second)
mut.Lock()
alerts = !data.Alerts
mut.Unlock()
}()
}
mut.Lock()
alerts = data.Alerts
mut.Unlock()
return c.NoContent(http.StatusOK)
}

View File

@ -13,8 +13,8 @@ FROM oven/bun:1
WORKDIR /app
COPY --from=build /app/.output .
ENV PORT 3000
ENV HOST 0.0.0.0
ENV PORT=3000
ENV HOST=0.0.0.0
EXPOSE 3000
CMD ["bun", "/app/server/index.mjs"]

View File

@ -77,7 +77,7 @@
:color="alert ? 'primary' : 'secondary'"
variant="solid"
class="flex items-center justify-center w-full h-10"
@click="() => (alert = !alert)"
@click="toggleAlert"
>
{{ alert ? "Turn off" : "Turn on" }}
</UButton>
@ -119,6 +119,21 @@ async function toggleLock() {
.catch(handleRequestError)
}
async function toggleAlert() {
const desired = !alert.value
axios
.post(useAPI("/alert"), { alert: desired }, { headers: useHeaders() })
.then((res) => {
handleResponse(res, () => {
toast.add({
title: `Alerts were turned ${desired ? "on" : "off"}`,
})
alert.value = desired
})
})
.catch(handleRequestError)
}
onMounted(() => {
if (!token.value) {
return navigateTo("/token")
@ -134,5 +149,16 @@ onMounted(() => {
})
})
.catch(handleRequestError)
axios
.get<boolean>(useAPI("/alert"), {
headers: useHeaders(),
})
.then((res) => {
handleResponse(res, (response) => {
alert.value = response.data
})
})
.catch(handleRequestError)
})
</script>