Skip to content

Commit 3814453

Browse files
committed
Properly support EG LPC & LPP for all device types
Depending on the devices type (Energy Management System or not), the nominal max values for LPC and LPP from a controllable systems have a different type. This change now uses the remote entities associated devices devicetype and uses the proper associated CharacteristicType value.
1 parent f635e34 commit 3814453

File tree

8 files changed

+188
-106
lines changed

8 files changed

+188
-106
lines changed

usecases/api/eg_lpc.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,9 @@ type EgLPCInterface interface {
8383
// Scenario 4
8484

8585
// return nominal maximum active (real) power the Controllable System is
86-
// able to consume according to the device label or data sheet.
86+
// able to consume according to the contract (EMS), device label or data sheet.
8787
//
8888
// parameters:
8989
// - entity: the entity of the e.g. EVSE
90-
PowerConsumptionNominalMax(entity spineapi.EntityRemoteInterface) (float64, error)
90+
ConsumptionNominalMax(entity spineapi.EntityRemoteInterface) (float64, error)
9191
}

usecases/api/eg_lpp.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,9 @@ type EgLPPInterface interface {
8383
// Scenario 4
8484

8585
// return nominal maximum active (real) power the Controllable System is
86-
// able to produce according to the device label or data sheet.
86+
// able to produce according to the contract (EMS), device label or data sheet.
8787
//
8888
// parameters:
8989
// - entity: the entity of the e.g. EVSE
90-
PowerProductionNominalMax(entity spineapi.EntityRemoteInterface) (float64, error)
90+
ProductionNominalMax(entity spineapi.EntityRemoteInterface) (float64, error)
9191
}

