diff --git a/evcc.dist.yaml b/evcc.dist.yaml index 7344620d3..7fde02ce4 100644 --- a/evcc.dist.yaml +++ b/evcc.dist.yaml @@ -69,7 +69,8 @@ meters: timeout: 3s # kill script after 3 seconds - name: sma type: sma # SMA Home Manager 2.0 or SMA Energy Meter 30 - uri: 192.168.1.4 # IP address of the device + serial: 1234567890 # Serial number of the device, if this is defined uri is not needed! + uri: 192.168.1.4 # IP address of the device, if this is defined serial is not needed! - name: sdm type: modbus model: sdm diff --git a/meter/sma.go b/meter/sma.go index 25b735b3c..3ebc0d61a 100644 --- a/meter/sma.go +++ b/meter/sma.go @@ -19,6 +19,7 @@ const ( type SMA struct { log *util.Logger uri string + serial string power float64 energy float64 powerO sma.Obis @@ -32,30 +33,38 @@ type SMA struct { // NewSMAFromConfig creates a SMA Meter from generic config func NewSMAFromConfig(log *util.Logger, other map[string]interface{}) api.Meter { cc := struct { - URI, Power, Energy string + URI, Serial, Power, Energy string }{} util.DecodeOther(log, other, &cc) - return NewSMA(cc.URI, cc.Power, cc.Energy) + return NewSMA(cc.URI, cc.Serial, cc.Power, cc.Energy) } // NewSMA creates a SMA Meter -func NewSMA(uri, power, energy string) api.Meter { +func NewSMA(uri, serial, power, energy string) api.Meter { log := util.NewLogger("sma ") sm := &SMA{ log: log, uri: uri, + serial: serial, powerO: sma.Obis(power), energyO: sma.Obis(energy), recv: make(chan sma.Telegram), } if sma.Instance == nil { - sma.Instance = sma.New(log, sm.uri) + sma.Instance = sma.New(log) } - sma.Instance.Subscribe(uri, sm.recv) + // we only need to subscribe to one of the two possible identifiers + if uri != "" { + sma.Instance.Subscribe(uri, sm.recv) + } else if serial != "" { + sma.Instance.Subscribe(serial, sm.recv) + } else { + log.FATAL.Fatalf("config: missing uri or serial") + } go sm.receive() diff --git a/meter/sma/listener.go b/meter/sma/listener.go index f0c68a831..c97e24de1 100644 --- a/meter/sma/listener.go +++ b/meter/sma/listener.go @@ -93,7 +93,7 @@ type Listener struct { } // New creates a Listener -func New(log *util.Logger, addr string) *Listener { +func New(log *util.Logger) *Listener { // Parse the string address gaddr, err := net.ResolveUDPAddr("udp4", multicastAddr) if err != nil { @@ -178,7 +178,7 @@ func (l *Listener) listen() { } // Subscribe adds a client address and message channel -func (l *Listener) Subscribe(addr string, c chan<- Telegram) { +func (l *Listener) Subscribe(identifier string, c chan<- Telegram) { l.mux.Lock() defer l.mux.Unlock() @@ -186,15 +186,15 @@ func (l *Listener) Subscribe(addr string, c chan<- Telegram) { l.clients = make(map[string]chan<- Telegram) } - l.clients[addr] = c + l.clients[identifier] = c } func (l *Listener) send(msg Telegram) { l.mux.Lock() defer l.mux.Unlock() - for addr, client := range l.clients { - if addr == msg.Addr { + for identifier, client := range l.clients { + if identifier == msg.Addr || identifier == msg.Serial { select { case client <- msg: default: