Read grid and charge meter currents (#272)

This commit is contained in:
andig 2020-08-09 16:52:55 +02:00 • committed by GitHub
parent 12cb57645c
commit 0922bc774c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 81 additions and 15 deletions

View file

@ -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

View file

@ -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
}

View file

@ -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())

View file

@ -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)