usecases/eg/lpc/public.go

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -237,8 +237,8 @@ func (e *LPC) WriteFailsafeDurationMinimum(entity spineapi.EntityRemoteInterface
237237
// Scenario 4
238238

239239
// return nominal maximum active (real) power the Controllable System is
240-
// able to consume according to the device label or data sheet.
241-
func (e *LPC) PowerConsumptionNominalMax(entity spineapi.EntityRemoteInterface) (float64, error) {
240+
// able to consume according to the contract (EMS), device label or data sheet.
241+
func (e *LPC) ConsumptionNominalMax(entity spineapi.EntityRemoteInterface) (float64, error) {
242242
if !e.IsCompatibleEntityType(entity) {
243243
return 0, api.ErrNoCompatibleEntity
244244
}
@@ -250,12 +250,33 @@ func (e *LPC) PowerConsumptionNominalMax(entity spineapi.EntityRemoteInterface)
250250

251251
filter := model.ElectricalConnectionCharacteristicDataType{
252252
CharacteristicContext: util.Ptr(model.ElectricalConnectionCharacteristicContextTypeEntity),
253-
CharacteristicType: util.Ptr(model.ElectricalConnectionCharacteristicTypeTypePowerConsumptionNominalMax),
253+
CharacteristicType: util.Ptr(e.characteristicType(entity)),
254254
}
255255
data, err := electricalConnection.GetCharacteristicsForFilter(filter)
256-
if err != nil || len(data) == 0 || data[0].Value == nil {
256+
if err != nil {
257257
return 0, err
258+
} else if len(data) == 0 || data[0].Value == nil {
259+
return 0, api.ErrDataNotAvailable
258260
}
259261

260262
return data[0].Value.GetValue(), nil
261263
}
264+
265+
// returns the characteristictype depending on the remote entities device devicetype
266+
func (e *LPC) characteristicType(entity spineapi.EntityRemoteInterface) model.ElectricalConnectionCharacteristicTypeType {
267+
// According to LPC V1.0 2.2, lines 400ff:
268+
// - a HEMS provides contractual consumption nominal max
269+
// - any other devices provides power consupmtion nominal max
270+
characteristic := model.ElectricalConnectionCharacteristicTypeTypePowerConsumptionNominalMax
271+
272+
if entity == nil || entity.Device() == nil {
273+
return characteristic
274+
}
275+
276+
deviceType := entity.Device().DeviceType()
277+
if deviceType == nil || *deviceType == model.DeviceTypeTypeEnergyManagementSystem {
278+
characteristic = model.ElectricalConnectionCharacteristicTypeTypeContractualConsumptionNominalMax
279+
}
280+
281+
return characteristic
282+
}

usecases/eg/lpc/public_test.go

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -333,11 +333,11 @@ func (s *EgLPCSuite) Test_WriteFailsafeDurationMinimum() {
333333
}
334334

335335
func (s *EgLPCSuite) Test_PowerConsumptionNominalMax() {
336-
data, err := s.sut.PowerConsumptionNominalMax(s.mockRemoteEntity)
336+
data, err := s.sut.ConsumptionNominalMax(s.mockRemoteEntity)
337337
assert.NotNil(s.T(), err)
338338
assert.Equal(s.T(), 0.0, data)
339339

340-
data, err = s.sut.PowerConsumptionNominalMax(s.monitoredEntity)
340+
data, err = s.sut.ConsumptionNominalMax(s.monitoredEntity)
341341
assert.NotNil(s.T(), err)
342342
assert.Equal(s.T(), 0.0, data)
343343

@@ -357,7 +357,27 @@ func (s *EgLPCSuite) Test_PowerConsumptionNominalMax() {
357357
fErr := rFeature.UpdateData(model.FunctionTypeElectricalConnectionCharacteristicListData, charData, nil, nil)
358358
assert.Nil(s.T(), fErr)
359359

360-
data, err = s.sut.PowerConsumptionNominalMax(s.monitoredEntity)
360+
data, err = s.sut.ConsumptionNominalMax(s.monitoredEntity)
361+
assert.NotNil(s.T(), err)
362+
assert.Equal(s.T(), 0.0, data)
363+
364+
charData = &model.ElectricalConnectionCharacteristicListDataType{
365+
ElectricalConnectionCharacteristicData: []model.ElectricalConnectionCharacteristicDataType{
366+
{
367+
ElectricalConnectionId: util.Ptr(model.ElectricalConnectionIdType(0)),
368+
CharacteristicId: util.Ptr(model.ElectricalConnectionCharacteristicIdType(0)),
369+
CharacteristicContext: util.Ptr(model.ElectricalConnectionCharacteristicContextTypeEntity),
370+
CharacteristicType: util.Ptr(model.ElectricalConnectionCharacteristicTypeTypeContractualConsumptionNominalMax),
371+
Value: model.NewScaledNumberType(8000),
372+
},
373+
},
374+
}
375+
376+
rFeature = s.remoteDevice.FeatureByEntityTypeAndRole(s.monitoredEntity, model.FeatureTypeTypeElectricalConnection, model.RoleTypeServer)
377+
fErr = rFeature.UpdateData(model.FunctionTypeElectricalConnectionCharacteristicListData, charData, nil, nil)
378+
assert.Nil(s.T(), fErr)
379+
380+
data, err = s.sut.ConsumptionNominalMax(s.monitoredEntity)
361381
assert.Nil(s.T(), err)
362382
assert.Equal(s.T(), 8000.0, data)
363383
}

usecases/eg/lpp/public.go

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -236,8 +236,8 @@ func (e *LPP) WriteFailsafeDurationMinimum(entity spineapi.EntityRemoteInterface
236236
// Scenario 4
237237

238238
// return nominal maximum active (real) power the Controllable System is
239-
// able to produce according to the device label or data sheet.
240-
func (e *LPP) PowerProductionNominalMax(entity spineapi.EntityRemoteInterface) (float64, error) {
239+
// able to produce according to the contract (EMS), device label or data sheet.
240+
func (e *LPP) ProductionNominalMax(entity spineapi.EntityRemoteInterface) (float64, error) {
241241
if !e.IsCompatibleEntityType(entity) {
242242
return 0, api.ErrNoCompatibleEntity
243243
}
@@ -249,12 +249,33 @@ func (e *LPP) PowerProductionNominalMax(entity spineapi.EntityRemoteInterface) (
249249

250250
filter := model.ElectricalConnectionCharacteristicDataType{
251251
CharacteristicContext: util.Ptr(model.ElectricalConnectionCharacteristicContextTypeEntity),
252-
CharacteristicType: util.Ptr(model.ElectricalConnectionCharacteristicTypeTypePowerProductionNominalMax),
252+
CharacteristicType: util.Ptr(e.characteristicType(entity)),
253253
}
254254
data, err := electricalConnection.GetCharacteristicsForFilter(filter)
255-
if err != nil || len(data) == 0 || data[0].Value == nil {
255+
if err != nil {
256256
return 0, err
257+
} else if len(data) == 0 || data[0].Value == nil {
258+
return 0, api.ErrDataNotAvailable
257259
}
258260

259261
return data[0].Value.GetValue(), nil
260262
}
263+
264+
// returns the characteristictype depending on the remote entities device devicetype
265+
func (e *LPP) characteristicType(entity spineapi.EntityRemoteInterface) model.ElectricalConnectionCharacteristicTypeType {
266+
// According to LPC V1.0 2.2, lines 400ff:
267+
// - a HEMS provides contractual consumption nominal max
268+
// - any other devices provides power consupmtion nominal max
269+
characteristic := model.ElectricalConnectionCharacteristicTypeTypePowerProductionNominalMax
270+
271+
if entity == nil || entity.Device() == nil {
272+
return characteristic
273+
}
274+
275+
deviceType := entity.Device().DeviceType()
276+
if deviceType == nil || *deviceType == model.DeviceTypeTypeEnergyManagementSystem {
277+
characteristic = model.ElectricalConnectionCharacteristicTypeTypeContractualProductionNominalMax
278+
}
279+
280+
return characteristic
281+
}

usecases/eg/lpp/public_test.go

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -327,11 +327,11 @@ func (s *EgLPPSuite) Test_WriteFailsafeDurationMinimum() {
327327
}
328328

329329
func (s *EgLPPSuite) Test_PowerProductionNominalMax() {
330-
data, err := s.sut.PowerProductionNominalMax(s.mockRemoteEntity)
330+
data, err := s.sut.ProductionNominalMax(s.mockRemoteEntity)
331331
assert.NotNil(s.T(), err)
332332
assert.Equal(s.T(), 0.0, data)
333333

334-
data, err = s.sut.PowerProductionNominalMax(s.monitoredEntity)
334+
data, err = s.sut.ProductionNominalMax(s.monitoredEntity)
335335
assert.NotNil(s.T(), err)
336336
assert.Equal(s.T(), 0.0, data)
337337

@@ -351,7 +351,27 @@ func (s *EgLPPSuite) Test_PowerProductionNominalMax() {
351351
fErr := rFeature.UpdateData(model.FunctionTypeElectricalConnectionCharacteristicListData, charData, nil, nil)
352352
assert.Nil(s.T(), fErr)
353353

354-
data, err = s.sut.PowerProductionNominalMax(s.monitoredEntity)
354+
data, err = s.sut.ProductionNominalMax(s.monitoredEntity)
355+
assert.NotNil(s.T(), err)
356+
assert.Equal(s.T(), 0.0, data)
357+
358+
charData = &model.ElectricalConnectionCharacteristicListDataType{
359+
ElectricalConnectionCharacteristicData: []model.ElectricalConnectionCharacteristicDataType{
360+
{
361+
ElectricalConnectionId: util.Ptr(model.ElectricalConnectionIdType(0)),
362+
CharacteristicId: util.Ptr(model.ElectricalConnectionCharacteristicIdType(0)),
363+
CharacteristicContext: util.Ptr(model.ElectricalConnectionCharacteristicContextTypeEntity),
364+
CharacteristicType: util.Ptr(model.ElectricalConnectionCharacteristicTypeTypeContractualProductionNominalMax),
365+
Value: model.NewScaledNumberType(8000),
366+
},
367+
},
368+
}
369+
370+
rFeature = s.remoteDevice.FeatureByEntityTypeAndRole(s.monitoredEntity, model.FeatureTypeTypeElectricalConnection, model.RoleTypeServer)
371+
fErr = rFeature.UpdateData(model.FunctionTypeElectricalConnectionCharacteristicListData, charData, nil, nil)
372+
assert.Nil(s.T(), fErr)
373+
374+
data, err = s.sut.ProductionNominalMax(s.monitoredEntity)
355375
assert.Nil(s.T(), err)
356376
assert.Equal(s.T(), 8000.0, data)
357377
}

usecases/mocks/EgLPCInterface.go

Lines changed: 56 additions & 56 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)