feat: toggle controller state on/off

This commit is contained in:
Kaaninchen
2026-08-03 18:50:22 +02:00
parent 67162359ed
commit 3f470096ce
7 changed files with 86 additions and 11 deletions
+2 -2
View File
@@ -10,10 +10,10 @@ build:
@echo "🔧 Building binary..."
@cp $(CONFIG_FILE) $(BIN_DIR)/
@go build -o $(BIN_DIR)/$(BIN_NAME) $(MAIN_PKG)
@echo "Build complete: $(BIN_DIR)/$(BIN_NAME)"
@echo "Build complete: $(BIN_DIR)/$(BIN_NAME)"
run:
@echo "🚀 Running server..."
@echo "Running server..."
@go run $(MAIN_PKG)
clean:
@echo "🧹 Cleaning up..."
+17 -5
View File
@@ -24,7 +24,7 @@ Laterna requires a config.json file in the root directory. A [example config](ht
cp config.json.example config.json
```
You can leave the json as it is or configure it to your liking, although some configuration options (e.g. `verboseLogging`) aren't fully implemented yet.
You can leave the config as it is or adjust it to your liking.
Make sure that your firewall supports connections to the configured port for laterna (default: `8080`), otherwise clients won't be able to connect to the API. You can do so by using ufw on most linux distributions
@@ -74,10 +74,11 @@ The token is shown once on the first startup. To regenerate it, run the server w
#### 🎛️ Controllers
| Method | Route | Description | Payload |
|--------|----------------|-------------------------------|---------------------|
| POST | `/controllers` | Create a new controller | |
| DELETE | `/controllers` | Delete an existing controller |{ "ID": 1} |
| Method | Route | Description | Payload |
|--------|----------------------------|--------------------------------------|------------|
| POST | `/controllers` | Create a new controller | |
| POST | `/controllers/toggle/{id}` | Toggle an existing controller on/off | |
| DELETE | `/controllers` | Delete an existing controller | { "ID": 1} |
</details>
@@ -126,6 +127,10 @@ $ http GET localhost:8080/api/v1/colors/1 "Authorization: $TOKEN"
$ http PUT localhost:8080/api/v1/colors/1 "Authorization: $TOKEN" Color="#C2C342"
```
#### Toggle controller on/off
```bash
$ http PUT localhost:8080/api/v1/colors/1 "Authorization: $TOKEN"
```
</details>
@@ -170,6 +175,13 @@ $ curl -X PUT localhost:8080/api/v1/colors/1 \
-d '{"Color": "#C2C342"}'
```
#### Toggle controller on/off
```bash
$ curl -X POST localhost:8080/api/v1/colors/1 \
-H "Authorization:$TOKEN"
```
</details>
+2 -1
View File
@@ -34,6 +34,7 @@ func InitDB() {
id INTEGER PRIMARY KEY,
token_hash TEXT,
color TEXT,
active INTEGER DEFAULT 0,
updated_at DATETIME
);
`)
@@ -42,4 +43,4 @@ func InitDB() {
logger.DBLogger.Fatalf("An error occured while initializing the database: %v", err)
}
}
}
+26 -3
View File
@@ -71,7 +71,7 @@ func ControllerExists(id int) bool {
}
func GetAllColors() ([]models.LampState, error) {
rows, err := DB.Query("SELECT id, color, updated_at FROM controllers WHERE id > 0")
rows, err := DB.Query("SELECT id, color, active, updated_at FROM controllers WHERE id > 0")
if err != nil {
return nil, err
}
@@ -81,7 +81,7 @@ func GetAllColors() ([]models.LampState, error) {
for rows.Next() {
var state models.LampState
if err := rows.Scan(&state.ID, &state.Color, &state.UpdatedAt); err != nil {
if err := rows.Scan(&state.ID, &state.Color, &state.Active, &state.UpdatedAt); err != nil {
return nil, err
}
controllers = append(controllers, state)
@@ -90,7 +90,6 @@ func GetAllColors() ([]models.LampState, error) {
if err := rows.Err(); err != nil {
return nil, err
}
return controllers, nil
}
@@ -129,3 +128,27 @@ func SetColor(id int, color string) error {
logger.DBLogger.Printf("Lamp %d color updated to %s", id, color)
return nil
}
func GetControllerState(id int) (bool, error) {
row := DB.QueryRow("SELECT active FROM controllers WHERE id = ?", id)
var state bool
err := row.Scan(&state)
if err != nil {
logger.DBLogger.Print(err)
return false, err
}
return state, nil
}
func SetControllerstate(active bool, id int) error {
_, err := DB.Exec("UPDATE controllers SET active = ? WHERE id = ?", active, id)
if err != nil {
logger.DBLogger.Printf("Failed to update active state for controller %d: %v", id, err)
return err
}
logger.DBLogger.Printf("Set active state for %d to %t", id, active)
return nil
}
+6
View File
@@ -27,6 +27,7 @@ type HTTPResponse struct {
type LampState struct {
ID int `json:"id"`
Color string `json:"color"`
Active bool `json:"active"`
UpdatedAt time.Time `json:"updated_at"`
}
@@ -45,3 +46,8 @@ type DeleteData struct {
type CreateData struct {
Created int `json:"created"`
}
type ToggleController struct {
ID int `json:"id"`
Active bool `json:"active"`
}
+1
View File
@@ -24,6 +24,7 @@ func listColors(w http.ResponseWriter, r *http.Request) {
colors, err := db.GetAllColors()
if err != nil {
utils.ErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}
utils.SuccessResponse(w, http.StatusOK, colors)
}
+32
View File
@@ -13,6 +13,8 @@ import (
func RegisterControllerRoutes(mux *http.ServeMux) {
mux.HandleFunc("POST /api/v1/controllers", middleware.WithAdminAuth(createController))
mux.HandleFunc("DELETE /api/v1/controllers", middleware.WithAdminAuth(deleteController))
mux.HandleFunc("POST /api/v1/controllers/toggle/{ID}", middleware.WithAdminAuth(toggleControllerState))
}
func createController(w http.ResponseWriter, r *http.Request) {
@@ -41,3 +43,33 @@ func deleteController(w http.ResponseWriter, r *http.Request) {
}
utils.SuccessResponse(w, http.StatusOK, models.DeleteData{Deleted: req.ID})
}
func toggleControllerState(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
idStr := r.PathValue("ID")
id, err := utils.IDtoInt((idStr))
if err != nil {
utils.ErrorResponse(w, http.StatusBadRequest, err.Error())
return
}
if !db.ControllerExists((id)) {
utils.ErrorResponse(w, http.StatusNotFound, "Controller not found")
return
}
currentState, err := db.GetControllerState(id)
if err != nil {
utils.ErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}
err = db.SetControllerstate(!currentState, id)
if err != nil {
utils.ErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}
utils.SuccessResponse(w, http.StatusOK, models.ToggleController{ID: id, Active: !currentState})
}