feat: remove state message retrieval and associated SQLite storage

This commit is contained in:
2026-02-04 16:29:32 +01:00
parent 152d5b82cd
commit 014885db6c
5 changed files with 3 additions and 85 deletions

27
API.md
View File

@@ -795,32 +795,6 @@ Publish a ping message to the MQTT broker for testing.
---
### Get State Messages
Retrieve stored state messages from SQLite storage.
**Endpoint**: `GET /messages`
**Authentication**: Required
**Query Parameters**:
- `page`: Page number (default: 0)
**Response** (200 OK):
```json
{
"messages": [
{
"id": 1,
"payload": "message content",
"timestamp": "2026-01-14T10:00:00Z"
}
]
}
```
---
## MQTT Integration
### Device Discovery
@@ -963,7 +937,6 @@ password = ""
4. **UUID Format**: Always use valid UUID v4 format for device, sensor, and actor IDs
5. **Date Format**: Use RFC3339 format for all timestamp fields
6. **Device Discovery**: Devices can self-register via MQTT discovery messages
7. **State Messages**: Messages on topics starting with `state:` are automatically stored
---

View File

@@ -8,7 +8,6 @@ import (
"net/http"
"os"
"os/signal"
"strings"
"syscall"
"time"
@@ -20,7 +19,6 @@ import (
"git.piskot.si/SeminarM2/lambdaiot-core/internal/handler"
"git.piskot.si/SeminarM2/lambdaiot-core/internal/middleware"
mqttclient "git.piskot.si/SeminarM2/lambdaiot-core/internal/mqtt"
"git.piskot.si/SeminarM2/lambdaiot-core/internal/storage"
)
func main() {
@@ -52,26 +50,10 @@ func main() {
if cfg.Server.Port != 0 {
addr = fmt.Sprintf(":%d", cfg.Server.Port)
}
// connect to MQTT broker (best-effort)
var mq *mqttclient.Client
var checker *devicecheck.Checker
var checkCancel context.CancelFunc
// initialize sqlite for state messages
var stateDB *storage.DB
{
dbPath := os.Getenv("SQLITE_PATH")
if dbPath == "" {
dbPath = "state_messages.db"
}
dbInit, err := storage.Init(dbPath)
if err != nil {
log.Printf("warning: sqlite init failed: %v", err)
} else {
stateDB = dbInit
storage.SetDefault(stateDB)
}
}
if cfg.MQTT.Broker != "" {
mqc, err := mqttclient.Connect(cfg.MQTT)
if err != nil {
@@ -92,12 +74,6 @@ func main() {
if checker != nil {
checker.HandleMessage(p)
}
// if topic starts with state: -> store in sqlite
if strings.HasPrefix(t, "state:") {
if storage.Default != nil {
_ = storage.Default.InsertMessage(string(p), time.Now())
}
}
}
if err := mq.Subscribe(cfg.MQTT.Topic, handlerFn); err != nil {
log.Printf("warning: mqtt subscribe failed: %v", err)
@@ -149,7 +125,6 @@ func main() {
auth.Use(middleware.AuthMiddleware(cfg.Server.JWTSecret))
auth.GET("/protected", h.Protected)
auth.GET("/mqttping", h.MQTTPing)
auth.GET("/messages", handler.GetMessages)
auth.GET("/sensors", h.GetSensors)
auth.GET("/sensors/:id", h.GetSensor)
auth.POST("/sensors/:id/trigger", h.TriggerSensor)
@@ -202,9 +177,6 @@ func main() {
if checkCancel != nil {
checkCancel()
}
if stateDB != nil {
stateDB.Close()
}
log.Println("server exiting")
}

1
go.mod
View File

@@ -8,7 +8,6 @@ require (
github.com/joho/godotenv v1.5.1
github.com/pelletier/go-toml/v2 v2.0.6
github.com/DATA-DOG/go-sqlmock v1.5.2
github.com/mattn/go-sqlite3 v1.14.20
)
require (

View File

@@ -10,7 +10,6 @@ import (
"time"
"git.piskot.si/SeminarM2/lambdaiot-core/internal/mqtt"
"git.piskot.si/SeminarM2/lambdaiot-core/internal/storage"
"github.com/gin-gonic/gin"
"github.com/golang-jwt/jwt/v5"
"github.com/google/uuid"
@@ -502,29 +501,6 @@ func Protected(c *gin.Context) {
c.JSON(http.StatusUnauthorized, gin.H{"error": "no claims"})
}
// GetMessages returns the last 100 state messages with optional pagination
// query parameter: ?page=N (0-based)
func GetMessages(c *gin.Context) {
page := 0
if p := c.Query("page"); p != "" {
if n, err := strconv.Atoi(p); err == nil && n >= 0 {
page = n
}
}
limit := 100
offset := page * limit
if storage.Default == nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "storage not initialized"})
return
}
msgs, err := storage.Default.QueryMessages(limit, offset)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"messages": msgs})
}
// Actor CRUD
func (h *Handler) CreateActor(c *gin.Context) {
var req struct {

View File

@@ -6,11 +6,10 @@ Repository: https://git.piskot.si/SeminarM2/lambdaiot-core
## Features ✅
- HTTP API with health, greeting, auth, device CRUD, sensor creation, MQTT ping, and stored message retrieval
- HTTP API with health, greeting, auth, device CRUD, sensor creation, and MQTT ping
- JWT-based auth middleware with demo login (`admin`/`password`)
- MQTT client with startup publish and best-effort subscription to persist `state:` topics into SQLite
- SQLite sidecar (file) for recent MQTT state messages
- Multi-stage `Dockerfile` (CGO-enabled for sqlite3) and `Makefile` for common tasks
- MQTT client with startup publish and best-effort subscription
- Multi-stage `Dockerfile` and `Makefile` for common tasks
- `test/docker-compose.yml` spins up MySQL, Mosquitto, phpMyAdmin, and the server for local integration
---
@@ -66,7 +65,6 @@ The compose file seeds the database from `ai-improved.sql` and exposes:
- Actors (JWT): `GET /actors`, `GET /actors/:id`, `POST /actors`, `PUT /actors/:id`, `DELETE /actors/:id`
- Sensor readings (JWT): `GET /sensor-readings`, `GET /sensor-readings/:id`, `POST /sensor-readings`, `PUT /sensor-readings/:id`, `DELETE /sensor-readings/:id` (optional `sensor_id` filter and pagination via `limit`, `page`)
- `GET /mqttping` — publish timestamp to MQTT default topic (JWT)
- `GET /messages` — last stored MQTT state messages from SQLite (JWT)
### Environment