refactor(db): map room and node on REST API
Signed-off-by: Klagarge <remi@heredero.ch>
This commit is contained in:
@@ -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{})
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user