forked from evcc-io/evcc
-
Notifications
You must be signed in to change notification settings - Fork 0
/
sunspec.go
102 lines (83 loc) · 2.2 KB
/
sunspec.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
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 <connection>",
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()
})
})
}