forked from evcc-io/evcc
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcfos.go
96 lines (74 loc) · 2.37 KB
/
cfos.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
package meter
import (
"encoding/binary"
"github.com/evcc-io/evcc/api"
"github.com/evcc-io/evcc/util"
"github.com/evcc-io/evcc/util/modbus"
)
const (
cfosRegEnergy = 8058 // energy reading
cfosRegPower = 8062 // power reading
)
// var cfosRegCurrents = []uint16{8064, 8066, 8068} // current readings
// CfosPowerBrain is a meter implementation for cFos PowerBrain wallboxes.
// It uses Modbus TCP to communicate at modbus client id 1 and power meters at id 2 and 3.
// https://www.cfos-emobility.de/en-gb/cfos-power-brain/modbus-registers.htm
type CfosPowerBrain struct {
conn *modbus.Connection
}
func init() {
registry.Add("cfos", NewCfosPowerBrainFromConfig)
}
// NewCfosPowerBrainFromConfig creates a cFos meter from generic config
func NewCfosPowerBrainFromConfig(other map[string]interface{}) (api.Meter, error) {
cc := modbus.TcpSettings{
ID: 1,
}
if err := util.DecodeOther(other, &cc); err != nil {
return nil, err
}
return NewCfosPowerBrain(cc.URI, cc.ID)
}
// NewCfosPowerBrain creates a cFos meter
func NewCfosPowerBrain(uri string, id uint8) (*CfosPowerBrain, error) {
conn, err := modbus.NewConnection(uri, "", "", 0, modbus.Tcp, id)
if err != nil {
return nil, err
}
log := util.NewLogger("cfos")
conn.Logger(log.TRACE)
wb := &CfosPowerBrain{
conn: conn,
}
return wb, nil
}
// CurrentPower implements the api.Meter interface
func (wb *CfosPowerBrain) CurrentPower() (float64, error) {
b, err := wb.conn.ReadHoldingRegisters(cfosRegPower, 2)
if err != nil {
return 0, err
}
return float64(binary.BigEndian.Uint32(b)), err
}
var _ api.MeterEnergy = (*CfosPowerBrain)(nil)
// TotalEnergy implements the api.MeterEnergy interface
func (wb *CfosPowerBrain) TotalEnergy() (float64, error) {
b, err := wb.conn.ReadHoldingRegisters(cfosRegEnergy, 4)
if err != nil {
return 0, err
}
return float64(binary.BigEndian.Uint64(b)) / 1e3, err
}
// var _ api.PhaseCurrents = (*CfosPowerBrain)(nil)
// // Currents implements the api.PhaseCurrents interface
// func (wb *CfosPowerBrain) Currents() (float64, float64, float64, error) {
// var currents []float64
// for _, regCurrent := range cfosRegCurrents {
// b, err := wb.conn.ReadHoldingRegisters(regCurrent, 2)
// if err != nil {
// return 0, 0, 0, err
// }
// currents = append(currents, float64(binary.BigEndian.Uint32(b))/10)
// }
// return currents[0], currents[1], currents[2], nil
// }