Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 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
138b6ae
create interface and update README.md
nils-prommersberger Aug 8, 2024
1e973e9
Zwischenspeichern der Implementierung des MGCP-usecases
nils-prommersberger Aug 9, 2024
d7e66b0
Added descriptions defined in MGCP-V1.0.0
nils-prommersberger Aug 10, 2024
7010476
Update mgcp
nils-prommersberger Aug 12, 2024
09001e6
rename ids and remove getter functions
nils-prommersberger Aug 14, 2024
d88878a
implement setter SetPvFeedInLimitationFactor.
nils-prommersberger Aug 14, 2024
e8fc551
accept all entityTypes to connect to the gcp-mgcp
nils-prommersberger Aug 14, 2024
e7ebbd5
little changes
nils-prommersberger Aug 29, 2024
fc4e237
Add additional EntityTypes to the cs-lpp and cs-lpc specified in EEBu…
nils-prommersberger Aug 5, 2024
7276e00
Update the mgcp usecase to be able to update multiple values at once …
nils-prommersberger Oct 14, 2024
5b4eb15
Create config types
nils-prommersberger Oct 16, 2024
97b69e6
Update the mgcp config to match the specs.
nils-prommersberger Oct 16, 2024
0b6ffe8
implement the mgcp with the mpc server standard
nils-prommersberger Oct 16, 2024
9cc2af5
fix import circle
nils-prommersberger Oct 17, 2024
33e2dc0
fix import circle 2
nils-prommersberger Oct 17, 2024
86c37a7
new naming pattern to match the getters without the Get-prefix.
nils-prommersberger Oct 25, 2024
b8dddf5
add test files
nils-prommersberger Oct 25, 2024
06fd5c3
Create tests for the default mgcp
nils-prommersberger Oct 28, 2024
0e023c1
Fit mgcp usecase to the requirements from the mpc usecase
nils-prommersberger Nov 28, 2024
6e72213
only add scenarios if configured
nils-prommersberger Nov 28, 2024
f6ca67f
Use the UpdateData from the usecases.api
nils-prommersberger Dec 11, 2024
95e4cba
Add test for getMeasurementForId and use the GridGuardEntityType
nils-prommersberger Dec 11, 2024
48855cd
refactoring
nils-prommersberger Dec 13, 2024
ed630d6
error coverage for usecase
nils-prommersberger Dec 13, 2024
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