feat: remove state message retrieval and associated SQLite storage
This commit is contained in:
27
API.md
27
API.md
@@ -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
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -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
1
go.mod
@@ -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 (
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user