diff --git a/cmd/confighandler.go b/cmd/confighandler.go index 284debb9..39edf6f8 100644 --- a/cmd/confighandler.go +++ b/cmd/confighandler.go @@ -7,7 +7,7 @@ import ( "strconv" "strings" "time" - + "github.com/volkszaehler/mbmd/server" "github.com/volkszaehler/mbmd/meters" "github.com/volkszaehler/mbmd/meters/rs485" "github.com/volkszaehler/mbmd/meters/sunspec" @@ -65,15 +65,17 @@ type DeviceConfig struct { // DeviceConfigHandler creates map of meter managers from given configuration type DeviceConfigHandler struct { - DefaultDevice string - Managers map[string]*meters.Manager + DefaultDevice string + Managers map[string]*meters.Manager + Names server.NameMap } // NewDeviceConfigHandler creates a configuration handler func NewDeviceConfigHandler() *DeviceConfigHandler { conf := &DeviceConfigHandler{ - Managers: make(map[string]*meters.Manager), - } + Managers: make(map[string]*meters.Manager), + Names: make(server.NameMap), +} return conf } @@ -155,7 +157,6 @@ func (conf *DeviceConfigHandler) createDeviceForManager( // CreateDevice creates new device and adds it to the connection manager func (conf *DeviceConfigHandler) CreateDevice(devConf DeviceConfig) { if devConf.Adapter == "" { - // find default adapter if len(conf.Managers) == 1 { for a := range conf.Managers { log.Printf("config: using default adapter %s for device %v", a, devConf) @@ -170,8 +171,20 @@ func (conf *DeviceConfigHandler) CreateDevice(devConf DeviceConfig) { if !ok { log.Fatalf("Missing adapter configuration for device %v", devConf) } + meter := conf.createDeviceForManager(manager, devConf.Type, devConf.SubDevice) + + if devConf.Name != "" { + if conf.Names[devConf.Adapter] == nil { + conf.Names[devConf.Adapter] = make(map[uint8]map[int]string) + } + if conf.Names[devConf.Adapter][devConf.ID] == nil { + conf.Names[devConf.Adapter][devConf.ID] = make(map[int]string) + } + conf.Names[devConf.Adapter][devConf.ID][devConf.SubDevice] = devConf.Name + } + if err := manager.Add(devConf.ID, meter); err != nil { log.Fatalf("Error adding device %v: %v.", devConf, err) } @@ -190,7 +203,6 @@ func (conf *DeviceConfigHandler) CreateDeviceFromSpec(deviceDef string, timeout if len(deviceSplit) == 2 { connSpec = deviceSplit[1] } - if connSpec == "" { log.Fatalf("Cannot parse connect string- missing physical device or connection for %s. See -h for help.", deviceDef) } @@ -222,12 +234,10 @@ func (conf *DeviceConfigHandler) CreateDeviceFromSpec(deviceDef string, timeout log.Fatalf("Error parsing device id %s: %v. See -h for help.", devID, err) } - // If this is an RTU over TCP device, a default RTU over TCP should already - // have been created of the --rtu flag was specified. We'll not re-check this here. manager := conf.ConnectionManager(connSpec, false, 0, "", timeout) - meter := conf.createDeviceForManager(manager, meterType, subdevice) + if err := manager.Add(uint8(id), meter); err != nil { log.Fatalf("Error adding device %s: %v. See -h for help.", meterDef, err) } -} +} \ No newline at end of file diff --git a/cmd/run.go b/cmd/run.go index 9acceb94..b52c21c8 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -259,7 +259,7 @@ func run(cmd *cobra.Command, args []string) { } // query engine - qe := server.NewQueryEngine(confHandler.Managers) + qe := server.NewQueryEngine(confHandler.Managers, confHandler.Names) // results- and control channels rc := make(chan server.QuerySnip) diff --git a/server/handler.go b/server/handler.go index 6cd2bc7f..541a5705 100644 --- a/server/handler.go +++ b/server/handler.go @@ -7,7 +7,8 @@ import ( "log" "math" "time" - + "regexp" + "strings" "github.com/volkszaehler/mbmd/meters" ) @@ -17,33 +18,51 @@ const ( initDelay = 3 * time.Second ) +type NameMap map[string]map[uint8]map[int]string + +func sanitizeName(s string) string { + s = strings.TrimSpace(s) + s = strings.ReplaceAll(s, " ", "_") + re := regexp.MustCompile(`[^A-Za-z0-9_-]+`) + return re.ReplaceAllString(s, "_") +} + // Handler is responsible for querying a single connection type Handler struct { - ID int - Manager *meters.Manager - status map[string]*RuntimeInfo + Conn string + ID int + Manager *meters.Manager + status map[string]*RuntimeInfo + names NameMap } // NewHandler creates a connection handler. The handler is responsible // for querying all devices attached to the connection. -func NewHandler(id int, m *meters.Manager) *Handler { - handler := &Handler{ - ID: id, - Manager: m, - status: make(map[string]*RuntimeInfo), - } - - return handler +func NewHandler(conn string, id int, m *meters.Manager, names NameMap) *Handler { + return &Handler{ + Conn: conn, + ID: id, + Manager: m, + status: make(map[string]*RuntimeInfo), + names: names, + } } // deviceID creates a unique id per device func (h *Handler) deviceID(id uint8, dev meters.Device) string { - desc := dev.Descriptor() - devID := fmt.Sprintf("%s%d.%d", desc.Type, h.ID, id) - if desc.SubDevice > 0 { - devID = fmt.Sprintf("%s.%d", devID, desc.SubDevice) - } - return devID + desc := dev.Descriptor() + devID := fmt.Sprintf("%s%d.%d", desc.Type, h.ID, id) + if desc.SubDevice > 0 { + devID = fmt.Sprintf("%s.%d", devID, desc.SubDevice) + } + if sub1, ok := h.names[h.Conn]; ok { + if sub2, ok2 := sub1[id]; ok2 { + if name, ok3 := sub2[desc.SubDevice]; ok3 && name != "" { + return sanitizeName(name) + } + } + } + return devID } // Run initializes and queries every device attached to the handler's connection diff --git a/server/queryengine.go b/server/queryengine.go index d285c68c..4bc26a88 100644 --- a/server/queryengine.go +++ b/server/queryengine.go @@ -22,7 +22,7 @@ type QueryEngine struct { } // NewQueryEngine creates new query engine -func NewQueryEngine(managers map[string]*meters.Manager) *QueryEngine { +func NewQueryEngine(managers map[string]*meters.Manager, names NameMap) *QueryEngine { handlers := make(map[string]*Handler) // sort handlers by name @@ -36,7 +36,7 @@ func NewQueryEngine(managers map[string]*meters.Manager) *QueryEngine { continue } - handlers[conn] = NewHandler(len(handlers)+1, m) + handlers[conn] = NewHandler(conn, len(handlers)+1, m, names) } qe := &QueryEngine{