evcc-io/server/eebus/test/controlbox.go

177 lines
4.7 KiB
Go

package eebus
import (
"context"
"fmt"
"sync"
"time"
"github.com/enbility/eebus-go/api"
"github.com/enbility/eebus-go/service"
ucapi "github.com/enbility/eebus-go/usecases/api"
"github.com/enbility/eebus-go/usecases/eg/lpc"
"github.com/enbility/eebus-go/usecases/eg/lpp"
shipapi "github.com/enbility/ship-go/api"
"github.com/enbility/ship-go/cert"
spineapi "github.com/enbility/spine-go/api"
"github.com/enbility/spine-go/model"
server "github.com/evcc-io/evcc/server/eebus"
)
type controlbox struct {
mu sync.Mutex
ski string
myService *service.Service
uclpc ucapi.EgLPCInterface
uclpp ucapi.EgLPPInterface
remoteEntities map[api.EventType][]spineapi.EntityRemoteInterface
remoteEventC chan<- api.EventType
isConnected bool
}
func createControlbox(ctx context.Context, remoteSki string, port int) (*controlbox, error) {
certificate, err := cert.CreateCertificate("Demo", "Demo", "DE", "Demo-Unit-01")
if err != nil {
return nil, err
}
ski, err := server.SkiFromCert(certificate)
if err != nil {
return nil, err
}
h := &controlbox{
ski: ski,
}
configuration, err := api.NewConfiguration(
"Demo", "Demo", "ControlBox", "123456789",
[]shipapi.DeviceCategoryType{shipapi.DeviceCategoryTypeGridConnectionHub},
model.DeviceTypeTypeElectricitySupplySystem,
[]model.EntityTypeType{model.EntityTypeTypeGridGuard},
port, certificate, time.Second*60, nil, nil)
if err != nil {
return nil, err
}
configuration.SetAlternateIdentifier("Demo-ControlBox-123456789")
h.myService = service.NewService(configuration, h)
// h.myService.SetLogging(h)
if err = h.myService.Setup(); err != nil {
return nil, err
}
localEntity := h.myService.LocalDevice().EntityForType(model.EntityTypeTypeGridGuard)
h.uclpc = lpc.NewLPC(localEntity, h.OnLPCEvent)
h.myService.AddUseCase(h.uclpc)
h.uclpp = lpp.NewLPP(localEntity, h.OnLPPEvent)
h.myService.AddUseCase(h.uclpp)
h.myService.RegisterRemoteService(shipapi.NewServiceIdentity(remoteSki, "", ""))
h.myService.Start()
go func() {
<-ctx.Done()
h.myService.Shutdown()
}()
return h, nil
}
func (h *controlbox) remoteEntity(event api.EventType) []spineapi.EntityRemoteInterface {
h.mu.Lock()
defer h.mu.Unlock()
return h.remoteEntities[event]
}
func (h *controlbox) registerRemoteEntity(entity spineapi.EntityRemoteInterface, event api.EventType) {
h.mu.Lock()
defer h.mu.Unlock()
defer func() {
if h.remoteEventC != nil {
h.remoteEventC <- event
}
}()
if h.remoteEntities == nil {
h.remoteEntities = make(map[api.EventType][]spineapi.EntityRemoteInterface)
}
h.remoteEntities[event] = append(h.remoteEntities[event], entity)
}
// LPC
func (h *controlbox) OnLPCEvent(ski string, device spineapi.DeviceRemoteInterface, entity spineapi.EntityRemoteInterface, event api.EventType) {
if !h.isConnected {
return
}
switch event {
case lpc.UseCaseSupportUpdate:
h.registerRemoteEntity(entity, event)
// case lpc.DataUpdateLimit:
// if currentLimit, err := h.uclpc.ConsumptionLimit(entity); err == nil {
// fmt.Println("New consumption limit received", currentLimit.Value, "W")
// }
default:
fmt.Println("lpc:", event)
}
}
// LPP
func (h *controlbox) OnLPPEvent(ski string, device spineapi.DeviceRemoteInterface, entity spineapi.EntityRemoteInterface, event api.EventType) {
if !h.isConnected {
return
}
switch event {
case lpp.UseCaseSupportUpdate:
h.registerRemoteEntity(entity, event)
// case lpp.DataUpdateLimit:
// if currentLimit, err := h.uclpp.ConsumptionLimit(entity); err == nil {
// fmt.Println("New consumption limit received", currentLimit.Value, "W")
// }
default:
fmt.Println("lpp:", event)
}
}
// EEBUSServiceHandler
func (h *controlbox) RemoteServiceConnected(service api.ServiceInterface, identity shipapi.ServiceIdentity) {
h.isConnected = true
}
func (h *controlbox) RemoteServiceDisconnected(service api.ServiceInterface, identity shipapi.ServiceIdentity) {
h.isConnected = false
}
func (h *controlbox) VisibleRemoteMdnsServicesUpdated(service api.ServiceInterface, entries []shipapi.RemoteMdnsService) {
}
func (h *controlbox) ServiceUpdated(identity shipapi.ServiceIdentity) {
}
func (h *controlbox) ServicePairingDetailUpdate(identity shipapi.ServiceIdentity, detail *shipapi.ConnectionStateDetail) {
}
func (h *controlbox) ServiceAutoTrusted(service api.ServiceInterface, identity shipapi.ServiceIdentity) {
}
func (h *controlbox) ServiceAutoTrustFailed(service api.ServiceInterface, identity shipapi.ServiceIdentity, reason error) {
}
func (h *controlbox) ServiceAutoTrustRemoved(service api.ServiceInterface, identity shipapi.ServiceIdentity, reason string) {
}
func (h *controlbox) AllowWaitingForTrust(identity shipapi.ServiceIdentity) bool {
return true
}