Skip to content
This repository was archived by the owner on Jun 29, 2024. It is now read-only.

Commit 072fc37

Browse files
committed
Support UCLPC and UCLPP server running together
1 parent 02b8f69 commit 072fc37

File tree

3 files changed

+175
-112
lines changed

3 files changed

+175
-112
lines changed

cmd/democem/democem.go

+21
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"github.com/enbility/cemd/cem"
99
"github.com/enbility/cemd/ucevsecc"
1010
"github.com/enbility/cemd/uclpcserver"
11+
"github.com/enbility/cemd/uclppserver"
1112
eebusapi "github.com/enbility/eebus-go/api"
1213
"github.com/enbility/ship-go/logging"
1314
)
@@ -53,6 +54,26 @@ func (d *DemoCem) Setup() error {
5354
logging.Log().Error(err)
5455
}
5556

57+
lpps := uclppserver.NewUCLPP(d.cem.Service, d.entityEventCB)
58+
d.cem.AddUseCase(lpps)
59+
60+
if err := lpps.SetProductionLimit(api.LoadLimit{
61+
IsChangeable: true,
62+
IsActive: false,
63+
Value: 0,
64+
}); err != nil {
65+
logging.Log().Error(err)
66+
}
67+
if err := lpps.SetContractualProductionNominalMax(-7000); err != nil {
68+
logging.Log().Error(err)
69+
}
70+
if err := lpps.SetFailsafeProductionActivePowerLimit(0, true); err != nil {
71+
logging.Log().Error(err)
72+
}
73+
if err := lpps.SetFailsafeDurationMinimum(time.Hour*2, true); err != nil {
74+
logging.Log().Error(err)
75+
}
76+
5677
evsecc := ucevsecc.NewUCEVSECC(d.cem.Service, d.entityEventCB)
5778
d.cem.AddUseCase(evsecc)
5879

uclpcserver/uclpc.go

