refactor(db): map room and node on REST API

Signed-off-by: Klagarge <remi@heredero.ch>
This commit is contained in:
2026-05-21 12:23:12 +02:00
parent 04c3883744
commit ef51f9b3ed
2 changed files with 44 additions and 10 deletions

View File

@@ -79,6 +79,17 @@ func (c *MappingConfig) GetRoom(nodeID string) (string, bool) {
return room, ok return room, ok
} }
// NodesForRoom returns the list of node IDs that belong to the given room.
func (c *MappingConfig) NodesForRoom(room string) []string {
var nodes []string
for nodeID, r := range c.nodeToRoom {
if r == room {
nodes = append(nodes, nodeID)
}
}
return nodes
}
// Rooms returns the list of all room names defined in the mapping. // Rooms returns the list of all room names defined in the mapping.
func (c *MappingConfig) Rooms() []string { func (c *MappingConfig) Rooms() []string {
seen := make(map[string]struct{}) seen := make(map[string]struct{})

View File

@@ -3,12 +3,12 @@ package rest
import ( import (
"context" "context"
"fmt" "fmt"
_ "gateway/docs"
"gateway/influx" "gateway/influx"
"net/http" "net/http"
"regexp" "regexp"
"slices" "slices"
"strings"
_ "gateway/docs"
"github.com/gin-contrib/cors" "github.com/gin-contrib/cors"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
@@ -16,21 +16,22 @@ import (
ginSwagger "github.com/swaggo/gin-swagger" ginSwagger "github.com/swaggo/gin-swagger"
) )
// RoomLister is an interface for getting the list of rooms from the mapping. // RoomMapper is an interface for mapping node IDs to rooms and listing rooms.
type RoomLister interface { type RoomMapper interface {
Rooms() []string Rooms() []string
NodesForRoom(room string) []string
} }
type RestGateway struct { type RestGateway struct {
influxGateway *influx.InfluxGateway influxGateway *influx.InfluxGateway
mapping RoomLister mapping RoomMapper
engine *gin.Engine engine *gin.Engine
measurementName string measurementName string
username string username string
password string password string
} }
func NewRestGateway(influxGateway *influx.InfluxGateway, mapping RoomLister, measurementName string, username, password string) *RestGateway { func NewRestGateway(influxGateway *influx.InfluxGateway, mapping RoomMapper, measurementName string, username, password string) *RestGateway {
g := &RestGateway{ g := &RestGateway{
influxGateway: influxGateway, influxGateway: influxGateway,
mapping: mapping, mapping: mapping,
@@ -75,6 +76,15 @@ func (g *RestGateway) setupRoutes() {
g.engine.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler)) g.engine.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
} }
// buildNodeFilter builds a SQL WHERE clause fragment matching any of the given node IDs.
func buildNodeFilter(nodes []string) string {
parts := make([]string, len(nodes))
for i, n := range nodes {
parts[i] = fmt.Sprintf(`"node" = '%s'`, n)
}
return "(" + strings.Join(parts, " OR ") + ")"
}
func (g *RestGateway) Run(addr string) error { func (g *RestGateway) Run(addr string) error {
return g.engine.Run(addr) return g.engine.Run(addr)
} }
@@ -110,8 +120,15 @@ func (g *RestGateway) getRooms(c *gin.Context) {
func (g *RestGateway) getRoomCurrent(c *gin.Context) { func (g *RestGateway) getRoomCurrent(c *gin.Context) {
roomID := c.Param("room-id") roomID := c.Param("room-id")
// Get the last record for the specific room nodes := g.mapping.NodesForRoom(roomID)
query := fmt.Sprintf(`SELECT * FROM "%s" WHERE "room" = '%s' AND time > now() - INTERVAL '1 days' ORDER BY time DESC LIMIT 1`, g.measurementName, roomID) if len(nodes) == 0 {
c.JSON(http.StatusNotFound, gin.H{"error": "Room not found in mapping"})
return
}
nodeFilter := buildNodeFilter(nodes)
// Get the last record for the specific room by matching node IDs
query := fmt.Sprintf(`SELECT * FROM "%s" WHERE %s AND time > now() - INTERVAL '1 days' ORDER BY time DESC LIMIT 1`, g.measurementName, nodeFilter)
// Using context.Background() as seen in working snippet // Using context.Background() as seen in working snippet
it, err := g.influxGateway.Query(context.Background(), query) it, err := g.influxGateway.Query(context.Background(), query)
@@ -149,8 +166,14 @@ func (g *RestGateway) getRoomHistory(c *gin.Context) {
roomID := c.Param("room-id") roomID := c.Param("room-id")
window := c.DefaultQuery("window", "1 day") window := c.DefaultQuery("window", "1 day")
query := fmt.Sprintf(` SELECT * FROM "%s" WHERE "room" = '%s' AND time > now() - INTERVAL '%s' ORDER BY time ASC nodes := g.mapping.NodesForRoom(roomID)
`, g.measurementName, roomID, window) if len(nodes) == 0 {
c.JSON(http.StatusNotFound, gin.H{"error": "Room not found in mapping"})
return
}
nodeFilter := buildNodeFilter(nodes)
query := fmt.Sprintf(`SELECT * FROM "%s" WHERE %s AND time > now() - INTERVAL '%s' ORDER BY time ASC`, g.measurementName, nodeFilter, window)
// Using context.Background() as seen in working snippet // Using context.Background() as seen in working snippet
it, err := g.influxGateway.Query(context.Background(), query) it, err := g.influxGateway.Query(context.Background(), query)