Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
c441d68
Implement MPC usecase for the MonitoredUnit actor type
nils-prommersberger Aug 5, 2024
4e150c2
Add and use allEntityTypesValid boolean instead of nil validEntityTypes
nils-prommersberger Oct 14, 2024
74eb1d3
Update MPC to allow for updating multiple data points in one step
nils-prommersberger Oct 11, 2024
e7738bc
Make the mpc configurable. And support option stuff.
nils-prommersberger Oct 15, 2024
dcb14b5
Fix comments and formatting mentioned in review
sthelen-enqs Nov 4, 2024
26038b7
Only add scenarios when they're supported
sthelen-enqs Nov 4, 2024
1f92eb6
refactor the addFeatures method of the mpc
nils-prommersberger Nov 20, 2024
b44b373
Add test for the mpc-power-config PhaseConnection-function
nils-prommersberger Nov 20, 2024
900a836
Ignore case for the SupportPhases function of the power config.
nils-prommersberger Nov 20, 2024
e511e7d
Add more tests with mocks
nils-prommersberger Nov 20, 2024
de9eb13
Remove panic statements with an additional wrapper struct.
nils-prommersberger Nov 20, 2024
30811ca
little fixes
nils-prommersberger Nov 22, 2024
a7883c5
Test if the client-filters work with the data set by the server.
nils-prommersberger Nov 22, 2024
4bb0866
Let the AddFeatures method return an error
nils-prommersberger Nov 22, 2024
667883c
Add a function in the electrical connection to get or add a Electrica…
nils-prommersberger Nov 27, 2024
1ce40ff
Update mocks and fix service_test
sthelen-enqs Nov 29, 2024
f73140a
Check AddFeatures return values in tests
sthelen-enqs Nov 29, 2024
560632d
Increase test coverage
sthelen-enqs Nov 29, 2024
75151fd
Address comments during code review
sthelen-enqs Nov 29, 2024
b632337
Ensure that MuMPCInterface includes UseCaseInterface
sthelen-enqs Oct 23, 2025
9d10385
Delete unused variables in /usecases/mu/mpc/usecase_test.go and renam…
nils-prommersberger Dec 11, 2024
d968f8e
Add comment for the GetOrAddIdForDescription in electricalConnection …
nils-prommersberger Dec 11, 2024
2764932
Return directly in GetOrAddIdForDescription if the id is found in the…
nils-prommersberger Dec 11, 2024
2d14384
Make AddFeatures methods consistent and check if the features do exist.
nils-prommersberger Dec 11, 2024
9aeace7
Add usecase tests
nils-prommersberger Dec 11, 2024
ddc70cb
Simplify mpc/public
nils-prommersberger Dec 11, 2024
0768c8e
Add simple testcases for private functions and error cases from AddFe…
nils-prommersberger Dec 12, 2024
a4d0aff
Increase test coverage
nils-prommersberger Dec 13, 2024
dbd73a5
Add error coverage for NewMPC
nils-prommersberger Dec 13, 2024
f1e4add
- Update the mu-mpc APIs to use maps for per-phase measurement
mohamedeltawel Oct 30, 2025
099ab86
go fmt
sthelen-enqs Nov 3, 2025
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