+77-56
Original file line numberDiff line numberDiff line change
@@ -55,75 +55,92 @@ func (e *UCLPCServer) AddFeatures() {
5555

5656
var limitId model.LoadControlLimitIdType = 0
5757
// get the highest limitId
58-
if desc, err := spine.LocalFeatureDataCopyOfType[*model.LoadControlLimitDescriptionListDataType](
59-
f, model.FunctionTypeLoadControlLimitDescriptionListData); err == nil && desc.LoadControlLimitDescriptionData != nil {
58+
desc, err := spine.LocalFeatureDataCopyOfType[*model.LoadControlLimitDescriptionListDataType](
59+
f, model.FunctionTypeLoadControlLimitDescriptionListData)
60+
if err == nil && desc.LoadControlLimitDescriptionData != nil {
6061
for _, desc := range desc.LoadControlLimitDescriptionData {
6162
if desc.LimitId != nil && *desc.LimitId >= limitId {
6263
limitId++
6364
}
6465
}
6566
}
6667

67-
loadControlDesc := &model.LoadControlLimitDescriptionListDataType{
68-
LoadControlLimitDescriptionData: []model.LoadControlLimitDescriptionDataType{
69-
{
70-
LimitId: eebusutil.Ptr(model.LoadControlLimitIdType(limitId)),
71-
LimitType: eebusutil.Ptr(model.LoadControlLimitTypeTypeSignDependentAbsValueLimit),
72-
LimitCategory: eebusutil.Ptr(model.LoadControlCategoryTypeObligation),
73-
LimitDirection: eebusutil.Ptr(model.EnergyDirectionTypeConsume),
74-
MeasurementId: eebusutil.Ptr(model.MeasurementIdType(0)), // This is a fake Measurement ID, as there is no Electrical Connection server defined, it can't provide any meaningful. But KEO requires this to be set :(
75-
Unit: eebusutil.Ptr(model.UnitOfMeasurementTypeW),
76-
ScopeType: eebusutil.Ptr(model.ScopeTypeTypeActivePowerLimit),
77-
},
78-
},
68+
if desc == nil || len(desc.LoadControlLimitDescriptionData) == 0 {
69+
desc = &model.LoadControlLimitDescriptionListDataType{
70+
LoadControlLimitDescriptionData: []model.LoadControlLimitDescriptionDataType{},
71+
}
7972
}
80-
f.SetData(model.FunctionTypeLoadControlLimitDescriptionListData, loadControlDesc)
73+
74+
newLimitDesc := model.LoadControlLimitDescriptionDataType{
75+
LimitId: eebusutil.Ptr(model.LoadControlLimitIdType(limitId)),
76+
LimitType: eebusutil.Ptr(model.LoadControlLimitTypeTypeSignDependentAbsValueLimit),
77+
LimitCategory: eebusutil.Ptr(model.LoadControlCategoryTypeObligation),
78+
LimitDirection: eebusutil.Ptr(model.EnergyDirectionTypeConsume),
79+
MeasurementId: eebusutil.Ptr(model.MeasurementIdType(0)), // This is a fake Measurement ID, as there is no Electrical Connection server defined, it can't provide any meaningful. But KEO requires this to be set :(
80+
Unit: eebusutil.Ptr(model.UnitOfMeasurementTypeW),
81+
ScopeType: eebusutil.Ptr(model.ScopeTypeTypeActivePowerLimit),
82+
}
83+
desc.LoadControlLimitDescriptionData = append(desc.LoadControlLimitDescriptionData, newLimitDesc)
84+
f.SetData(model.FunctionTypeLoadControlLimitDescriptionListData, desc)
8185

8286
f = localEntity.GetOrAddFeature(model.FeatureTypeTypeDeviceConfiguration, model.RoleTypeServer)
8387
f.AddFunctionType(model.FunctionTypeDeviceConfigurationKeyValueDescriptionListData, true, false)
8488
f.AddFunctionType(model.FunctionTypeDeviceConfigurationKeyValueListData, true, true)
8589

8690
var configId model.DeviceConfigurationKeyIdType = 0
8791
// get the highest keyId
88-
if desc, err := spine.LocalFeatureDataCopyOfType[*model.DeviceConfigurationKeyValueDescriptionListDataType](
89-
f, model.FunctionTypeDeviceConfigurationKeyValueDescriptionListData); err == nil && desc.DeviceConfigurationKeyValueDescriptionData != nil {
90-
for _, desc := range desc.DeviceConfigurationKeyValueDescriptionData {
92+
deviceConfigDesc, err := spine.LocalFeatureDataCopyOfType[*model.DeviceConfigurationKeyValueDescriptionListDataType](
93+
f, model.FunctionTypeDeviceConfigurationKeyValueDescriptionListData)
94+
if err == nil && deviceConfigDesc.DeviceConfigurationKeyValueDescriptionData != nil {
95+
for _, desc := range deviceConfigDesc.DeviceConfigurationKeyValueDescriptionData {
9196
if desc.KeyId != nil && *desc.KeyId >= configId {
9297
configId++
9398
}
9499
}
95100
}
96101

97-
deviceConfigDesc := &model.DeviceConfigurationKeyValueDescriptionListDataType{
98-
DeviceConfigurationKeyValueDescriptionData: []model.DeviceConfigurationKeyValueDescriptionDataType{
99-
{
100-
KeyId: eebusutil.Ptr(model.DeviceConfigurationKeyIdType(configId)),
101-
KeyName: eebusutil.Ptr(model.DeviceConfigurationKeyNameTypeFailsafeConsumptionActivePowerLimit),
102-
ValueType: eebusutil.Ptr(model.DeviceConfigurationKeyValueTypeTypeScaledNumber),
103-
Unit: eebusutil.Ptr(model.UnitOfMeasurementTypeW),
104-
},
105-
{
106-
KeyId: eebusutil.Ptr(model.DeviceConfigurationKeyIdType(configId + 1)),
107-
KeyName: eebusutil.Ptr(model.DeviceConfigurationKeyNameTypeFailsafeDurationMinimum),
108-
ValueType: eebusutil.Ptr(model.DeviceConfigurationKeyValueTypeTypeDuration),
109-
},
102+
if err != nil || deviceConfigDesc == nil || len(deviceConfigDesc.DeviceConfigurationKeyValueDescriptionData) == 0 {
103+
deviceConfigDesc = &model.DeviceConfigurationKeyValueDescriptionListDataType{
104+
DeviceConfigurationKeyValueDescriptionData: []model.DeviceConfigurationKeyValueDescriptionDataType{},
105+
}
106+
}
107+
108+
newConfigs := []model.DeviceConfigurationKeyValueDescriptionDataType{
109+
{
110+
KeyId: eebusutil.Ptr(model.DeviceConfigurationKeyIdType(configId)),
111+
KeyName: eebusutil.Ptr(model.DeviceConfigurationKeyNameTypeFailsafeConsumptionActivePowerLimit),
112+
ValueType: eebusutil.Ptr(model.DeviceConfigurationKeyValueTypeTypeScaledNumber),
113+
Unit: eebusutil.Ptr(model.UnitOfMeasurementTypeW),
114+
},
115+
{
116+
KeyId: eebusutil.Ptr(model.DeviceConfigurationKeyIdType(configId + 1)),
117+
KeyName: eebusutil.Ptr(model.DeviceConfigurationKeyNameTypeFailsafeDurationMinimum),
118+
ValueType: eebusutil.Ptr(model.DeviceConfigurationKeyValueTypeTypeDuration),
110119
},
111120
}
121+
deviceConfigDesc.DeviceConfigurationKeyValueDescriptionData = append(deviceConfigDesc.DeviceConfigurationKeyValueDescriptionData, newConfigs...)
112122
f.SetData(model.FunctionTypeDeviceConfigurationKeyValueDescriptionListData, deviceConfigDesc)
113123

114-
deviceConfig := &model.DeviceConfigurationKeyValueListDataType{
115-
DeviceConfigurationKeyValueData: []model.DeviceConfigurationKeyValueDataType{
116-
{
117-
KeyId: eebusutil.Ptr(model.DeviceConfigurationKeyIdType(configId)),
118-
IsValueChangeable: eebusutil.Ptr(true),
119-
},
120-
{
121-
KeyId: eebusutil.Ptr(model.DeviceConfigurationKeyIdType(configId + 1)),
122-
IsValueChangeable: eebusutil.Ptr(true),
123-
},
124+
configData, err := spine.LocalFeatureDataCopyOfType[*model.DeviceConfigurationKeyValueListDataType](f, model.FunctionTypeDeviceConfigurationKeyValueListData)
125+
if err != nil || configData == nil || len(configData.DeviceConfigurationKeyValueData) == 0 {
126+
configData = &model.DeviceConfigurationKeyValueListDataType{
127+
DeviceConfigurationKeyValueData: []model.DeviceConfigurationKeyValueDataType{},
128+
}
129+
}
130+
131+
newConfigData := []model.DeviceConfigurationKeyValueDataType{
132+
{
133+
KeyId: eebusutil.Ptr(model.DeviceConfigurationKeyIdType(configId)),
134+
IsValueChangeable: eebusutil.Ptr(true),
135+
},
136+
{
137+
KeyId: eebusutil.Ptr(model.DeviceConfigurationKeyIdType(configId + 1)),
138+
IsValueChangeable: eebusutil.Ptr(true),
124139
},
125140
}
126-
f.SetData(model.FunctionTypeDeviceConfigurationKeyValueListData, deviceConfig)
141+
142+
configData.DeviceConfigurationKeyValueData = append(configData.DeviceConfigurationKeyValueData, newConfigData...)
143+
f.SetData(model.FunctionTypeDeviceConfigurationKeyValueListData, configData)
127144

128145
f = localEntity.GetOrAddFeature(model.FeatureTypeTypeDeviceDiagnosis, model.RoleTypeServer)
129146
f.AddFunctionType(model.FunctionTypeDeviceDiagnosisHeartbeatData, true, false)
@@ -133,29 +150,33 @@ func (e *UCLPCServer) AddFeatures() {
133150

134151
var elCharId model.ElectricalConnectionCharacteristicIdType = 0
135152
// get the highest CharacteristicId
136-
if desc, err := spine.LocalFeatureDataCopyOfType[*model.ElectricalConnectionCharacteristicListDataType](
137-
f, model.FunctionTypeElectricalConnectionCharacteristicListData); err == nil && desc.ElectricalConnectionCharacteristicData != nil {
138-
for _, desc := range desc.ElectricalConnectionCharacteristicData {
153+
elCharData, err := spine.LocalFeatureDataCopyOfType[*model.ElectricalConnectionCharacteristicListDataType](
154+
f, model.FunctionTypeElectricalConnectionCharacteristicListData)
155+
if err == nil && elCharData.ElectricalConnectionCharacteristicData != nil {
156+
for _, desc := range elCharData.ElectricalConnectionCharacteristicData {
139157
if desc.CharacteristicId != nil && *desc.CharacteristicId >= elCharId {
140158
elCharId++
141159
}
142160
}
143161
}
144162

163+
if err != nil || configData == nil || len(configData.DeviceConfigurationKeyValueData) == 0 {
164+
elCharData = &model.ElectricalConnectionCharacteristicListDataType{
165+
ElectricalConnectionCharacteristicData: []model.ElectricalConnectionCharacteristicDataType{},
166+
}
167+
}
168+
145169
// ElectricalConnectionId and ParameterId should be identical to the ones used
146170
// in a MPC Server role implementation, which is not done here (yet)
147-
elCharData := &model.ElectricalConnectionCharacteristicListDataType{
148-
ElectricalConnectionCharacteristicData: []model.ElectricalConnectionCharacteristicDataType{
149-
{
150-
ElectricalConnectionId: eebusutil.Ptr(model.ElectricalConnectionIdType(0)),
151-
ParameterId: eebusutil.Ptr(model.ElectricalConnectionParameterIdType(0)),
152-
CharacteristicId: eebusutil.Ptr(elCharId),
153-
CharacteristicContext: eebusutil.Ptr(model.ElectricalConnectionCharacteristicContextTypeEntity),
154-
CharacteristicType: eebusutil.Ptr(model.ElectricalConnectionCharacteristicTypeTypeContractualConsumptionNominalMax),
155-
Unit: eebusutil.Ptr(model.UnitOfMeasurementTypeW),
156-
},
157-
},
171+
newCharData := model.ElectricalConnectionCharacteristicDataType{
172+
ElectricalConnectionId: eebusutil.Ptr(model.ElectricalConnectionIdType(0)),
173+
ParameterId: eebusutil.Ptr(model.ElectricalConnectionParameterIdType(0)),
174+
CharacteristicId: eebusutil.Ptr(elCharId),
175+
CharacteristicContext: eebusutil.Ptr(model.ElectricalConnectionCharacteristicContextTypeEntity),
176+
CharacteristicType: eebusutil.Ptr(model.ElectricalConnectionCharacteristicTypeTypeContractualConsumptionNominalMax),
177+
Unit: eebusutil.Ptr(model.UnitOfMeasurementTypeW),
158178
}
179+
elCharData.ElectricalConnectionCharacteristicData = append(elCharData.ElectricalConnectionCharacteristicData, newCharData)
159180
f.SetData(model.FunctionTypeElectricalConnectionCharacteristicListData, elCharData)
160181
}
161182

0 commit comments

Comments
 (0)