Skip to content

Commit

Permalink
Add support for deleting TimePeriod on purpose (#118)
Browse files Browse the repository at this point in the history
When using LPC/LPP, setting the duration to 0 has a different meaning than not having a duration value at all. Therefor it is now possible to delete the Duration value explicitly on a write.
  • Loading branch information
DerAndereAndi authored Oct 7, 2024
2 parents f4be567 + db5fd16 commit 02ffaa9
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 57 deletions.
9 changes: 5 additions & 4 deletions usecases/api/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,11 @@ type LoadLimitsPhase struct {

// Defines a limit data set
type LoadLimit struct {
Duration time.Duration // the duration of the limit,
IsChangeable bool // if the value can be changed via write, ignored when writing data
IsActive bool // if the limit is active
Value float64 // the limit
Duration time.Duration // the duration of the limit,
IsChangeable bool // if the value can be changed via write, ignored when writing data
IsActive bool // if the limit is active
Value float64 // the limit
DeleteDuration bool // if the Duration (TimePeriod in SPINE) should be deleted (only used for write commands. Relevant for LPC & LPP only)
}

// identification
Expand Down
109 changes: 64 additions & 45 deletions usecases/cs/lpc/usecase_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@ func (s *CsLPCSuite) Test_loadControlServerAndLimitId() {
}

func (s *CsLPCSuite) Test_loadControlWriteCB() {
msg := spineapi.Message{}
msg0 := &spineapi.Message{}

s.sut.loadControlWriteCB(&msg)
s.sut.loadControlWriteCB(msg0)
assert.False(s.T(), s.eventCalled)

msg = spineapi.Message{
msg1 := &spineapi.Message{
RequestHeader: &model.HeaderType{
MsgCounter: util.Ptr(model.MsgCounterType(500)),
},
Expand All @@ -43,74 +43,93 @@ func (s *CsLPCSuite) Test_loadControlWriteCB() {
EntityRemote: s.monitoredEntity,
}

msg0 := msg
s.sut.loadControlWriteCB(&msg0)
s.sut.loadControlWriteCB(msg1)

msg1 := msg
msg1.RequestHeader.MsgCounter = util.Ptr(model.MsgCounterType(501))
msg1.Cmd = model.CmdType{
LoadControlLimitListData: &model.LoadControlLimitListDataType{
LoadControlLimitData: []model.LoadControlLimitDataType{},
msg2 := &spineapi.Message{
RequestHeader: &model.HeaderType{
MsgCounter: util.Ptr(model.MsgCounterType(501)),
},
Cmd: model.CmdType{
LoadControlLimitListData: &model.LoadControlLimitListDataType{
LoadControlLimitData: []model.LoadControlLimitDataType{},
},
},
DeviceRemote: s.remoteDevice,
EntityRemote: s.monitoredEntity,
}

s.sut.loadControlWriteCB(&msg1)
s.sut.loadControlWriteCB(msg2)
assert.False(s.T(), s.eventCalled)

msg2 := msg
msg2.RequestHeader.MsgCounter = util.Ptr(model.MsgCounterType(502))
msg2.Cmd = model.CmdType{
LoadControlLimitListData: &model.LoadControlLimitListDataType{
LoadControlLimitData: []model.LoadControlLimitDataType{
{},
msg3 := &spineapi.Message{
RequestHeader: &model.HeaderType{
MsgCounter: util.Ptr(model.MsgCounterType(502)),
},
Cmd: model.CmdType{
LoadControlLimitListData: &model.LoadControlLimitListDataType{
LoadControlLimitData: []model.LoadControlLimitDataType{
{},
},
},
},
DeviceRemote: s.remoteDevice,
EntityRemote: s.monitoredEntity,
}

s.sut.loadControlWriteCB(&msg2)
s.sut.loadControlWriteCB(msg3)
assert.False(s.T(), s.eventCalled)

msg3 := msg
msg3.RequestHeader.MsgCounter = util.Ptr(model.MsgCounterType(503))
msg3.Cmd = model.CmdType{
LoadControlLimitListData: &model.LoadControlLimitListDataType{
LoadControlLimitData: []model.LoadControlLimitDataType{
{
LimitId: util.Ptr(model.LoadControlLimitIdType(0)),
IsLimitActive: util.Ptr(true),
Value: model.NewScaledNumberType(1000),
TimePeriod: model.NewTimePeriodTypeWithRelativeEndTime(time.Minute * 2),
msg4 := &spineapi.Message{
RequestHeader: &model.HeaderType{
MsgCounter: util.Ptr(model.MsgCounterType(503)),
},
Cmd: model.CmdType{
LoadControlLimitListData: &model.LoadControlLimitListDataType{
LoadControlLimitData: []model.LoadControlLimitDataType{
{
LimitId: util.Ptr(model.LoadControlLimitIdType(0)),
IsLimitActive: util.Ptr(true),
Value: model.NewScaledNumberType(1000),
TimePeriod: model.NewTimePeriodTypeWithRelativeEndTime(time.Minute * 2),
},
},
},
},
DeviceRemote: s.remoteDevice,
EntityRemote: s.monitoredEntity,
}

s.sut.loadControlWriteCB(&msg3)
s.sut.loadControlWriteCB(msg4)
assert.True(s.T(), s.eventCalled)

msg4 := msg
msg4.RequestHeader.MsgCounter = util.Ptr(model.MsgCounterType(504))
msg4.Cmd = model.CmdType{
Filter: []model.FilterType{
{
CmdControl: &model.CmdControlType{
Partial: util.Ptr(model.ElementTagType{}),
},
},
msg5 := &spineapi.Message{
RequestHeader: &model.HeaderType{
MsgCounter: util.Ptr(model.MsgCounterType(504)),
},
LoadControlLimitListData: &model.LoadControlLimitListDataType{
LoadControlLimitData: []model.LoadControlLimitDataType{
Cmd: model.CmdType{
Filter: []model.FilterType{
{
LimitId: util.Ptr(model.LoadControlLimitIdType(0)),
IsLimitActive: util.Ptr(true),
Value: model.NewScaledNumberType(5000),
TimePeriod: model.NewTimePeriodTypeWithRelativeEndTime(time.Hour * 3),
CmdControl: &model.CmdControlType{
Partial: util.Ptr(model.ElementTagType{}),
},
},
},
LoadControlLimitListData: &model.LoadControlLimitListDataType{
LoadControlLimitData: []model.LoadControlLimitDataType{
{
LimitId: util.Ptr(model.LoadControlLimitIdType(0)),
IsLimitActive: util.Ptr(true),
Value: model.NewScaledNumberType(5000),
TimePeriod: model.NewTimePeriodTypeWithRelativeEndTime(time.Hour * 3),
},
},
},
},
DeviceRemote: s.remoteDevice,
EntityRemote: s.monitoredEntity,
}

s.sut.loadControlWriteCB(&msg4)
s.sut.loadControlWriteCB(msg5)
assert.True(s.T(), s.eventCalled)
}

Expand Down
21 changes: 13 additions & 8 deletions usecases/internal/loadcontrol.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,9 @@ func WriteLoadControlLimit(
return nil, api.ErrNotSupported
}

var deleteSelectors *model.LoadControlLimitListDataSelectorsType
var deleteElements *model.LoadControlLimitDataElementsType

newLimit := model.LoadControlLimitDataType{
LimitId: item.LimitId,
IsLimitActive: util.Ptr(limit.IsActive),
Expand All @@ -152,16 +155,18 @@ func WriteLoadControlLimit(
}
}

limitData = append(limitData, newLimit)

// always delete the timePeriod first
deleteSelectors := &model.LoadControlLimitListDataSelectorsType{
LimitId: currentLimits[0].LimitId,
}
deleteElements := &model.LoadControlLimitDataElementsType{
TimePeriod: &model.TimePeriodElementsType{},
// should we delete the TimePeriod value?
if limit.DeleteDuration {
deleteSelectors = &model.LoadControlLimitListDataSelectorsType{
LimitId: currentLimits[0].LimitId,
}
deleteElements = &model.LoadControlLimitDataElementsType{
TimePeriod: &model.TimePeriodElementsType{},
}
}

limitData = append(limitData, newLimit)

msgCounter, err := loadControl.WriteLimitData(limitData, deleteSelectors, deleteElements)

if resultCB != nil && msgCounter != nil {
Expand Down
11 changes: 11 additions & 0 deletions usecases/internal/loadcontrol_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -877,6 +877,17 @@ func (s *InternalSuite) Test_WriteLoadControlLimit() {
s.mux.Lock()
assert.True(s.T(), cbInvoked)
s.mux.Unlock()

loadLimit = ucapi.LoadLimit{
Duration: 0,
IsActive: true,
Value: 5000,
DeleteDuration: true,
}

msgCounter, err = WriteLoadControlLimit(s.localEntity, s.monitoredEntity, filter, loadLimit, nil)
assert.Nil(s.T(), err)
assert.NotNil(s.T(), msgCounter)
}

func (s *InternalSuite) Test_WriteLoadControlLimits() {
Expand Down

0 comments on commit 02ffaa9

Please sign in to comment.