func NewSMA(uri, password, iface string, serial uint32, scale float64) (api.Meter, error) {
	log := util.NewLogger("sma")
	once.Do(func() {
		sunny.Log = log.TRACE
	})

	sm := &SMA{
		mux:    util.NewWaiter(udpTimeout, func() { log.TRACE.Println("wait for initial value") }),
		log:    log,
		uri:    uri,
		iface:  iface,
		values: make(map[string]interface{}),
		scale:  scale,
	}

	conn, err := sunny.NewConnection(iface)
	if err != nil {
		return nil, fmt.Errorf("connection failed: %w", err)
	}

	switch {
	case uri != "":
		sm.device, err = conn.NewDevice(uri, password)
		if err != nil {
			return nil, err
		}

	case serial > 0:
		discoverer, ok := discoverers[iface]
		if !ok {
			discoverer = &smaDiscoverer{
				conn:    conn,
				devices: make(map[uint32]*sunny.Device),
			}

			go discoverer.run()

			discoverers[iface] = discoverer
		}

		sm.device = discoverer.deviceBySerial(serial)
		if sm.device == nil {
			return nil, fmt.Errorf("device not found: %d", serial)
		}
		sm.device.SetPassword(password)

	default:
		return nil, errors.New("missing uri or serial")
	}

	// decorate api.Battery in case of inverter
	var soc func() (float64, error)
	if !sm.device.IsEnergyMeter() {
		vals, err := sm.device.GetValues()
		if err != nil {
			return nil, err
		}

		if _, ok := vals["battery_charge"]; ok {
			soc = sm.soc
		}
	}

	go func() {
		for range time.NewTicker(time.Second).C {
			sm.updateValues()
		}
	}()

	return decorateSMA(sm, soc), nil
}
// NewSMA creates a SMA Meter
NewSMA creates a SMA Meter
// NewSMA creates a SMA Meter
func NewSMA(uri, password, iface string, serial uint32, scale float64) (api.Meter, error) {
	log := util.NewLogger("sma")
	once.Do(func() {
		sunny.Log = log.TRACE
	})
	sm := &SMA{
		mux:    util.NewWaiter(udpTimeout, func() { log.TRACE.Println("wait for initial value") }),
		log:    log,
		uri:    uri,
		iface:  iface,
		values: make(map[string]interface{}),
		scale:  scale,
	}
	conn, err := sunny.NewConnection(iface)
	if err != nil {
		return nil, fmt.Errorf("connection failed: %w", err)
	}
	switch {
	case uri != "":
		sm.device, err = conn.NewDevice(uri, password)
		if err != nil {
			return nil, err
		}
	case serial > 0:
		discoverer, ok := discoverers[iface]
		if !ok {
			discoverer = &smaDiscoverer{
				conn:    conn,
				devices: make(map[uint32]*sunny.Device),
			}
			go discoverer.run()
			discoverers[iface] = discoverer
		}
		sm.device = discoverer.deviceBySerial(serial)
		if sm.device == nil {
			return nil, fmt.Errorf("device not found: %d", serial)
		}
		sm.device.SetPassword(password)
	default:
		return nil, errors.New("missing uri or serial")
	}
	var soc func() (float64, error)
	if !sm.device.IsEnergyMeter() {
		vals, err := sm.device.GetValues()
		if err != nil {
			return nil, err
		}
		if _, ok := vals["battery_charge"]; ok {
			soc = sm.soc
		}
	}
	go func() {
		for range time.NewTicker(time.Second).C {
			sm.updateValues()
		}
	}()
	return decorateSMA(sm, soc), nil
}
func NewSMA ( uri , password , iface string , serial uint32 , scale float64 ) ( api . Meter , error ) { log := util . NewLogger ( " " ) once . Do ( func ( ) { sunny . Log = log . TRACE } ) sm := & SMA { mux : util . NewWaiter ( udpTimeout , func ( ) { log . TRACE . Println ( " " ) } ) , log : log , uri : uri , iface : iface , values : make ( map [ string ] interface { } ) , scale : scale , } conn , err := sunny . NewConnection ( iface ) if err != nil { return nil , fmt . Errorf ( " " , err ) } switch { case uri != " " : sm . device , err = conn . NewDevice ( uri , password ) if err != nil { return nil , err } case serial > 0 : discoverer , ok := discoverers [ iface ] if ! ok { discoverer = & smaDiscoverer { conn : conn , devices : make ( map [ uint32 ] * sunny . Device ) , } go discoverer . run ( ) discoverers [ iface ] = discoverer } sm . device = discoverer . deviceBySerial ( serial ) if sm . device == nil { return nil , fmt . Errorf ( " " , serial ) } sm . device . SetPassword ( password ) default : return nil , errors . New ( " " ) } var soc func ( ) ( float64 , error ) if ! sm . device . IsEnergyMeter ( ) { vals , err := sm . device . GetValues ( ) if err != nil { return nil , err } if _ , ok := vals [ " " ] ; ok { soc = sm . soc } } go func ( ) { for range time . NewTicker ( time . Second ) . C { sm . updateValues ( ) } } ( ) return decorateSMA ( sm , soc ) , nil }
NewSMA creates a SMA Meter
NewSMA creates a SMA Meter
// decorate api.Battery in case of inverter