Skip to content

Commit

Permalink
Add method to check for UseCase & Feature support
Browse files Browse the repository at this point in the history
This can be used to verify the required usecase scenarios are available and the provided server features are also present
  • Loading branch information
DerAndereAndi committed Jan 5, 2024
1 parent cc42189 commit 497fb1c
Show file tree
Hide file tree
Showing 2 changed files with 219 additions and 0 deletions.
86 changes: 86 additions & 0 deletions spine/device_remote.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"encoding/json"
"errors"
"reflect"
"slices"
"sync"

"github.com/enbility/eebus-go/logging"
Expand Down Expand Up @@ -234,6 +235,91 @@ func (d *DeviceRemoteImpl) AddEntity(entity *EntityRemoteImpl) *EntityRemoteImpl
return entity
}

// Checks if the given actor, usecasename and provided server features are available
// Note: the server features are expected to be in a single entity and entity 0 is not checked!
func (d *DeviceRemoteImpl) VerifyUseCaseScenariosAndFeaturesSupport(
usecaseActor model.UseCaseActorType,
usecaseName model.UseCaseNameType,
scenarios []model.UseCaseScenarioSupportType,
serverFeatures []model.FeatureTypeType,
) bool {
remoteUseCaseManager := d.UseCaseManager()

usecases := remoteUseCaseManager.UseCaseInformation()
if len(usecases) == 0 {
return false
}

usecaseAndScenariosFound := false
for _, usecase := range usecases {
if usecase.Actor == nil || *usecase.Actor != usecaseActor {
continue
}

for _, support := range usecase.UseCaseSupport {
if support.UseCaseName == nil || *support.UseCaseName != usecaseName {
continue
}

if support.UseCaseAvailable == nil || !*support.UseCaseAvailable {
continue
}

var foundScenarios []model.UseCaseScenarioSupportType
for _, scenario := range support.ScenarioSupport {
if slices.Contains(scenarios, scenario) {
foundScenarios = append(foundScenarios, scenario)
}
}

if len(foundScenarios) == len(scenarios) {
usecaseAndScenariosFound = true
break
}
}

if usecaseAndScenariosFound {
break
}
}

if !usecaseAndScenariosFound {
return false
}

entities := d.Entities()
if len(entities) < 2 {
return false
}

entityWithServerFeaturesFound := false

for index, entity := range entities {
// ignore NodeManagement entity
if index == 0 {
continue
}

var foundServerFeatures []model.FeatureTypeType
for _, feature := range entity.Features() {
if feature.Role() != model.RoleTypeServer {
continue
}

if slices.Contains(serverFeatures, feature.Type()) {
foundServerFeatures = append(foundServerFeatures, feature.Type())
}
}

if len(serverFeatures) == len(foundServerFeatures) {
entityWithServerFeaturesFound = true
break
}
}

return entityWithServerFeaturesFound
}

func unmarshalFeature(entity *EntityRemoteImpl,
featureData model.NodeManagementDetailedDiscoveryFeatureInformationType,
) *FeatureRemoteImpl {
Expand Down
133 changes: 133 additions & 0 deletions spine/device_remote_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,136 @@ func (s *DeviceRemoteSuite) Test_FeatureByEntityTypeAndRole() {
feature = s.remoteDevice.FeatureByEntityTypeAndRole(entity, model.FeatureTypeTypeDeviceDiagnosis, model.RoleTypeServer)
assert.Nil(s.T(), feature)
}

func (s *DeviceRemoteSuite) Test_VerifyUseCaseScenariosAndFeaturesSupport() {
result := s.remoteDevice.VerifyUseCaseScenariosAndFeaturesSupport(
model.UseCaseActorTypeEVSE,
model.UseCaseNameTypeEVSECommissioningAndConfiguration,
[]model.UseCaseScenarioSupportType{},
[]model.FeatureTypeType{},
)
assert.Equal(s.T(), false, result)

s.remoteDevice.UseCaseManager().Add(
model.UseCaseActorTypeBatterySystem,
model.UseCaseNameTypeControlOfBattery,
model.SpecificationVersionType("1.0.0"),
true,
[]model.UseCaseScenarioSupportType{1},
)

result = s.remoteDevice.VerifyUseCaseScenariosAndFeaturesSupport(
model.UseCaseActorTypeEVSE,
model.UseCaseNameTypeEVSECommissioningAndConfiguration,
[]model.UseCaseScenarioSupportType{},
[]model.FeatureTypeType{},
)
assert.Equal(s.T(), false, result)

s.remoteDevice.UseCaseManager().Add(
model.UseCaseActorTypeEVSE,
model.UseCaseNameTypeEVCommissioningAndConfiguration,
model.SpecificationVersionType("1.0.0"),
true,
[]model.UseCaseScenarioSupportType{1},
)

result = s.remoteDevice.VerifyUseCaseScenariosAndFeaturesSupport(
model.UseCaseActorTypeEVSE,
model.UseCaseNameTypeEVSECommissioningAndConfiguration,
[]model.UseCaseScenarioSupportType{},
[]model.FeatureTypeType{},
)
assert.Equal(s.T(), false, result)

s.remoteDevice.UseCaseManager().Add(
model.UseCaseActorTypeEVSE,
model.UseCaseNameTypeEVSECommissioningAndConfiguration,
model.SpecificationVersionType("1.0.0"),
false,
[]model.UseCaseScenarioSupportType{1},
)

result = s.remoteDevice.VerifyUseCaseScenariosAndFeaturesSupport(
model.UseCaseActorTypeEVSE,
model.UseCaseNameTypeEVSECommissioningAndConfiguration,
[]model.UseCaseScenarioSupportType{},
[]model.FeatureTypeType{},
)
assert.Equal(s.T(), false, result)

s.remoteDevice.UseCaseManager().Add(
model.UseCaseActorTypeEVSE,
model.UseCaseNameTypeEVSECommissioningAndConfiguration,
model.SpecificationVersionType("1.0.0"),
true,
[]model.UseCaseScenarioSupportType{1},
)

result = s.remoteDevice.VerifyUseCaseScenariosAndFeaturesSupport(
model.UseCaseActorTypeEVSE,
model.UseCaseNameTypeEVSECommissioningAndConfiguration,
[]model.UseCaseScenarioSupportType{},
[]model.FeatureTypeType{},
)
assert.Equal(s.T(), true, result)

result = s.remoteDevice.VerifyUseCaseScenariosAndFeaturesSupport(
model.UseCaseActorTypeEVSE,
model.UseCaseNameTypeEVSECommissioningAndConfiguration,
[]model.UseCaseScenarioSupportType{2},
[]model.FeatureTypeType{},
)
assert.Equal(s.T(), false, result)

result = s.remoteDevice.VerifyUseCaseScenariosAndFeaturesSupport(
model.UseCaseActorTypeEVSE,
model.UseCaseNameTypeEVSECommissioningAndConfiguration,
[]model.UseCaseScenarioSupportType{1},
[]model.FeatureTypeType{},
)
assert.Equal(s.T(), true, result)

result = s.remoteDevice.VerifyUseCaseScenariosAndFeaturesSupport(
model.UseCaseActorTypeEVSE,
model.UseCaseNameTypeEVSECommissioningAndConfiguration,
[]model.UseCaseScenarioSupportType{1},
[]model.FeatureTypeType{model.FeatureTypeTypeElectricalConnection},
)
assert.Equal(s.T(), false, result)

entity := s.remoteDevice.Entity([]model.AddressEntityType{1})
assert.NotNil(s.T(), entity)

feature := spine.NewFeatureRemoteImpl(0, entity, model.FeatureTypeTypeElectricalConnection, model.RoleTypeClient)
entity.AddFeature(feature)

result = s.remoteDevice.VerifyUseCaseScenariosAndFeaturesSupport(
model.UseCaseActorTypeEVSE,
model.UseCaseNameTypeEVSECommissioningAndConfiguration,
[]model.UseCaseScenarioSupportType{1},
[]model.FeatureTypeType{model.FeatureTypeTypeElectricalConnection},
)
assert.Equal(s.T(), false, result)

feature = spine.NewFeatureRemoteImpl(0, entity, model.FeatureTypeTypeElectricalConnection, model.RoleTypeServer)
entity.AddFeature(feature)

result = s.remoteDevice.VerifyUseCaseScenariosAndFeaturesSupport(
model.UseCaseActorTypeEVSE,
model.UseCaseNameTypeEVSECommissioningAndConfiguration,
[]model.UseCaseScenarioSupportType{1},
[]model.FeatureTypeType{model.FeatureTypeTypeElectricalConnection},
)
assert.Equal(s.T(), true, result)

s.remoteDevice.RemoveByAddress(feature.Address().Entity)

result = s.remoteDevice.VerifyUseCaseScenariosAndFeaturesSupport(
model.UseCaseActorTypeEVSE,
model.UseCaseNameTypeEVSECommissioningAndConfiguration,
[]model.UseCaseScenarioSupportType{1},
[]model.FeatureTypeType{model.FeatureTypeTypeElectricalConnection},
)
assert.Equal(s.T(), false, result)
}

0 comments on commit 497fb1c

Please sign in to comment.