diff --git a/cmd/configure.go b/cmd/configure.go index 640b24300..bd3b72de6 100644 --- a/cmd/configure.go +++ b/cmd/configure.go @@ -15,7 +15,7 @@ import ( // configureCmd represents the configure command var configureCmd = &cobra.Command{ Use: "configure", - Short: "Create an EVCC configuration", + Short: "Create configuration (evcc.yaml)", Run: runConfigure, } diff --git a/cmd/flags.go b/cmd/flags.go index e4dbb4736..19c3976bd 100644 --- a/cmd/flags.go +++ b/cmd/flags.go @@ -9,7 +9,7 @@ import ( const ( flagSqlite = "sqlite" - flagSqliteDescription = "Sqlite database file" + flagSqliteDescription = "SQlite database file" flagHeaders = "log-headers" flagHeadersDescription = "Log headers" diff --git a/cmd/sunspec.go b/cmd/sunspec.go new file mode 100644 index 000000000..eace9a498 --- /dev/null +++ b/cmd/sunspec.go @@ -0,0 +1,102 @@ +package cmd + +import ( + "fmt" + "os" + "strings" + "text/tabwriter" + + sunspec "github.com/andig/gosunspec" + bus "github.com/andig/gosunspec/modbus" + "github.com/andig/gosunspec/smdx" + "github.com/evcc-io/evcc/util" + "github.com/spf13/cobra" + "github.com/spf13/viper" + "github.com/volkszaehler/mbmd/meters" + quirks "github.com/volkszaehler/mbmd/meters/sunspec" +) + +// sunspecCmd represents the charger command +var sunspecCmd = &cobra.Command{ + Use: "sunspec ", + Short: "Dump SunSpec model information", + Args: cobra.ExactArgs(1), + Run: runSunspec, +} + +var slaveID *int + +func init() { + rootCmd.AddCommand(sunspecCmd) + + slaveID = sunspecCmd.Flags().IntP("id", "i", 1, "Slave id") +} + +func pf(format string, v ...interface{}) { + format = strings.TrimSuffix(format, "\n") + "\n" + fmt.Printf(format, v...) +} + +func modelName(m sunspec.Model) string { + model := smdx.GetModel(uint16(m.Id())) + if model == nil { + return "" + } + return model.Name +} + +func runSunspec(cmd *cobra.Command, args []string) { + util.LogLevel(viper.GetString("log"), nil) + + conn := meters.NewTCP(args[0]) + conn.Slave(uint8(*slaveID)) + conn.Logger(log.TRACE) + + in, err := bus.Open(conn.ModbusClient()) + if err != nil && in == nil { + log.FATAL.Fatal(err) + } else if err != nil { + log.WARN.Printf("warning: device opened with partial result: %v", err) // log error but continue + } + + tw := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0) + + in.Do(func(d sunspec.Device) { + d.Do(func(m sunspec.Model) { + pf("--------- Model %d %s ---------", m.Id(), modelName(m)) + + blocknum := 0 + m.Do(func(b sunspec.Block) { + if blocknum > 0 { + fmt.Fprintf(tw, "-- Block %d --\n", blocknum) + } + blocknum++ + + err = b.Read() + if err != nil { + log.INFO.Printf("skipping due to read error: %v", err) + return + } + + b.Do(func(p sunspec.Point) { + t := p.Type()[0:3] + v := p.Value() + if p.NotImplemented() { + v = "n/a" + } else if t == "int" || t == "uin" || t == "acc" { + // for time being, always to this + quirks.FixKostal(p) + + v = p.ScaledValue() + v = fmt.Sprintf("%.2f", v) + } + + vs := fmt.Sprintf("%17v", v) + fmt.Fprintf(tw, "%s\t%s\t %s\n", p.Id(), vs, p.Type()) + }) + }) + + tw.Flush() + }) + }) +} diff --git a/go.mod b/go.mod index 22730add3..f45bdaaa2 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ require ( github.com/BurntSushi/toml v1.2.0 github.com/Masterminds/sprig/v3 v3.2.2 github.com/PuerkitoBio/goquery v1.8.0 + github.com/andig/gosunspec v0.0.0-20211108155140-af2e73b86e71 github.com/asaskevich/EventBus v0.0.0-20200907212545-49d423059eef github.com/avast/retry-go/v3 v3.1.1 github.com/aws/aws-sdk-go v1.44.119 @@ -97,7 +98,6 @@ require ( cloud.google.com/go/compute v1.10.0 // indirect github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/semver/v3 v3.1.1 // indirect - github.com/andig/gosunspec v0.0.0-20211108155140-af2e73b86e71 // indirect github.com/andybalholm/cascadia v1.3.1 // indirect github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect github.com/beorn7/perks v1.0.1 // indirect