Read grid and charge meter currents (#272)
This commit is contained in:
parent
12cb57645c
commit
0922bc774c
4 changed files with 81 additions and 15 deletions
|
|
@ -405,13 +405,21 @@ func (lp *LoadPoint) updateChargerStatus() error {
|
|||
|
||||
// detectPhases uses MeterCurrent interface to count phases with current >=1A
|
||||
func (lp *LoadPoint) detectPhases() {
|
||||
if phaseMeter, ok := lp.chargeMeter.(api.MeterCurrent); ok {
|
||||
i1, i2, i3, err := phaseMeter.Currents()
|
||||
if err != nil {
|
||||
lp.log.ERROR.Printf("charge meter error: %v", err)
|
||||
return
|
||||
}
|
||||
phaseMeter, ok := lp.chargeMeter.(api.MeterCurrent)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
i1, i2, i3, err := phaseMeter.Currents()
|
||||
if err != nil {
|
||||
lp.log.ERROR.Printf("charge meter error: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
lp.log.TRACE.Printf("charge currents: %vA", []float64{i1, i2, i3})
|
||||
lp.publish("chargeCurrents", []float64{i1, i2, i3})
|
||||
|
||||
if lp.charging {
|
||||
var phases int64
|
||||
for _, i := range []float64{i1, i2, i3} {
|
||||
if i >= minActiveCurrent {
|
||||
|
|
@ -630,10 +638,8 @@ func (lp *LoadPoint) Update(sitePower float64) {
|
|||
lp.handler.SyncEnabled()
|
||||
}
|
||||
|
||||
// phase detection - run only when actually charging
|
||||
if lp.charging {
|
||||
lp.detectPhases()
|
||||
}
|
||||
// phase detection
|
||||
lp.detectPhases()
|
||||
|
||||
// check if car connected and ready for charging
|
||||
var err error
|
||||
|
|
|
|||
|
|
@ -282,6 +282,15 @@ func (site *Site) updateMeters() error {
|
|||
err = retryMeter("battery", site.batteryMeter, &site.batteryPower)
|
||||
}
|
||||
|
||||
// currents
|
||||
if phaseMeter, ok := site.gridMeter.(api.MeterCurrent); err == nil && ok {
|
||||
i1, i2, i3, err := phaseMeter.Currents()
|
||||
if err == nil {
|
||||
site.log.TRACE.Printf("grid currents: %vA", []float64{i1, i2, i3})
|
||||
site.publish("gridCurrents", []float64{i1, i2, i3})
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -49,6 +49,24 @@ func NewInfluxClient(url, token, org, user, password, database string) *Influx {
|
|||
}
|
||||
}
|
||||
|
||||
// supportedType checks if type can be written as influx value
|
||||
func (m *Influx) supportedType(p util.Param) bool {
|
||||
if p.Val == nil {
|
||||
return true
|
||||
}
|
||||
|
||||
switch val := p.Val.(type) {
|
||||
case float64:
|
||||
return true
|
||||
case [3]float64:
|
||||
return true
|
||||
case []float64:
|
||||
return len(val) == 3
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Run Influx publisher
|
||||
func (m *Influx) Run(loadPoints []*core.LoadPoint, in <-chan util.Param) {
|
||||
writer := m.client.WriteApi(m.org, m.database)
|
||||
|
|
@ -62,8 +80,7 @@ func (m *Influx) Run(loadPoints []*core.LoadPoint, in <-chan util.Param) {
|
|||
|
||||
// add points to batch for async writing
|
||||
for param := range in {
|
||||
// allow nil value to be written as series gaps
|
||||
if _, ok := param.Val.(float64); param.Val != nil && !ok {
|
||||
if !m.supportedType(param) {
|
||||
continue
|
||||
}
|
||||
|
||||
|
|
@ -72,10 +89,28 @@ func (m *Influx) Run(loadPoints []*core.LoadPoint, in <-chan util.Param) {
|
|||
tags["loadpoint"] = loadPoints[*param.LoadPoint].Name()
|
||||
}
|
||||
|
||||
fields := map[string]interface{}{
|
||||
"value": param.Val,
|
||||
fields := map[string]interface{}{}
|
||||
|
||||
// array to slice
|
||||
val := param.Val
|
||||
if v, ok := val.([3]float64); ok {
|
||||
val = v[:]
|
||||
}
|
||||
|
||||
// add slice as phase values
|
||||
if phases, ok := val.([]float64); ok {
|
||||
var total float64
|
||||
for i, v := range phases {
|
||||
total += v
|
||||
fields[fmt.Sprintf("l%d", i+1)] = v
|
||||
}
|
||||
|
||||
// add total as "value"
|
||||
val = total
|
||||
}
|
||||
|
||||
fields["value"] = val
|
||||
|
||||
// write asynchronously
|
||||
m.log.TRACE.Printf("write %s=%v (%v)", param.Key, param.Val, tags)
|
||||
p := influxdb2.NewPoint(param.Key, tags, fields, time.Now())
|
||||
|
|
|
|||
|
|
@ -44,11 +44,27 @@ func (m *MQTT) encode(v interface{}) string {
|
|||
return s
|
||||
}
|
||||
|
||||
func (m *MQTT) publish(topic string, retained bool, payload interface{}) {
|
||||
func (m *MQTT) publishSingleValue(topic string, retained bool, payload interface{}) {
|
||||
token := m.Handler.Client.Publish(topic, m.Handler.Qos, retained, m.encode(payload))
|
||||
go m.Handler.WaitForToken(token)
|
||||
}
|
||||
|
||||
func (m *MQTT) publish(topic string, retained bool, payload interface{}) {
|
||||
if slice, ok := payload.([]float64); ok && len(slice) == 3 {
|
||||
// publish phase values
|
||||
var total float64
|
||||
for i, v := range slice {
|
||||
total += v
|
||||
m.publishSingleValue(fmt.Sprintf("%s/l%d", topic, i+1), retained, v)
|
||||
}
|
||||
|
||||
// publish sum value
|
||||
payload = total
|
||||
}
|
||||
|
||||
m.publishSingleValue(topic, retained, payload)
|
||||
}
|
||||
|
||||
type apiHandler interface {
|
||||
SetMode(api.ChargeMode)
|
||||
SetTargetSoC(int)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue