Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
6a35f7a
Implement MPC usecase for the MonitoredUnit actor type
nils-prommersberger Aug 5, 2024
173c281
Add and use allEntityTypesValid boolean instead of nil validEntityTypes
nils-prommersberger Oct 14, 2024
4808cc8
Update MPC to allow for updating multiple data points in one step
nils-prommersberger Oct 11, 2024
05aa9f4
Make the mpc configurable. And support option stuff.
nils-prommersberger Oct 15, 2024
2bdd156
Fix comments and formatting mentioned in review
sthelen-enqs Nov 4, 2024
715e1b0
Only add scenarios when they're supported
sthelen-enqs Nov 4, 2024
f3bcf8f
refactor the addFeatures method of the mpc
nils-prommersberger Nov 20, 2024
5a4705c
Add test for the mpc-power-config PhaseConnection-function
nils-prommersberger Nov 20, 2024
6bc2f64
Ignore case for the SupportPhases function of the power config.
nils-prommersberger Nov 20, 2024
2f71c8d
Add more tests with mocks
nils-prommersberger Nov 20, 2024
dbef9c2
Remove panic statements with an additional wrapper struct.
nils-prommersberger Nov 20, 2024
6d40163
little fixes
nils-prommersberger Nov 22, 2024
b80232b
Test if the client-filters work with the data set by the server.
nils-prommersberger Nov 22, 2024
2482104
Let the AddFeatures method return an error
nils-prommersberger Nov 22, 2024
67cbbf1
Add a function in the electrical connection to get or add a Electrica…
nils-prommersberger Nov 27, 2024
0011953
Update mocks and fix service_test
sthelen-enqs Nov 29, 2024
0d75300
Check AddFeatures return values in tests
sthelen-enqs Nov 29, 2024
832fb39
Increase test coverage
sthelen-enqs Nov 29, 2024
878f1e3
Address comments during code review
sthelen-enqs Nov 29, 2024
de32a66
Ensure that MuMPCInterface includes UseCaseInterface
sthelen-enqs Oct 23, 2025
86332c0
Delete unused variables in /usecases/mu/mpc/usecase_test.go and renam…
nils-prommersberger Dec 11, 2024
f0a6f1a
Add comment for the GetOrAddIdForDescription in electricalConnection …
nils-prommersberger Dec 11, 2024
7809400
Return directly in GetOrAddIdForDescription if the id is found in the…
nils-prommersberger Dec 11, 2024
f8138e9
Make AddFeatures methods consistent and check if the features do exist.
nils-prommersberger Dec 11, 2024
7fd53c8
Add usecase tests
nils-prommersberger Dec 11, 2024
55a4b3e
Simplify mpc/public
nils-prommersberger Dec 11, 2024
2533a50
Add simple testcases for private functions and error cases from AddFe…
nils-prommersberger Dec 12, 2024
5fc5d70
Increase test coverage
nils-prommersberger Dec 13, 2024
3ae9953
Add error coverage for NewMPC
nils-prommersberger Dec 13, 2024
962c1af
- Update the mu-mpc APIs to use maps for per-phase measurement
mohamedeltawel Oct 30, 2025
115f2ff
go fmt
sthelen-enqs Nov 3, 2025
5ef84fb
Implement Marshaler/Unmarshaler for UpdateData
sthelen-enqs Jan 30, 2025
ea452d8
Expand on comment for empty HandleEvent method
sthelen-enqs Jan 23, 2026
427c4c8
create interface and update README.md
nils-prommersberger Aug 8, 2024
21fc02f
Zwischenspeichern der Implementierung des MGCP-usecases
nils-prommersberger Aug 9, 2024
11670bf
Added descriptions defined in MGCP-V1.0.0
nils-prommersberger Aug 10, 2024
bd1e5b3
Update mgcp
nils-prommersberger Aug 12, 2024
f51dedd
rename ids and remove getter functions
nils-prommersberger Aug 14, 2024
c5334d3
implement setter SetPvFeedInLimitationFactor.
nils-prommersberger Aug 14, 2024
b1ee905
accept all entityTypes to connect to the gcp-mgcp
nils-prommersberger Aug 14, 2024
b4eb6be
little changes
nils-prommersberger Aug 29, 2024
f5dc5a6
Add additional EntityTypes to the cs-lpp and cs-lpc specified in EEBu…
nils-prommersberger Aug 5, 2024
94f5625
Update the mgcp usecase to be able to update multiple values at once …
nils-prommersberger Oct 14, 2024
1bad42c
Create config types
nils-prommersberger Oct 16, 2024
93a1584
Update the mgcp config to match the specs.
nils-prommersberger Oct 16, 2024
d175f9e
implement the mgcp with the mpc server standard
nils-prommersberger Oct 16, 2024
751fc6d
fix import circle
nils-prommersberger Oct 17, 2024
eb28b1a
fix import circle 2
nils-prommersberger Oct 17, 2024
37f137d
new naming pattern to match the getters without the Get-prefix.
nils-prommersberger Oct 25, 2024
a32fe8e
add test files
nils-prommersberger Oct 25, 2024
504ec45
Create tests for the default mgcp
nils-prommersberger Oct 28, 2024
998bc39
Fit mgcp usecase to the requirements from the mpc usecase
nils-prommersberger Nov 28, 2024
d2d341c
only add scenarios if configured
nils-prommersberger Nov 28, 2024
c951439
Use the UpdateData from the usecases.api
nils-prommersberger Dec 11, 2024
6324713
Add test for getMeasurementForId and use the GridGuardEntityType
nils-prommersberger Dec 11, 2024
0e497bc
refactoring
nils-prommersberger Dec 13, 2024
551d63a
error coverage for usecase
nils-prommersberger Dec 13, 2024
97556df
regenerated mocks
TomLucaRoth May 29, 2026
90cfe36
fixed mgcp after rebase
TomLucaRoth May 29, 2026
5370066
Clear warning in mgcp use case.
sthelen-enqs Jun 9, 2026
4aad63b
Fix MPC/MGCP tests
sthelen-enqs Jun 9, 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 @@ -32,7 +32,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 @@ -126,12 +126,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(config.remoteSKI) == 0 && pairingConfig == nil {
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 @@ -189,10 +189,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)
}

for _, remoteSki := range config.remoteSKIs {
h.myService.RegisterRemoteService(shipapi.NewServiceIdentity(remoteSki, "", ""))
Expand Down
5 changes: 4 additions & 1 deletion examples/evse/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,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 @@ -129,19 +129,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
62 changes: 62 additions & 0 deletions mocks/ElectricalConnectionServerInterface.go

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

4 changes: 2 additions & 2 deletions mocks/EntityEventCallback.go

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

25 changes: 18 additions & 7 deletions mocks/ServiceInterface.go

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

Loading
Loading