Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
c9baa03
Implement MPC usecase for the MonitoredUnit actor type
nils-prommersberger Aug 5, 2024
fe93b88
Add and use allEntityTypesValid boolean instead of nil validEntityTypes
nils-prommersberger Oct 14, 2024
72dfd67
Update MPC to allow for updating multiple data points in one step
nils-prommersberger Oct 11, 2024
9bad2f3
Make the mpc configurable. And support option stuff.
nils-prommersberger Oct 15, 2024
c07debb
Fix comments and formatting mentioned in review
sthelen-enqs Nov 4, 2024
37655f8
Only add scenarios when they're supported
sthelen-enqs Nov 4, 2024
c042ec6
refactor the addFeatures method of the mpc
nils-prommersberger Nov 20, 2024
515e966
Add test for the mpc-power-config PhaseConnection-function
nils-prommersberger Nov 20, 2024
78c450e
Ignore case for the SupportPhases function of the power config.
nils-prommersberger Nov 20, 2024
74db007
Add more tests with mocks
nils-prommersberger Nov 20, 2024
b79b35a
Remove panic statements with an additional wrapper struct.
nils-prommersberger Nov 20, 2024
9fa97d7
little fixes
nils-prommersberger Nov 22, 2024
64f55b4
Test if the client-filters work with the data set by the server.
nils-prommersberger Nov 22, 2024
0742569
Let the AddFeatures method return an error
nils-prommersberger Nov 22, 2024
996c19a
Add a function in the electrical connection to get or add a Electrica…
nils-prommersberger Nov 27, 2024
11103d5
Update mocks and fix service_test
sthelen-enqs Nov 29, 2024
e6489fc
Check AddFeatures return values in tests
sthelen-enqs Nov 29, 2024
fb953fc
Increase test coverage
sthelen-enqs Nov 29, 2024
8a16cf3
Address comments during code review
sthelen-enqs Nov 29, 2024
167f026
Ensure that MuMPCInterface includes UseCaseInterface
sthelen-enqs Oct 23, 2025
9da6126
Delete unused variables in /usecases/mu/mpc/usecase_test.go and renam…
nils-prommersberger Dec 11, 2024
1ae5146
Add comment for the GetOrAddIdForDescription in electricalConnection …
nils-prommersberger Dec 11, 2024
b068646
Return directly in GetOrAddIdForDescription if the id is found in the…
nils-prommersberger Dec 11, 2024
580ee0b
Make AddFeatures methods consistent and check if the features do exist.
nils-prommersberger Dec 11, 2024
cb11064
Add usecase tests
nils-prommersberger Dec 11, 2024
5ecc018
Simplify mpc/public
nils-prommersberger Dec 11, 2024
a25fa3c
Add simple testcases for private functions and error cases from AddFe…
nils-prommersberger Dec 12, 2024
4f6c9a7
Increase test coverage
nils-prommersberger Dec 13, 2024
5725907
Add error coverage for NewMPC
nils-prommersberger Dec 13, 2024
56932e0
- Update the mu-mpc APIs to use maps for per-phase measurement
mohamedeltawel Oct 30, 2025
7058f68
go fmt
sthelen-enqs Nov 3, 2025
5905035
Implement Marshaler/Unmarshaler for UpdateData
sthelen-enqs Jan 30, 2025
ed77cc6
Expand on comment for empty HandleEvent method
sthelen-enqs Jan 23, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ type ServiceInterface interface {
IsRunning() bool

// add a use case to the service
AddUseCase(useCase UseCaseInterface)
AddUseCase(useCase UseCaseInterface) error

// set logging interface
SetLogging(logger logging.LoggingInterface)
Expand Down
7 changes: 7 additions & 0 deletions api/featuresserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,13 @@ type ElectricalConnectionServerInterface interface {
deleteSelector *model.ElectricalConnectionPermittedValueSetListDataSelectorsType,
deleteElements *model.ElectricalConnectionPermittedValueSetDataElementsType,
) error

// either returns the given description id or creates a new one for the given description
//
// will return error if could not add the new description
GetOrAddIdForDescription(
electricalConnectionDescription model.ElectricalConnectionDescriptionDataType,
) (*model.ElectricalConnectionIdType, error)
}

