Skip to content

Commit

Permalink
SMA: upgrade library (evcc-io#1155)
Browse files Browse the repository at this point in the history
  • Loading branch information
bboehmke authored Jun 19, 2021
1 parent c5c07da commit 5eb5a08
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 48 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ require (
github.com/thoas/go-funk v0.8.0
github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c
github.com/volkszaehler/mbmd v0.0.0-20210526131012-e1fec7232ed7
gitlab.com/bboehmke/sunny v0.12.2
gitlab.com/bboehmke/sunny v0.13.0
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a // indirect
golang.org/x/net v0.0.0-20210614182718-04defd469f4e
golang.org/x/oauth2 v0.0.0-20210615190721-d04028783cf1
Expand Down
7 changes: 5 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ github.com/denisbrodbeck/machineid v1.0.1 h1:geKr9qtkB876mXguW2X6TU4ZynleN6ezuMS
github.com/denisbrodbeck/machineid v1.0.1/go.mod h1:dJUwb7PTidGDeYyUBmXZ2GphQBbjJCrnectwCyxcUSI=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/dmarkham/enumer v1.5.2/go.mod h1:jZ3PNbNJDEkFGx54MlkSjnDQUo7445l7/guoKdh9cY8=
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/dylanmei/iso8601 v0.1.0 h1:812NGQDBcqquTfH5Yeo7lwR0nzx/cKdsmf3qMjPURUI=
Expand Down Expand Up @@ -520,6 +521,7 @@ github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pascaldekloe/name v0.0.0-20180628100202-0fd16699aae1/go.mod h1:eD5JxqMiuNYyFNmyY9rkJ/slN8y59oEu4Ei7F8OoKWQ=
github.com/pascaldekloe/name v1.0.0/go.mod h1:Z//MfYJnH4jVpQ9wkclwu2I2MkHmXTlT9wR5UZScttM=
github.com/pascaldekloe/name v1.0.1/go.mod h1:Z//MfYJnH4jVpQ9wkclwu2I2MkHmXTlT9wR5UZScttM=
github.com/paypal/gatt v0.0.0-20151011220935-4ae819d591cf/go.mod h1:+AwQL2mK3Pd3S+TUwg0tYQjid0q1txyNUJuuSmz8Kdk=
github.com/pbnjay/strptime v0.0.0-20140226051138-5c05b0d668c9/go.mod h1:6Hr+C/olSdkdL3z68MlyXWzwhvwmwN7KuUFXGb3PoOk=
Expand Down Expand Up @@ -658,8 +660,8 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
gitlab.com/bboehmke/sunny v0.12.2 h1:hKH1dfTmFIUpl/roQy8jkvIJLV9Frsaq6Y+cgn1C0Gk=
gitlab.com/bboehmke/sunny v0.12.2/go.mod h1:o0e0jA5xTQ7JpQ2FO/C8N21gSV47g64EC+dRUQui+CM=
gitlab.com/bboehmke/sunny v0.13.0 h1:B9bJQOEFyE/MhempCdvYe59Lb6ARZTjz3bJ7dDmAlk8=
gitlab.com/bboehmke/sunny v0.13.0/go.mod h1:F5AIuL7kYteSJFR5E+YEocxIdpyCXmtDciFmMQVjP88=
go.coder.com/go-tools v0.0.0-20190317003359-0c6a35b74a16/go.mod h1:iKV5yK9t+J5nG9O3uF6KYdPEz3dyfMyB15MN1rbQ8Qw=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
Expand Down Expand Up @@ -933,6 +935,7 @@ golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapK
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200221224223-e1da425f72fd/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
Expand Down
78 changes: 33 additions & 45 deletions meter/sma.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import (
"context"
"errors"
"fmt"
"os"
"sort"
"strings"
"sync"
"sync/atomic"
"text/tabwriter"
"time"

"github.com/andig/evcc/api"
Expand Down Expand Up @@ -79,7 +80,7 @@ type SMA struct {
mux *util.Waiter
uri string
iface string
values map[string]interface{}
values map[sunny.ValueID]interface{}
scale float64
device *sunny.Device
}
Expand Down Expand Up @@ -131,7 +132,7 @@ func NewSMA(uri, password, iface string, serial uint32, scale float64) (api.Mete
log: log,
uri: uri,
iface: iface,
values: make(map[string]interface{}),
values: make(map[sunny.ValueID]interface{}),
scale: scale,
}

Expand Down Expand Up @@ -178,7 +179,7 @@ func NewSMA(uri, password, iface string, serial uint32, scale float64) (api.Mete
return nil, err
}

if _, ok := vals["battery_charge"]; ok {
if _, ok := vals[sunny.BatteryCharge]; ok {
soc = sm.soc
}
}
Expand Down Expand Up @@ -208,7 +209,7 @@ func (sm *SMA) updateValues() {
}
}

func (sm *SMA) hasValue() (map[string]interface{}, error) {
func (sm *SMA) hasValue() (map[sunny.ValueID]interface{}, error) {
elapsed := sm.mux.LockWithTimeout()
defer sm.mux.Unlock()

Expand All @@ -222,40 +223,20 @@ func (sm *SMA) hasValue() (map[string]interface{}, error) {
// CurrentPower implements the api.Meter interface
func (sm *SMA) CurrentPower() (float64, error) {
values, err := sm.hasValue()

var power float64
if sm.device.IsEnergyMeter() {
power = sm.asFloat(values["active_power_plus"]) - sm.asFloat(values["active_power_minus"])
} else {
power = sm.asFloat(values["power_ac_total"])
}

return sm.scale * power, err
return sm.scale * (sm.asFloat(values[sunny.ActivePowerPlus]) - sm.asFloat(values[sunny.ActivePowerMinus])), err
}

// TotalEnergy implements the api.MeterEnergy interface
func (sm *SMA) TotalEnergy() (float64, error) {
values, err := sm.hasValue()

var energy float64
if sm.device.IsEnergyMeter() {
energy = sm.asFloat(values["active_energy_plus"]) / 3600000
} else {
energy = sm.asFloat(values["energy_total"]) / 1000
}

return energy, err
return sm.asFloat(values[sunny.ActiveEnergyPlus]) / 3600000, err
}

// Currents implements the api.MeterCurrent interface
func (sm *SMA) Currents() (float64, float64, float64, error) {
values, err := sm.hasValue()

measurements := []string{"l1_current", "l2_current", "l3_current"}
if !sm.device.IsEnergyMeter() {
measurements = []string{"current_ac1", "current_ac2", "current_ac3"}
}

measurements := []sunny.ValueID{sunny.CurrentL1, sunny.CurrentL2, sunny.CurrentL3}
var vals [3]float64
for i := 0; i < 3; i++ {
vals[i] = sm.asFloat(values[measurements[i]])
Expand All @@ -267,40 +248,47 @@ func (sm *SMA) Currents() (float64, float64, float64, error) {
// soc implements the api.Battery interface
func (sm *SMA) soc() (float64, error) {
values, err := sm.hasValue()
return sm.asFloat(values["battery_charge"]), err
return sm.asFloat(values[sunny.BatteryCharge]), err
}

// Diagnose implements the api.Diagnosis interface
func (sm *SMA) Diagnose() {
fmt.Printf(" IP: %s\n", sm.device.Address())
fmt.Printf(" Serial: %d\n", sm.device.SerialNumber())
fmt.Printf(" EnergyMeter: %v\n", sm.device.IsEnergyMeter())
fmt.Printf("\n")
w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0)

fmt.Fprintf(w, " IP:\t%s\n", sm.device.Address())
fmt.Fprintf(w, " Serial:\t%d\n", sm.device.SerialNumber())
fmt.Fprintf(w, " EnergyMeter:\t%v\n", sm.device.IsEnergyMeter())
fmt.Fprintln(w)

if name, err := sm.device.GetDeviceName(); err == nil {
fmt.Printf(" Name: %s\n", name)
fmt.Fprintf(w, " Name:\t%s\n", name)
}

if devClass, err := sm.device.GetDeviceClass(); err == nil {
fmt.Printf(" Device Class: 0x%X\n", devClass)
fmt.Fprintf(w, " Device Class:\t0x%X\n", devClass)
}
fmt.Printf("\n")
fmt.Fprintln(w)

if values, err := sm.device.GetValues(); err == nil {
keys := make([]string, 0, len(values))
keyLength := 0
ids := make([]sunny.ValueID, 0, len(values))
for k := range values {
keys = append(keys, k)
if len(k) > keyLength {
keyLength = len(k)
}
ids = append(ids, k)
}
sort.Strings(keys)

for _, k := range keys {
fmt.Printf(" %s:%s %v %s\n", k, strings.Repeat(" ", keyLength-len(k)), values[k], sm.device.GetValueInfo(k).Unit)
sort.Slice(ids, func(i, j int) bool {
return ids[i].String() < ids[j].String()
})

for _, id := range ids {
switch values[id].(type) {
case float64:
fmt.Fprintf(w, " %s:\t%f %s\n", id.String(), values[id], sunny.GetValueInfo(id).Unit)
default:
fmt.Fprintf(w, " %s:\t%v %s\n", id.String(), values[id], sunny.GetValueInfo(id).Unit)
}
}
}
w.Flush()
}

func (sm *SMA) asFloat(value interface{}) float64 {
Expand Down

0 comments on commit 5eb5a08

Please sign in to comment.