From c34ec94a6b8b852eb9161011cfa28eab0927cf0d Mon Sep 17 00:00:00 2001 From: Klagarge Date: Thu, 21 May 2026 12:40:39 +0200 Subject: [PATCH] feat(db): get mapping dynamically from file Assisted-by: Junie:claude-sonnet-4.6 Signed-off-by: Klagarge --- db/src/main.go | 10 +++------- db/src/mapping.go | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/db/src/main.go b/db/src/main.go index 6d52410..1bf10be 100644 --- a/db/src/main.go +++ b/db/src/main.go @@ -92,13 +92,9 @@ func influxConnection() *influx.InfluxGateway { // @BasePath /api/v1 // @securityDefinitions.basic BasicAuth func main() { - // Load mapping configuration + // Load mapping configuration (reloaded dynamically on each access) mappingPath := getEnv("MAPPING_CONFIG_PATH", "mapping.json") - mapping, err := LoadMapping(mappingPath) - if err != nil { - log.Printf("[Main] Warning: could not load mapping file: %v. Using defaults.", err) - mapping = EmptyMapping() - } + mapping := NewDynamicMapping(mappingPath) mqttGateway := mqttConnection() defer mqttGateway.Disconnect() @@ -112,7 +108,7 @@ func main() { provenceMeasurement := point.CreateMeasurement[ProvenceData](measurementName) // The incoming MQTT topic structure is: //update topicStructur := []string{"gateway", "node"} - err = mqtt.SubscribeTyped(mqttGateway, "+/+/update", provenceMeasurement, topicStructur, func(dp point.DataPoint[ProvenceData]) { + err := mqtt.SubscribeTyped(mqttGateway, "+/+/update", provenceMeasurement, topicStructur, func(dp point.DataPoint[ProvenceData]) { var gatewayID, nodeID string for _, tag := range dp.Tags() { switch tag.Subject { diff --git a/db/src/mapping.go b/db/src/mapping.go index e7ca109..774bf7a 100644 --- a/db/src/mapping.go +++ b/db/src/mapping.go @@ -23,6 +23,45 @@ type MappingConfig struct { nodeToRoom map[string]string } +// DynamicMapping reloads the mapping file on every access so that changes +// to the JSON file take effect without restarting the programme. +type DynamicMapping struct { + path string +} + +// NewDynamicMapping creates a DynamicMapping that reads from the given path. +func NewDynamicMapping(path string) *DynamicMapping { + return &DynamicMapping{path: path} +} + +func (d *DynamicMapping) load() *MappingConfig { + cfg, err := LoadMapping(d.path) + if err != nil { + return EmptyMapping() + } + return cfg +} + +func (d *DynamicMapping) GetCampus(gatewayID string) (string, bool) { + return d.load().GetCampus(gatewayID) +} + +func (d *DynamicMapping) GetRoom(nodeID string) (string, bool) { + return d.load().GetRoom(nodeID) +} + +func (d *DynamicMapping) NodesForRoom(room string) []string { + return d.load().NodesForRoom(room) +} + +func (d *DynamicMapping) AllNodes() []string { + return d.load().AllNodes() +} + +func (d *DynamicMapping) Rooms() []string { + return d.load().Rooms() +} + // EmptyMapping returns a MappingConfig with no entries. // GetCampus and GetRoom will return their "unknown_*" fallback values. func EmptyMapping() *MappingConfig {