type LoadControlLimitDataForID struct {
Expand Down
13 changes: 11 additions & 2 deletions api/usecases.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,15 @@ type UseCaseBaseInterface interface {
type UseCaseInterface interface {
UseCaseBaseInterface

// add the features
AddFeatures()
// add the features described by the Use Case
//
// returns an error if any Feature could not be added
// - errors should not occur during normal usage of eebus-go, and should
// generally be considered fatal implementation errors
// - if an error occurs while adding features to a new Entity, that Entity
// will be in an incomplete state and should not be added to the service
//
// No cleanup occurs on error, some features may end up partially
// configured and unused
AddFeatures() error
}
10 changes: 8 additions & 2 deletions examples/ced/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,12 +99,18 @@ func (h *controlbox) run() {

localEntity := h.myService.LocalDevice().EntityForType(model.EntityTypeTypeHeatPumpAppliance)
h.uclpc = lpc.NewLPC(localEntity, h.OnLPCEvent)
h.myService.AddUseCase(h.uclpc)
err = h.myService.AddUseCase(h.uclpc)
if err != nil {
log.Fatal(err)
}
// h.uclpp = lpp.NewLPP(localEntity, h.OnLPPEvent)
// h.myService.AddUseCase(h.uclpp)

h.ucmpc = mpc.NewMPC(localEntity, h.OnMPCEvent)
h.myService.AddUseCase(h.ucmpc)
err = h.myService.AddUseCase(h.ucmpc)
if err != nil {
log.Fatal(err)
}

if len(remoteSki) == 0 {
os.Exit(0)
Expand Down
10 changes: 8 additions & 2 deletions examples/controlbox/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,16 @@ func (h *controlbox) run() {

localEntity := h.myService.LocalDevice().EntityForType(model.EntityTypeTypeGridGuard)
h.uclpc = lpc.NewLPC(localEntity, h.OnLPCEvent)
h.myService.AddUseCase(h.uclpc)
err = h.myService.AddUseCase(h.uclpc)
if err != nil {
log.Fatal(err)
}

h.uclpp = lpp.NewLPP(localEntity, h.OnLPPEvent)
h.myService.AddUseCase(h.uclpp)
err = h.myService.AddUseCase(h.uclpp)
if err != nil {
log.Fatal(err)
}

if len(remoteSki) == 0 {
os.Exit(0)
Expand Down
5 changes: 4 additions & 1 deletion examples/evse/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,10 @@ func (h *evse) run() {

localEntity := h.myService.LocalDevice().EntityForType(model.EntityTypeTypeEVSE)
h.uclpc = lpc.NewLPC(localEntity, h.OnLPCEvent)
h.myService.AddUseCase(h.uclpc)
err = h.myService.AddUseCase(h.uclpc)
if err != nil {
log.Fatal(err)
}

// Initialize local server data
_ = h.uclpc.SetConsumptionNominalMax(32000)
Expand Down
41 changes: 34 additions & 7 deletions examples/hems/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,19 +102,46 @@ func (h *hems) run() {

localEntity := h.myService.LocalDevice().EntityForType(model.EntityTypeTypeCEM)
h.uccslpc = cslpc.NewLPC(localEntity, h.OnLPCEvent)
h.myService.AddUseCase(h.uccslpc)
err = h.myService.AddUseCase(h.uccslpc)
if err != nil {
log.Fatal(err)
}

h.uccslpp = cslpp.NewLPP(localEntity, h.OnLPPEvent)
h.myService.AddUseCase(h.uccslpp)
err = h.myService.AddUseCase(h.uccslpp)
if err != nil {
log.Fatal(err)
}

h.uceglpc = eglpc.NewLPC(localEntity, nil)
h.myService.AddUseCase(h.uceglpc)
err = h.myService.AddUseCase(h.uceglpc)
if err != nil {
log.Fatal(err)
}

h.uceglpp = eglpp.NewLPP(localEntity, nil)
h.myService.AddUseCase(h.uceglpp)
err = h.myService.AddUseCase(h.uceglpp)
if err != nil {
log.Fatal(err)
}

h.ucmamgcp = mgcp.NewMGCP(localEntity, h.OnMGCPEvent)
h.myService.AddUseCase(h.ucmamgcp)
err = h.myService.AddUseCase(h.ucmamgcp)
if err != nil {
log.Fatal(err)
}

h.uccemvabd = vabd.NewVABD(localEntity, h.OnVABDEvent)
h.myService.AddUseCase(h.uccemvabd)
err = h.myService.AddUseCase(h.uccemvabd)
if err != nil {
log.Fatal(err)
}

h.uccemvapd = vapd.NewVAPD(localEntity, h.OnVAPDEvent)
h.myService.AddUseCase(h.uccemvapd)
err = h.myService.AddUseCase(h.uccemvapd)
if err != nil {
log.Fatal(err)
}

// Initialize local server data
_ = h.uccslpc.SetConsumptionNominalMax(32000)
Expand Down
6 changes: 5 additions & 1 deletion examples/remote/ucs.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package main
import (
"context"
"fmt"
"log"

"github.com/enbility/eebus-go/api"
spineapi "github.com/enbility/spine-go/api"
Expand Down Expand Up @@ -31,7 +32,10 @@ func (r *Remote) RegisterUseCase(entityType model.EntityTypeType, usecaseId stri
) {
r.PropagateEvent(identifier, ski, device, entity, event)
})
r.service.AddUseCase(uc)
err := r.service.AddUseCase(uc)
if err != nil {
log.Fatal(err)
}

return r.registerStaticReceiverProxy(usecaseId, uc)
}
Expand Down
45 changes: 45 additions & 0 deletions features/server/electricalconnection.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,51 @@ func NewElectricalConnection(localEntity spineapi.EntityLocalInterface) (*Electr
return ec, nil
}

// Get or add the id for a electrical connection with a given electricalConnectionDescription
//
// NOTE: This can be used instead of AddDescription to be sure it exists only one id for the same description
//
// will return the id for the electrical connection with the given description
func (e *ElectricalConnection) GetOrAddIdForDescription(
electricalConnectionDescription model.ElectricalConnectionDescriptionDataType,
) (*model.ElectricalConnectionIdType, error) {
electricalConnectionId := (*model.ElectricalConnectionIdType)(nil)
highestExistingElectricalConnectionId := model.ElectricalConnectionIdType(0)

descriptionData := e.featureLocal.DataCopy(model.FunctionTypeElectricalConnectionDescriptionListData).(*model.ElectricalConnectionDescriptionListDataType)

if descriptionData != nil && descriptionData.ElectricalConnectionDescriptionData != nil {
for _, description := range descriptionData.ElectricalConnectionDescriptionData {
if description.ElectricalConnectionId != nil &&
description.PowerSupplyType == electricalConnectionDescription.PowerSupplyType &&
description.AcConnectedPhases == electricalConnectionDescription.AcConnectedPhases &&
description.AcRmsPeriodDuration == electricalConnectionDescription.AcRmsPeriodDuration &&
description.PositiveEnergyDirection == electricalConnectionDescription.PositiveEnergyDirection &&
description.ScopeType == electricalConnectionDescription.ScopeType &&
description.Label == electricalConnectionDescription.Label &&
description.Description == electricalConnectionDescription.Description {
electricalConnectionId = description.ElectricalConnectionId
return electricalConnectionId, nil
} else if description.ElectricalConnectionId != nil {
if *description.ElectricalConnectionId > highestExistingElectricalConnectionId {
highestExistingElectricalConnectionId = *description.ElectricalConnectionId
}
}
}
}

electricalConnectionId = util.Ptr(highestExistingElectricalConnectionId + 1)
description := electricalConnectionDescription
description.ElectricalConnectionId = electricalConnectionId
if errType := e.featureLocal.UpdateData(model.FunctionTypeElectricalConnectionDescriptionListData, &model.ElectricalConnectionDescriptionListDataType{
ElectricalConnectionDescriptionData: []model.ElectricalConnectionDescriptionDataType{description},
}, model.NewFilterTypePartial(), nil); errType != nil {
return nil, errors.New("could not add description data")
}

return electricalConnectionId, nil
}

// Add a new description data set
//
// NOTE: the electricalConnectionId has to be provided
Expand Down
34 changes: 34 additions & 0 deletions features/server/electricalconnection_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,40 @@ func (s *ElectricalConnectionSuite) Test_Description() {
assert.NotNil(s.T(), data)
}

func (s *ElectricalConnectionSuite) Test_GetOrAddIdForDescription() {
filter := model.ElectricalConnectionDescriptionDataType{}

data, err := s.sut.GetDescriptionsForFilter(filter)
assert.NotNil(s.T(), err)
assert.Nil(s.T(), data)

desc1 := model.ElectricalConnectionDescriptionDataType{
PowerSupplyType: util.Ptr(model.ElectricalConnectionVoltageTypeTypeDc),
ScopeType: util.Ptr(model.ScopeTypeTypeACPowerTotal),
}

eConnectionId, err := s.sut.GetOrAddIdForDescription(desc1)
assert.Nil(s.T(), err)
assert.Equal(s.T(), model.ElectricalConnectionIdType(1), *eConnectionId)

eConnectionId, err = s.sut.GetOrAddIdForDescription(desc1)
assert.Nil(s.T(), err)
assert.Equal(s.T(), model.ElectricalConnectionIdType(1), *eConnectionId)

desc2 := model.ElectricalConnectionDescriptionDataType{
PowerSupplyType: util.Ptr(model.ElectricalConnectionVoltageTypeTypeAc),
ScopeType: util.Ptr(model.ScopeTypeTypeACPowerTotal),
}

eConnectionId2, err := s.sut.GetOrAddIdForDescription(desc2)
assert.Nil(s.T(), err)
assert.Equal(s.T(), model.ElectricalConnectionIdType(2), *eConnectionId2)

eConnectionId, err = s.sut.GetOrAddIdForDescription(desc1)
assert.Nil(s.T(), err)
assert.Equal(s.T(), model.ElectricalConnectionIdType(1), *eConnectionId)
}

func (s *ElectricalConnectionSuite) Test_ParameterDescription() {
filter := model.ElectricalConnectionParameterDescriptionDataType{}

Expand Down
58 changes: 29 additions & 29 deletions mocks/DeviceClassificationClientInterface.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading