EEBus meter: fix monitoring of power consumption (#26472)
This commit is contained in:
parent
4f20cc56d9
commit
fea6e09b4c
5 changed files with 186 additions and 200 deletions
|
|
@ -141,12 +141,8 @@ func NewEEBus(ctx context.Context, ski string, limits Limits, passthrough func(b
|
|||
}
|
||||
|
||||
// controllable system
|
||||
for _, s := range c.cs.CsLPCInterface.RemoteEntitiesScenarios() {
|
||||
c.log.DEBUG.Printf("ski %s CS LPC scenarios: %v", s.Entity.Device().Ski(), s.Scenarios)
|
||||
}
|
||||
for _, s := range c.cs.CsLPPInterface.RemoteEntitiesScenarios() {
|
||||
c.log.DEBUG.Printf("ski %s CS LPP scenarios: %v", s.Entity.Device().Ski(), s.Scenarios)
|
||||
}
|
||||
eebus.LogEntities(c.log.DEBUG, "CS LPC", c.cs.CsLPCInterface)
|
||||
eebus.LogEntities(c.log.DEBUG, "CS LPP", c.cs.CsLPPInterface)
|
||||
|
||||
// set initial values
|
||||
if err := c.cs.CsLPCInterface.SetConsumptionNominalMax(limits.ContractualConsumptionNominalMax); err != nil {
|
||||
|
|
|
|||
276
meter/eebus.go
276
meter/eebus.go
|
|
@ -4,17 +4,12 @@ import (
|
|||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"slices"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
eebusapi "github.com/enbility/eebus-go/api"
|
||||
ucapi "github.com/enbility/eebus-go/usecases/api"
|
||||
"github.com/enbility/eebus-go/usecases/eg/lpc"
|
||||
"github.com/enbility/eebus-go/usecases/eg/lpp"
|
||||
"github.com/enbility/eebus-go/usecases/ma/mgcp"
|
||||
"github.com/enbility/eebus-go/usecases/ma/mpc"
|
||||
spineapi "github.com/enbility/spine-go/api"
|
||||
"github.com/enbility/spine-go/model"
|
||||
"github.com/evcc-io/evcc/api"
|
||||
|
|
@ -35,19 +30,14 @@ type EEBus struct {
|
|||
eg *eebus.EnergyGuard
|
||||
mm measurements
|
||||
|
||||
power *util.Value[float64]
|
||||
energy *util.Value[float64]
|
||||
currents *util.Value[[]float64]
|
||||
voltages *util.Value[[]float64]
|
||||
|
||||
mu sync.Mutex
|
||||
consumptionLimit ucapi.LoadLimit
|
||||
productionLimit ucapi.LoadLimit
|
||||
egLpcEntity spineapi.EntityRemoteInterface
|
||||
egLppEntity spineapi.EntityRemoteInterface
|
||||
mu sync.Mutex
|
||||
maEntity spineapi.EntityRemoteInterface
|
||||
egLpcEntity spineapi.EntityRemoteInterface
|
||||
egLppEntity spineapi.EntityRemoteInterface
|
||||
}
|
||||
|
||||
type measurements interface {
|
||||
eebusapi.UseCaseBaseInterface
|
||||
Power(entity spineapi.EntityRemoteInterface) (float64, error)
|
||||
EnergyConsumed(entity spineapi.EntityRemoteInterface) (float64, error)
|
||||
CurrentPerPhase(entity spineapi.EntityRemoteInterface) ([]float64, error)
|
||||
|
|
@ -60,25 +50,23 @@ func init() {
|
|||
|
||||
// NewEEBusFromConfig creates an EEBus meter from generic config
|
||||
func NewEEBusFromConfig(ctx context.Context, other map[string]any) (api.Meter, error) {
|
||||
cc := struct {
|
||||
Ski string
|
||||
Ip string
|
||||
Usage *templates.Usage
|
||||
Timeout time.Duration
|
||||
}{
|
||||
Timeout: 10 * time.Second,
|
||||
var cc struct {
|
||||
Ski string
|
||||
Ip string
|
||||
Usage *templates.Usage
|
||||
Timeout_ time.Duration `mapstructure:"timeout"` // TODO deprecated
|
||||
}
|
||||
|
||||
if err := util.DecodeOther(other, &cc); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewEEBus(ctx, cc.Ski, cc.Ip, cc.Usage, cc.Timeout)
|
||||
return NewEEBus(ctx, cc.Ski, cc.Ip, cc.Usage)
|
||||
}
|
||||
|
||||
// NewEEBus creates an EEBus meter
|
||||
// Uses MGCP only when usage="grid", otherwise uses MPC (default)
|
||||
func NewEEBus(ctx context.Context, ski, ip string, usage *templates.Usage, timeout time.Duration) (api.Meter, error) {
|
||||
func NewEEBus(ctx context.Context, ski, ip string, usage *templates.Usage) (api.Meter, error) {
|
||||
if eebus.Instance == nil {
|
||||
return nil, errors.New("eebus not configured")
|
||||
}
|
||||
|
|
@ -100,10 +88,6 @@ func NewEEBus(ctx context.Context, ski, ip string, usage *templates.Usage, timeo
|
|||
eg: eebus.Instance.EnergyGuard(),
|
||||
mm: mm,
|
||||
Connector: eebus.NewConnector(),
|
||||
power: util.NewValue[float64](timeout),
|
||||
energy: util.NewValue[float64](timeout),
|
||||
currents: util.NewValue[[]float64](timeout),
|
||||
voltages: util.NewValue[[]float64](timeout),
|
||||
}
|
||||
|
||||
if err := eebus.Instance.RegisterDevice(ski, ip, c); err != nil {
|
||||
|
|
@ -116,157 +100,87 @@ func NewEEBus(ctx context.Context, ski, ip string, usage *templates.Usage, timeo
|
|||
}
|
||||
|
||||
// monitoring appliance
|
||||
for _, s := range c.ma.MaMPCInterface.RemoteEntitiesScenarios() {
|
||||
c.log.DEBUG.Printf("ski %s MA MPC scenarios: %v", s.Entity.Device().Ski(), s.Scenarios)
|
||||
}
|
||||
for _, s := range c.ma.MaMGCPInterface.RemoteEntitiesScenarios() {
|
||||
c.log.DEBUG.Printf("ski %s MA MGCP scenarios: %v", s.Entity.Device().Ski(), s.Scenarios)
|
||||
}
|
||||
eebus.LogEntities(c.log.DEBUG, "MA MPC", c.ma.MaMPCInterface)
|
||||
eebus.LogEntities(c.log.DEBUG, "MA MGCP", c.ma.MaMGCPInterface)
|
||||
|
||||
// energy guard
|
||||
for _, s := range c.eg.EgLPCInterface.RemoteEntitiesScenarios() {
|
||||
c.log.DEBUG.Printf("ski %s EG LPC scenarios: %v", s.Entity.Device().Ski(), s.Scenarios)
|
||||
}
|
||||
for _, s := range c.eg.EgLPPInterface.RemoteEntitiesScenarios() {
|
||||
c.log.DEBUG.Printf("ski %s EG LPP scenarios: %v", s.Entity.Device().Ski(), s.Scenarios)
|
||||
}
|
||||
eebus.LogEntities(c.log.DEBUG, "EG LPC", c.eg.EgLPCInterface)
|
||||
eebus.LogEntities(c.log.DEBUG, "EG LPP", c.eg.EgLPPInterface)
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
||||
var _ eebus.Device = (*EEBus)(nil)
|
||||
func eebusReadValue[T any](scenario uint, uc eebusapi.UseCaseBaseInterface, entity spineapi.EntityRemoteInterface, update func(entity spineapi.EntityRemoteInterface) (T, error)) (T, error) {
|
||||
var zero T
|
||||
|
||||
// UseCaseEvent implements the eebus.Device interface
|
||||
func (c *EEBus) UseCaseEvent(_ spineapi.DeviceRemoteInterface, entity spineapi.EntityRemoteInterface, event eebusapi.EventType) {
|
||||
switch event {
|
||||
// Monitoring Appliance
|
||||
case mpc.DataUpdatePower, mgcp.DataUpdatePower:
|
||||
c.maDataUpdatePower(entity)
|
||||
case mpc.DataUpdateEnergyConsumed, mgcp.DataUpdateEnergyConsumed:
|
||||
c.maDataUpdateEnergyConsumed(entity)
|
||||
case mpc.DataUpdateCurrentsPerPhase, mgcp.DataUpdateCurrentPerPhase:
|
||||
c.maDataUpdateCurrentPerPhase(entity)
|
||||
case mpc.DataUpdateVoltagePerPhase, mgcp.DataUpdateVoltagePerPhase:
|
||||
c.maDataUpdateVoltagePerPhase(entity)
|
||||
|
||||
// Energy Guard - LPC
|
||||
case lpc.UseCaseSupportUpdate:
|
||||
c.egLpcUseCaseSupportUpdate(entity)
|
||||
case lpc.DataUpdateLimit:
|
||||
c.egLpcDataUpdateLimit(entity)
|
||||
|
||||
// Energy Guard - LPP
|
||||
case lpp.UseCaseSupportUpdate:
|
||||
c.egLppUseCaseSupportUpdate(entity)
|
||||
case lpp.DataUpdateLimit:
|
||||
c.egLppDataUpdateLimit(entity)
|
||||
if entity == nil || !uc.IsScenarioAvailableAtEntity(entity, scenario) {
|
||||
return zero, api.ErrNotAvailable
|
||||
}
|
||||
}
|
||||
|
||||
func (c *EEBus) maDataUpdatePower(entity spineapi.EntityRemoteInterface) {
|
||||
data, err := c.mm.Power(entity)
|
||||
res, err := update(entity)
|
||||
if err != nil {
|
||||
c.log.ERROR.Println("Power:", err)
|
||||
return
|
||||
}
|
||||
c.log.TRACE.Printf("Power: %.0fW", data)
|
||||
c.power.Set(data)
|
||||
}
|
||||
|
||||
func (c *EEBus) maDataUpdateEnergyConsumed(entity spineapi.EntityRemoteInterface) {
|
||||
data, err := c.mm.EnergyConsumed(entity)
|
||||
if err != nil {
|
||||
c.log.ERROR.Println("EnergyConsumed:", err)
|
||||
return
|
||||
}
|
||||
c.log.TRACE.Printf("EnergyConsumed: %.1fkWh", data/1000)
|
||||
// Convert Wh to kWh
|
||||
c.energy.Set(data / 1000)
|
||||
}
|
||||
|
||||
func (c *EEBus) maDataUpdateCurrentPerPhase(entity spineapi.EntityRemoteInterface) {
|
||||
data, err := c.mm.CurrentPerPhase(entity)
|
||||
if err != nil {
|
||||
c.log.ERROR.Println("CurrentPerPhase:", err)
|
||||
return
|
||||
}
|
||||
c.currents.Set(data)
|
||||
}
|
||||
|
||||
func (c *EEBus) maDataUpdateVoltagePerPhase(entity spineapi.EntityRemoteInterface) {
|
||||
data, err := c.mm.VoltagePerPhase(entity)
|
||||
if err != nil {
|
||||
c.log.ERROR.Println("VoltagePerPhase:", err)
|
||||
return
|
||||
}
|
||||
c.voltages.Set(data)
|
||||
}
|
||||
|
||||
var _ api.Meter = (*EEBus)(nil)
|
||||
|
||||
func (c *EEBus) CurrentPower() (float64, error) {
|
||||
return c.power.Get()
|
||||
}
|
||||
|
||||
var _ api.MeterEnergy = (*EEBus)(nil)
|
||||
|
||||
func (c *EEBus) TotalEnergy() (float64, error) {
|
||||
res, err := c.energy.Get()
|
||||
if err != nil {
|
||||
return 0, api.ErrNotAvailable
|
||||
// announced but not provided
|
||||
if errors.Is(err, eebusapi.ErrDataNotAvailable) {
|
||||
err = api.ErrNotAvailable
|
||||
}
|
||||
return zero, err
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (c *EEBus) readValue(scenario uint, update func(entity spineapi.EntityRemoteInterface) (float64, error)) (float64, error) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
return eebusReadValue(scenario, c.mm, c.maEntity, update)
|
||||
}
|
||||
|
||||
var _ api.Meter = (*EEBus)(nil)
|
||||
|
||||
func (c *EEBus) CurrentPower() (float64, error) {
|
||||
return c.readValue(1, c.mm.Power)
|
||||
}
|
||||
|
||||
var _ api.MeterEnergy = (*EEBus)(nil)
|
||||
|
||||
func (c *EEBus) TotalEnergy() (float64, error) {
|
||||
return c.readValue(2, c.mm.EnergyConsumed)
|
||||
}
|
||||
|
||||
func (c *EEBus) readPhases(scenario uint, update func(entity spineapi.EntityRemoteInterface) ([]float64, error)) (float64, float64, float64, error) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
res, err := eebusReadValue(scenario, c.mm, c.maEntity, update)
|
||||
if err != nil {
|
||||
// announced but not provided
|
||||
if errors.Is(err, eebusapi.ErrDataNotAvailable) {
|
||||
err = api.ErrNotAvailable
|
||||
}
|
||||
return 0, 0, 0, err
|
||||
}
|
||||
|
||||
if len(res) < 1 || len(res) > 3 {
|
||||
return 0, 0, 0, fmt.Errorf("invalid phases: %v", res)
|
||||
}
|
||||
|
||||
for len(res) < 3 {
|
||||
res = append(res, 0)
|
||||
}
|
||||
|
||||
return res[0], res[1], res[2], nil
|
||||
}
|
||||
|
||||
var _ api.PhaseCurrents = (*EEBus)(nil)
|
||||
|
||||
func (c *EEBus) Currents() (float64, float64, float64, error) {
|
||||
res, err := c.currents.Get()
|
||||
if err != nil {
|
||||
return 0, 0, 0, api.ErrNotAvailable
|
||||
}
|
||||
if len(res) != 3 {
|
||||
return 0, 0, 0, errors.New("invalid phase currents")
|
||||
}
|
||||
return res[0], res[1], res[2], nil
|
||||
return c.readPhases(3, c.mm.CurrentPerPhase)
|
||||
}
|
||||
|
||||
var _ api.PhaseVoltages = (*EEBus)(nil)
|
||||
|
||||
func (c *EEBus) Voltages() (float64, float64, float64, error) {
|
||||
res, err := c.voltages.Get()
|
||||
if err != nil {
|
||||
return 0, 0, 0, api.ErrNotAvailable
|
||||
}
|
||||
if len(res) != 3 {
|
||||
return 0, 0, 0, errors.New("invalid phase voltages")
|
||||
}
|
||||
return res[0], res[1], res[2], nil
|
||||
}
|
||||
|
||||
//
|
||||
// Energy Guard - LPC
|
||||
//
|
||||
|
||||
func (c *EEBus) egLpcUseCaseSupportUpdate(entity spineapi.EntityRemoteInterface) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
c.egLpcEntity = entity
|
||||
}
|
||||
|
||||
func (c *EEBus) egLpcDataUpdateLimit(entity spineapi.EntityRemoteInterface) {
|
||||
limit, err := c.eg.EgLPCInterface.ConsumptionLimit(entity)
|
||||
if err != nil {
|
||||
c.log.ERROR.Println("EG LPC ConsumptionLimit:", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
c.consumptionLimit = limit
|
||||
return c.readPhases(4, c.mm.VoltagePerPhase)
|
||||
}
|
||||
|
||||
var _ api.Dimmer = (*EEBus)(nil)
|
||||
|
|
@ -276,8 +190,13 @@ func (c *EEBus) Dimmed() (bool, error) {
|
|||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
limit, err := eebusReadValue(1, c.eg.EgLPCInterface, c.egLpcEntity, c.eg.EgLPCInterface.ConsumptionLimit)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
// Check if limit is active and has a valid power value
|
||||
return c.consumptionLimit.IsActive && c.consumptionLimit.Value > 0, nil
|
||||
return limit.IsActive && limit.Value > 0, nil
|
||||
}
|
||||
|
||||
// Dim implements the api.Dimmer interface
|
||||
|
|
@ -296,14 +215,10 @@ func (c *EEBus) Dim(dim bool) error {
|
|||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
if c.egLpcEntity == nil {
|
||||
if c.egLpcEntity == nil || !c.eg.EgLPCInterface.IsScenarioAvailableAtEntity(c.egLpcEntity, 1) {
|
||||
return api.ErrNotAvailable
|
||||
}
|
||||
|
||||
if !slices.Contains(c.eg.EgLPCInterface.AvailableScenariosForEntity(c.egLpcEntity), 1) {
|
||||
return errors.New("eg lpc: scenario 1 not supported")
|
||||
}
|
||||
|
||||
_, err := c.eg.EgLPCInterface.WriteConsumptionLimit(c.egLpcEntity, ucapi.LoadLimit{
|
||||
Value: value,
|
||||
IsActive: dim,
|
||||
|
|
@ -312,30 +227,6 @@ func (c *EEBus) Dim(dim bool) error {
|
|||
return err
|
||||
}
|
||||
|
||||
//
|
||||
// Energy Guard - LPP
|
||||
//
|
||||
|
||||
func (c *EEBus) egLppUseCaseSupportUpdate(entity spineapi.EntityRemoteInterface) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
c.egLppEntity = entity
|
||||
}
|
||||
|
||||
func (c *EEBus) egLppDataUpdateLimit(entity spineapi.EntityRemoteInterface) {
|
||||
limit, err := c.eg.EgLPPInterface.ProductionLimit(entity)
|
||||
if err != nil {
|
||||
c.log.ERROR.Println("EG LPP ProductionLimit:", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
c.productionLimit = limit
|
||||
}
|
||||
|
||||
var _ api.Curtailer = (*EEBus)(nil)
|
||||
|
||||
// Curtailed implements the api.Curtailer interface
|
||||
|
|
@ -343,8 +234,13 @@ func (c *EEBus) Curtailed() (bool, error) {
|
|||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
limit, err := eebusReadValue(1, c.eg.EgLPPInterface, c.egLppEntity, c.eg.EgLPPInterface.ProductionLimit)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
// Check if limit is active and has a valid power value
|
||||
return c.productionLimit.IsActive && c.productionLimit.Value > 0, nil
|
||||
return limit.IsActive && limit.Value > 0, nil
|
||||
}
|
||||
|
||||
// Curtail implements the api.Curtailer interface
|
||||
|
|
@ -363,14 +259,10 @@ func (c *EEBus) Curtail(curtail bool) error {
|
|||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
if c.egLppEntity == nil {
|
||||
if c.egLppEntity == nil || !c.eg.EgLPPInterface.IsScenarioAvailableAtEntity(c.egLppEntity, 1) {
|
||||
return api.ErrNotAvailable
|
||||
}
|
||||
|
||||
if !slices.Contains(c.eg.EgLPPInterface.AvailableScenariosForEntity(c.egLppEntity), 1) {
|
||||
return errors.New("eg lpp: scenario 1 not supported")
|
||||
}
|
||||
|
||||
_, err := c.eg.EgLPPInterface.WriteProductionLimit(c.egLppEntity, ucapi.LoadLimit{
|
||||
Value: value,
|
||||
IsActive: curtail,
|
||||
|
|
|
|||
72
meter/eebus_events.go
Normal file
72
meter/eebus_events.go
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
package meter
|
||||
|
||||
import (
|
||||
eebusapi "github.com/enbility/eebus-go/api"
|
||||
"github.com/enbility/eebus-go/usecases/eg/lpc"
|
||||
"github.com/enbility/eebus-go/usecases/eg/lpp"
|
||||
"github.com/enbility/eebus-go/usecases/ma/mgcp"
|
||||
"github.com/enbility/eebus-go/usecases/ma/mpc"
|
||||
spineapi "github.com/enbility/spine-go/api"
|
||||
"github.com/evcc-io/evcc/server/eebus"
|
||||
)
|
||||
|
||||
var _ eebus.Device = (*EEBus)(nil)
|
||||
|
||||
// UseCaseEvent implements the eebus.Device interface
|
||||
func (c *EEBus) UseCaseEvent(_ spineapi.DeviceRemoteInterface, entity spineapi.EntityRemoteInterface, event eebusapi.EventType) {
|
||||
switch event {
|
||||
// Monitoring Appliance
|
||||
case mpc.UseCaseSupportUpdate, mgcp.UseCaseSupportUpdate:
|
||||
c.maUseCaseSupportUpdate(entity)
|
||||
|
||||
// Energy Guard - LPC
|
||||
case lpc.UseCaseSupportUpdate:
|
||||
c.egLpcUseCaseSupportUpdate(entity)
|
||||
|
||||
// Energy Guard - LPP
|
||||
case lpp.UseCaseSupportUpdate:
|
||||
c.egLppUseCaseSupportUpdate(entity)
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Monitoring Appliance - MPC/MGPC
|
||||
//
|
||||
|
||||
func (c *EEBus) maUseCaseSupportUpdate(entity spineapi.EntityRemoteInterface) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
// use most specific selector
|
||||
if c.maEntity == nil || len(entity.Address().Entity) < len(c.maEntity.Address().Entity) {
|
||||
c.maEntity = entity
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Energy Guard - LPC
|
||||
//
|
||||
|
||||
func (c *EEBus) egLpcUseCaseSupportUpdate(entity spineapi.EntityRemoteInterface) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
// use most specific selector
|
||||
if c.egLpcEntity == nil || len(entity.Address().Entity) < len(c.egLpcEntity.Address().Entity) {
|
||||
c.egLpcEntity = entity
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Energy Guard - LPP
|
||||
//
|
||||
|
||||
func (c *EEBus) egLppUseCaseSupportUpdate(entity spineapi.EntityRemoteInterface) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
// use most specific selector
|
||||
if c.egLppEntity == nil || len(entity.Address().Entity) < len(c.egLppEntity.Address().Entity) {
|
||||
c.egLppEntity = entity
|
||||
}
|
||||
}
|
||||
|
|
@ -7,6 +7,7 @@ import (
|
|||
"net"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
|
|
@ -354,12 +355,20 @@ func (c *EEBus) Tracef(format string, args ...any) {
|
|||
c.log.TRACE.Printf(format, args...)
|
||||
}
|
||||
|
||||
func isRelevant(s string) bool {
|
||||
return strings.Contains(s, "connect") || strings.Contains(s, " event ")
|
||||
}
|
||||
|
||||
func (c *EEBus) Debug(args ...any) {
|
||||
c.log.DEBUG.Println(args...)
|
||||
if s := fmt.Sprint(args...); isRelevant(s) {
|
||||
c.log.DEBUG.Print(s)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *EEBus) Debugf(format string, args ...any) {
|
||||
c.log.DEBUG.Printf(format, args...)
|
||||
if s := fmt.Sprintf(format, args...); isRelevant(s) {
|
||||
c.log.DEBUG.Print(s)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *EEBus) Info(args ...any) {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package eebus
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"log"
|
||||
|
||||
eebusapi "github.com/enbility/eebus-go/api"
|
||||
"github.com/evcc-io/evcc/api"
|
||||
|
|
@ -13,3 +14,19 @@ func WrapError(err error) error {
|
|||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func LogEntities(log *log.Logger, actor string, uc eebusapi.UseCaseInterface) {
|
||||
ss := uc.RemoteEntitiesScenarios()
|
||||
if len(ss) > 0 {
|
||||
log.Printf("%s:", actor)
|
||||
}
|
||||
|
||||
for _, s := range ss {
|
||||
var desc string
|
||||
if d := s.Entity.Description(); d != nil {
|
||||
desc = string(*d)
|
||||
}
|
||||
|
||||
log.Printf(" entity: %s scenarios: %v meta: %s (%s)", s.Entity.Address(), s.Scenarios, s.Entity.EntityType(), desc)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue