diff --git a/api/api.go b/api/api.go index d213ed6..d71b17b 100644 --- a/api/api.go +++ b/api/api.go @@ -45,7 +45,9 @@ type HeartbeatManagerInterface interface { type OperationsInterface interface { Write() bool + WritePartial() bool Read() bool + ReadPartial() bool String() string Information() *model.PossibleOperationsType } diff --git a/api/function.go b/api/function.go index ba006c8..263a025 100644 --- a/api/function.go +++ b/api/function.go @@ -7,10 +7,14 @@ import "github.com/enbility/spine-go/model" type FunctionDataCmdInterface interface { FunctionDataInterface // Get the CmdType data for a read command + // + // Note: partialSelector and elements have to be pointers! ReadCmdType(partialSelector any, elements any) model.CmdType // Get the CmdType data for a reply command ReplyCmdType(partial bool) model.CmdType // Get the CmdType data for a notify or write command + // + // Note: partialSelector and elements have to be pointers! NotifyOrWriteCmdType(deleteSelector, partialSelector any, partialWithoutSelector bool, deleteElements any) model.CmdType } diff --git a/mocks/OperationsInterface.go b/mocks/OperationsInterface.go index 05e96a7..9cedf5f 100644 --- a/mocks/OperationsInterface.go +++ b/mocks/OperationsInterface.go @@ -112,6 +112,51 @@ func (_c *OperationsInterface_Read_Call) RunAndReturn(run func() bool) *Operatio return _c } +// ReadPartial provides a mock function with given fields: +func (_m *OperationsInterface) ReadPartial() bool { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for ReadPartial") + } + + var r0 bool + if rf, ok := ret.Get(0).(func() bool); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(bool) + } + + return r0 +} + +// OperationsInterface_ReadPartial_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ReadPartial' +type OperationsInterface_ReadPartial_Call struct { + *mock.Call +} + +// ReadPartial is a helper method to define mock.On call +func (_e *OperationsInterface_Expecter) ReadPartial() *OperationsInterface_ReadPartial_Call { + return &OperationsInterface_ReadPartial_Call{Call: _e.mock.On("ReadPartial")} +} + +func (_c *OperationsInterface_ReadPartial_Call) Run(run func()) *OperationsInterface_ReadPartial_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *OperationsInterface_ReadPartial_Call) Return(_a0 bool) *OperationsInterface_ReadPartial_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *OperationsInterface_ReadPartial_Call) RunAndReturn(run func() bool) *OperationsInterface_ReadPartial_Call { + _c.Call.Return(run) + return _c +} + // String provides a mock function with given fields: func (_m *OperationsInterface) String() string { ret := _m.Called() @@ -202,6 +247,51 @@ func (_c *OperationsInterface_Write_Call) RunAndReturn(run func() bool) *Operati return _c } +// WritePartial provides a mock function with given fields: +func (_m *OperationsInterface) WritePartial() bool { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for WritePartial") + } + + var r0 bool + if rf, ok := ret.Get(0).(func() bool); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(bool) + } + + return r0 +} + +// OperationsInterface_WritePartial_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WritePartial' +type OperationsInterface_WritePartial_Call struct { + *mock.Call +} + +// WritePartial is a helper method to define mock.On call +func (_e *OperationsInterface_Expecter) WritePartial() *OperationsInterface_WritePartial_Call { + return &OperationsInterface_WritePartial_Call{Call: _e.mock.On("WritePartial")} +} + +func (_c *OperationsInterface_WritePartial_Call) Run(run func()) *OperationsInterface_WritePartial_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *OperationsInterface_WritePartial_Call) Return(_a0 bool) *OperationsInterface_WritePartial_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *OperationsInterface_WritePartial_Call) RunAndReturn(run func() bool) *OperationsInterface_WritePartial_Call { + _c.Call.Return(run) + return _c +} + // NewOperationsInterface creates a new instance of OperationsInterface. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. // The first argument is typically a *testing.T value. func NewOperationsInterface(t interface { diff --git a/model/commandframe_additions_test.go b/model/commandframe_additions_test.go index a1c32d8..0e6e294 100644 --- a/model/commandframe_additions_test.go +++ b/model/commandframe_additions_test.go @@ -34,7 +34,9 @@ func TestFilterType_Selector_SetDataForFunction(t *testing.T) { cmd.SetDataForFunction(EEBusTagTypeTypeSelector, FunctionTypeElectricalConnectionDescriptionListData, nil) assert.Nil(t, cmd.ElectricalConnectionDescriptionListDataSelectors) - var test *ElectricalConnectionDescriptionListDataSelectorsType + test := &ElectricalConnectionDescriptionListDataSelectorsType{ + ElectricalConnectionId: util.Ptr(ElectricalConnectionIdType(1)), + } cmd = FilterType{} cmd.SetDataForFunction(EEBusTagTypeTypeSelector, FunctionTypeElectricalConnectionDescriptionListData, test) assert.NotNil(t, cmd.ElectricalConnectionDescriptionListDataSelectors) diff --git a/model/deviceconfiguration.go b/model/deviceconfiguration.go index f9a2eca..2da9d70 100644 --- a/model/deviceconfiguration.go +++ b/model/deviceconfiguration.go @@ -129,8 +129,8 @@ type DeviceConfigurationKeyValueDescriptionListDataType struct { } type DeviceConfigurationKeyValueDescriptionListDataSelectorsType struct { - KeyId *DeviceConfigurationKeyIdType `json:"keyId,omitempty"` - KeyName *string `json:"keyName,omitempty"` + KeyId *DeviceConfigurationKeyIdType `json:"keyId,omitempty"` + KeyName *DeviceConfigurationKeyNameType `json:"keyName,omitempty"` } type DeviceConfigurationKeyValueConstraintsDataType struct { diff --git a/spine/feature_local.go b/spine/feature_local.go index 0ec9d31..feadfa7 100644 --- a/spine/feature_local.go +++ b/spine/feature_local.go @@ -76,7 +76,7 @@ func (r *FeatureLocal) AddFunctionType(function model.FunctionType, read, write if r.operations[function] != nil { return } - r.operations[function] = NewOperations(read, write) + r.operations[function] = NewOperations(read, false, write, write) if r.role == model.RoleTypeServer && r.ftype == model.FeatureTypeTypeDeviceDiagnosis && diff --git a/spine/feature_remote.go b/spine/feature_remote.go index 899e05a..6c525b2 100644 --- a/spine/feature_remote.go +++ b/spine/feature_remote.go @@ -82,7 +82,12 @@ func (r *FeatureRemote) SetOperations(functions []model.FunctionPropertyType) { if sf.PossibleOperations == nil { continue } - r.operations[*sf.Function] = NewOperations(sf.PossibleOperations.Read != nil, sf.PossibleOperations.Write != nil) + r.operations[*sf.Function] = NewOperations( + sf.PossibleOperations.Read != nil, + sf.PossibleOperations.Read != nil && sf.PossibleOperations.Read.Partial != nil, + sf.PossibleOperations.Write != nil, + sf.PossibleOperations.Write != nil && sf.PossibleOperations.Write.Partial != nil, + ) } } diff --git a/spine/function_data_cmd.go b/spine/function_data_cmd.go index 2035db1..850e915 100644 --- a/spine/function_data_cmd.go +++ b/spine/function_data_cmd.go @@ -76,10 +76,10 @@ func filtersForSelectorsElements(functionType model.FunctionType, filters []mode if partialSelector != nil || readElements != nil { filter := model.FilterType{CmdControl: &model.CmdControlType{Partial: &model.ElementTagType{}}} if partialSelector != nil { - filter = addSelectorToFilter(filter, functionType, &partialSelector) + filter = addSelectorToFilter(filter, functionType, partialSelector) } if readElements != nil { - filter = addElementToFilter(filter, functionType, &readElements) + filter = addElementToFilter(filter, functionType, readElements) } filters = append(filters, filter) } @@ -92,7 +92,7 @@ func filterEmptyPartial() []model.FilterType { return []model.FilterType{*model.NewFilterTypePartial()} } -func addSelectorToFilter[T any](filter model.FilterType, function model.FunctionType, data *T) model.FilterType { +func addSelectorToFilter(filter model.FilterType, function model.FunctionType, data any) model.FilterType { result := filter result.SetDataForFunction(model.EEBusTagTypeTypeSelector, function, data) @@ -100,7 +100,7 @@ func addSelectorToFilter[T any](filter model.FilterType, function model.Function return result } -func addElementToFilter[T any](filter model.FilterType, function model.FunctionType, data *T) model.FilterType { +func addElementToFilter(filter model.FilterType, function model.FunctionType, data any) model.FilterType { result := filter result.SetDataForFunction(model.EEbusTagTypeTypeElements, function, data) diff --git a/spine/function_data_cmd_test.go b/spine/function_data_cmd_test.go index 4a42d88..91b5ad2 100644 --- a/spine/function_data_cmd_test.go +++ b/spine/function_data_cmd_test.go @@ -36,7 +36,10 @@ func (suite *FctDataCmdSuite) TestFunctionDataCmd_ReadCmd() { assert.Nil(suite.T(), readCmd.Function) partialS := model.NewFilterTypePartial() - readCmd = suite.sut.ReadCmdType(partialS, nil) + partialE := &model.DeviceClassificationManufacturerDataElementsType{ + DeviceName: util.Ptr(model.ElementTagType{}), + } + readCmd = suite.sut.ReadCmdType(partialS, partialE) assert.NotNil(suite.T(), readCmd.DeviceClassificationManufacturerData) assert.Nil(suite.T(), readCmd.DeviceClassificationManufacturerData.DeviceName) assert.NotNil(suite.T(), readCmd.Function) diff --git a/spine/operations.go b/spine/operations.go index ff81418..b0e0be6 100644 --- a/spine/operations.go +++ b/spine/operations.go @@ -6,26 +6,36 @@ import ( ) type Operations struct { - read, write bool + read, write bool + readPartial, writePartial bool } var _ api.OperationsInterface = (*Operations)(nil) -func NewOperations(read, write bool) *Operations { +func NewOperations(read, readPartial, write, writePartial bool) *Operations { return &Operations{ - read: read, - write: write, + read: read, + readPartial: readPartial, + write: write, + writePartial: writePartial, } } - func (r *Operations) Read() bool { return r.read } +func (r *Operations) ReadPartial() bool { + return r.readPartial +} + func (r *Operations) Write() bool { return r.write } +func (r *Operations) WritePartial() bool { + return r.writePartial +} + func (r *Operations) String() string { switch { case r.read && !r.write: @@ -41,10 +51,18 @@ func (r *Operations) Information() *model.PossibleOperationsType { res := new(model.PossibleOperationsType) if r.read { res.Read = &model.PossibleOperationsReadType{} + if r.readPartial { + res.Read = &model.PossibleOperationsReadType{ + Partial: &model.ElementTagType{}, + } + } } if r.write { - res.Write = &model.PossibleOperationsWriteType{ - Partial: &model.ElementTagType{}, + res.Write = &model.PossibleOperationsWriteType{} + if r.writePartial { + res.Write = &model.PossibleOperationsWriteType{ + Partial: &model.ElementTagType{}, + } } } diff --git a/spine/operations_test.go b/spine/operations_test.go index b9cbdbe..bb46c7f 100644 --- a/spine/operations_test.go +++ b/spine/operations_test.go @@ -7,7 +7,7 @@ import ( ) func TestOperations(t *testing.T) { - operations := NewOperations(true, false) + operations := NewOperations(true, true, false, false) assert.NotNil(t, operations) text := operations.String() @@ -16,7 +16,16 @@ func TestOperations(t *testing.T) { data := operations.Information() assert.NotNil(t, data) - operations2 := NewOperations(true, true) + result := operations.Read() + assert.True(t, result) + result = operations.ReadPartial() + assert.True(t, result) + result = operations.Write() + assert.False(t, result) + result = operations.WritePartial() + assert.False(t, result) + + operations2 := NewOperations(true, false, true, true) assert.NotNil(t, operations2) text = operations2.String() @@ -25,7 +34,16 @@ func TestOperations(t *testing.T) { data = operations2.Information() assert.NotNil(t, data) - operations3 := NewOperations(false, false) + result = operations2.Read() + assert.True(t, result) + result = operations2.ReadPartial() + assert.False(t, result) + result = operations2.Write() + assert.True(t, result) + result = operations2.WritePartial() + assert.True(t, result) + + operations3 := NewOperations(false, false, false, false) assert.NotNil(t, operations3) text = operations3.String() @@ -33,4 +51,13 @@ func TestOperations(t *testing.T) { data = operations3.Information() assert.NotNil(t, data) + + result = operations3.Read() + assert.False(t, result) + result = operations3.ReadPartial() + assert.False(t, result) + result = operations3.Write() + assert.False(t, result) + result = operations3.WritePartial() + assert.False(t, result) }