Skip to content

Commit

Permalink
Various maintenance updates (#136)
Browse files Browse the repository at this point in the history
- Fix a G115 linter warning
- Add documentation/comments to all usecase NewABC implementations
- Make `DataUpdateHeartbeat` event names mote consistent and make the
EG/CS LPx events differentiable
- Improve comments
- Update SHIP and SPINE to latest dev
  • Loading branch information
DerAndereAndi authored Nov 18, 2024
2 parents ec402c2 + 90a5c1f commit cec3695
Show file tree
Hide file tree
Showing 30 changed files with 226 additions and 31 deletions.
46 changes: 46 additions & 0 deletions api/usecases_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package api

import (
"encoding/json"
"testing"

"github.com/enbility/spine-go/mocks"
"github.com/enbility/spine-go/model"
"github.com/enbility/spine-go/spine"

"github.com/stretchr/testify/assert"
)

func Test_RemoteEntityScenarios_Marshal(t *testing.T) {
item := RemoteEntityScenarios{
Entity: nil,
Scenarios: nil,
}
value, err := json.Marshal(item)
assert.Nil(t, err)
assert.NotNil(t, value)
assert.Equal(t, `{"Entity":null,"Scenarios":null}`, string(value))

item = RemoteEntityScenarios{
Entity: nil,
Scenarios: []uint{1, 2, 3},
}
value, err = json.Marshal(item)
assert.Nil(t, err)
assert.NotNil(t, value)
assert.Equal(t, `{"Entity":null,"Scenarios":[1,2,3]}`, string(value))

device := mocks.NewDeviceRemoteInterface(t)
deviceAddress := model.AddressDeviceType("test")
device.EXPECT().Address().Return(&deviceAddress).Times(1)
entity := spine.NewEntityRemote(device, model.EntityTypeTypeCEM, []model.AddressEntityType{1, 1})

item = RemoteEntityScenarios{
Entity: entity,
Scenarios: []uint{1, 2, 3},
}
value, err = json.Marshal(item)
assert.Nil(t, err)
assert.NotNil(t, value)
assert.Equal(t, `{"Entity":{"Device":"test","Entity":[1,1]},"Scenarios":[1,2,3]}`, string(value))
}
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ module github.com/enbility/eebus-go
go 1.22.0

require (
github.com/enbility/ship-go v0.0.0-20241006160314-3a4325a1a6d6
github.com/enbility/spine-go v0.0.0-20241007182100-30ee8bc405a7
github.com/enbility/ship-go v0.0.0-20241118145930-d68708c5f1c0
github.com/enbility/spine-go v0.0.0-20241118145803-0589320ceced
github.com/stretchr/testify v1.9.0
golang.org/x/exp/jsonrpc2 v0.0.0-20240909161429-701f63a606c0
)
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/enbility/go-avahi v0.0.0-20240909195612-d5de6b280d7a h1:foChWb8lhzqa6lWDRs6COYMdp649YlUirFP8GqoT0JQ=
github.com/enbility/go-avahi v0.0.0-20240909195612-d5de6b280d7a/go.mod h1:H64mhYcAQUGUUnVqMdZQf93kPecH4M79xwH95Lddt3U=
github.com/enbility/ship-go v0.0.0-20241006160314-3a4325a1a6d6 h1:bjrcJ4wxEsG5rXHlXnedRzqAV9JYglj82S14Nf1oLvs=
github.com/enbility/ship-go v0.0.0-20241006160314-3a4325a1a6d6/go.mod h1:JJp8EQcJhUhTpZ2LSEU4rpdaM3E2n08tswWFWtmm/wU=
github.com/enbility/spine-go v0.0.0-20241007182100-30ee8bc405a7 h1:n6tv+YUMncSR9qxUs6k7d/YsKD9ujHHp5pUspIvM6sc=
github.com/enbility/spine-go v0.0.0-20241007182100-30ee8bc405a7/go.mod h1:ZoI9TaJO/So/677uknrli8sc6iryD7wC5iWhVIre+MI=
github.com/enbility/ship-go v0.0.0-20241118145930-d68708c5f1c0 h1:Z8j/N4DgUL8T8mINkHdq0bUbKcWtwDpno0bsKOGahPo=
github.com/enbility/ship-go v0.0.0-20241118145930-d68708c5f1c0/go.mod h1:JJp8EQcJhUhTpZ2LSEU4rpdaM3E2n08tswWFWtmm/wU=
github.com/enbility/spine-go v0.0.0-20241118145803-0589320ceced h1:Z2WrJ+ku7lPZqJ+uzqvIqdMpXqvAZRB3J3xW592pDXI=
github.com/enbility/spine-go v0.0.0-20241118145803-0589320ceced/go.mod h1:ZoI9TaJO/So/677uknrli8sc6iryD7wC5iWhVIre+MI=
github.com/enbility/zeroconf/v2 v2.0.0-20240920094356-be1cae74fda6 h1:XOYvxKtT1oxT37w/5oEiRLuPbm9FuJPt3fiYhX0h8Po=
github.com/enbility/zeroconf/v2 v2.0.0-20240920094356-be1cae74fda6/go.mod h1:BszP9qFV14mPXgyIREbgIdQtWxbAj3OKqvK02HihMoM=
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
Expand Down
3 changes: 2 additions & 1 deletion usecases/cem/cevc/public_scen2.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,9 @@ func (e *CEVC) WritePowerLimits(entity spineapi.EntityRemoteInterface, data []uc
for index, slot := range data {
relativeStart := totalDuration

slotid := uint(index) //nolint:gosec // disable G115
timeSeriesSlot := model.TimeSeriesSlotType{
TimeSeriesSlotId: util.Ptr(model.TimeSeriesSlotIdType(index)),
TimeSeriesSlotId: util.Ptr(model.TimeSeriesSlotIdType(slotid)),
TimePeriod: &model.TimePeriodType{
StartTime: model.NewAbsoluteOrRelativeTimeTypeFromDuration(relativeStart),
},
Expand Down
6 changes: 6 additions & 0 deletions usecases/cem/cevc/usecase.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ type CEVC struct {

var _ ucapi.CemCEVCInterface = (*CEVC)(nil)

// Add support for the Coordinated EV Charging (CEVC) use case
// as a CEM actor
//
// Parameters:
// - localEntity: The local entity which should support the use case
// - eventCB: The callback to be called when an event is triggered (optional, can be nil)
func NewCEVC(localEntity spineapi.EntityLocalInterface, eventCB api.EntityEventCallback) *CEVC {
validActorTypes := []model.UseCaseActorType{
model.UseCaseActorTypeEV,
Expand Down
7 changes: 7 additions & 0 deletions usecases/cem/evcc/usecase.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@ type EVCC struct {

var _ ucapi.CemEVCCInterface = (*EVCC)(nil)

// Add support for the EV Commissioning and Configuration (EVCEM) use case
// as a CEM actor
//
// Parameters:
// - service: The service implementation
// - localEntity: The local entity which should support the use case
// - eventCB: The callback to be called when an event is triggered (optional, can be nil)
func NewEVCC(
service api.ServiceInterface,
localEntity spineapi.EntityLocalInterface,
Expand Down
13 changes: 12 additions & 1 deletion usecases/cem/evcem/usecase.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,18 @@ type EVCEM struct {

var _ ucapi.CemEVCEMInterface = (*EVCEM)(nil)

func NewEVCEM(service api.ServiceInterface, localEntity spineapi.EntityLocalInterface, eventCB api.EntityEventCallback) *EVCEM {
// Add support for the Measurement of Electricity during EV Charging (EVCEM) use case
// as a CEM actor
//
// Parameters:
// - service: The service implementation
// - localEntity: The local entity which should support the use case
// - eventCB: The callback to be called when an event is triggered (optional, can be nil)
func NewEVCEM(
service api.ServiceInterface,
localEntity spineapi.EntityLocalInterface,
eventCB api.EntityEventCallback,
) *EVCEM {
validActorTypes := []model.UseCaseActorType{
model.UseCaseActorTypeEV,
}
Expand Down
6 changes: 6 additions & 0 deletions usecases/cem/evsecc/usecase.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ type EVSECC struct {

var _ ucapi.CemEVSECCInterface = (*EVSECC)(nil)

// Add support for the EVSE Commmissioning and Configuration (EVSECC) use case
// as a CEM actor
//
// Parameters:
// - localEntity: The local entity which should support the use case
// - eventCB: The callback to be called when an event is triggered (optional, can be nil)
func NewEVSECC(localEntity spineapi.EntityLocalInterface, eventCB api.EntityEventCallback) *EVSECC {
validActorTypes := []model.UseCaseActorType{
model.UseCaseActorTypeEVSE,
Expand Down
11 changes: 10 additions & 1 deletion usecases/cem/evsoc/usecase.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ type EVSOC struct {

var _ ucapi.CemEVSOCInterface = (*EVSOC)(nil)

// Add support for the EV State of Charge (EVSOC) use case
// as a CEM actor
//
// Parameters:
// - localEntity: The local entity which should support the use case
// - eventCB: The callback to be called when an event is triggered (optional, can be nil)
func NewEVSOC(localEntity spineapi.EntityLocalInterface, eventCB api.EntityEventCallback) *EVSOC {
validActorTypes := []model.UseCaseActorType{
model.UseCaseActorTypeEV,
Expand Down Expand Up @@ -64,5 +70,8 @@ func (e *EVSOC) AddFeatures() {
}

func (e *EVSOC) UpdateUseCaseAvailability(available bool) {
e.LocalEntity.SetUseCaseAvailability(model.UseCaseActorTypeCEM, e.UseCaseName, available)
e.LocalEntity.SetUseCaseAvailability(model.UseCaseFilterType{
Actor: model.UseCaseActorTypeCEM,
UseCaseName: e.UseCaseName,
}, available)
}
7 changes: 7 additions & 0 deletions usecases/cem/opev/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@ func (e *OPEV) HandleEvent(payload spineapi.EventPayload) {
}
}

// TODOS:
// - wie gehen wir damit um, wenn subscriptions nicht erfolgreich sind
// - wie gehen wir damit um, wenn bindings nicht erfolgreich sind, z.b. write implementierungen müssen prüfen ob ein binding exisiteirt
// könnte prüfen ob ein binding exisitert, wenn nicht gleich einen fehler zurückliefern
// - wie gehen wir damit um, wenn descriptions nicht abgefragt werden können
// - wie, wenn die einen Fehler zurückgeben

// an EV was connected
func (e *OPEV) evConnected(entity spineapi.EntityRemoteInterface) {
// initialise features, e.g. subscriptions, descriptions
Expand Down
6 changes: 5 additions & 1 deletion usecases/cem/opev/public.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,12 @@ func (e *OPEV) CurrentLimits(entity spineapi.EntityRemoteInterface) ([]float64,
// - limits: per phase data
//
// possible errors:
// - ErrDataNotAvailable if no such limit is (yet) available
// - ErrDataNotAvailable if none such limit is (yet) available
// - and others
//
// Notes:
// - If a limit of phase is not active, the value returned is set to the maximum permitted value (if available), otherwise the phase value is not returned
// - If at least one phase value is available, no error is returned
func (e *OPEV) LoadControlLimits(entity spineapi.EntityRemoteInterface) (
limits []ucapi.LoadLimitsPhase, resultErr error) {
if !e.IsCompatibleEntityType(entity) {
Expand Down
2 changes: 1 addition & 1 deletion usecases/cem/opev/public_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
)

func (s *CemOPEVSuite) Test_Public() {
// The actual tests of the functionality is located in the util package
// The actual tests of the functionality is located in the internal package

_, _, _, err := s.sut.CurrentLimits(s.mockRemoteEntity)
assert.NotNil(s.T(), err)
Expand Down
6 changes: 6 additions & 0 deletions usecases/cem/opev/usecase.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ type OPEV struct {

var _ ucapi.CemOPEVInterface = (*OPEV)(nil)

// Add support for the Overload Protection by EV Charging Current Curtailment (OPEV) use case
// as a CEM actor
//
// Parameters:
// - localEntity: The local entity which should support the use case
// - eventCB: The callback to be called when an event is triggered (optional, can be nil)
func NewOPEV(localEntity spineapi.EntityLocalInterface, eventCB api.EntityEventCallback) *OPEV {
validActorTypes := []model.UseCaseActorType{
model.UseCaseActorTypeEV,
Expand Down
2 changes: 1 addition & 1 deletion usecases/cem/oscev/public_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
)

func (s *CemOSCEVSuite) Test_Public() {
// The actual tests of the functionality is located in the util package
// The actual tests of the functionality is located in the internal package

_, _, _, err := s.sut.CurrentLimits(s.mockRemoteEntity)
assert.NotNil(s.T(), err)
Expand Down
6 changes: 6 additions & 0 deletions usecases/cem/oscev/usecase.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ type OSCEV struct {

var _ ucapi.CemOSCEVInterface = (*OSCEV)(nil)

// Add support for the Optimization of Self-Consumption during EV Charging (OSCEV) use case
// as a CEM actor
//
// Parameters:
// - localEntity: The local entity which should support the use case
// - eventCB: The callback to be called when an event is triggered (optional, can be nil)
func NewOSCEV(localEntity spineapi.EntityLocalInterface, eventCB api.EntityEventCallback) *OSCEV {
validActorTypes := []model.UseCaseActorType{
model.UseCaseActorTypeEV,
Expand Down
6 changes: 6 additions & 0 deletions usecases/cem/vabd/usecase.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ type VABD struct {

var _ ucapi.CemVABDInterface = (*VABD)(nil)

// Add support for the Visualization of Aggregated Battery Data (VABD) use case
// as a CEM actor
//
// Parameters:
// - localEntity: The local entity which should support the use case
// - eventCB: The callback to be called when an event is triggered (optional, can be nil)
func NewVABD(localEntity spineapi.EntityLocalInterface, eventCB api.EntityEventCallback) *VABD {
validActorTypes := []model.UseCaseActorType{
model.UseCaseActorTypeBatterySystem,
Expand Down
6 changes: 6 additions & 0 deletions usecases/cem/vapd/usecase.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ type VAPD struct {

var _ ucapi.CemVAPDInterface = (*VAPD)(nil)

// Add support for the Visualization of Aggregated Photovoltaic Data (VAPD) use case
// as a CEM actor
//
// Parameters:
// - localEntity: The local entity which should support the use case
// - eventCB: The callback to be called when an event is triggered (optional, can be nil)
func NewVAPD(localEntity spineapi.EntityLocalInterface, eventCB api.EntityEventCallback) *VAPD {
validActorTypes := []model.UseCaseActorType{
model.UseCaseActorTypePVSystem,
Expand Down
6 changes: 6 additions & 0 deletions usecases/cs/lpc/usecase.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ type LPC struct {

var _ ucapi.CsLPCInterface = (*LPC)(nil)

// Add support for the Limitation of Power Consumption (LPC) use case
// as a Controllable System actor
//
// Parameters:
// - localEntity: The local entity which should support the use case
// - eventCB: The callback to be called when an event is triggered (optional, can be nil)
func NewLPC(localEntity spineapi.EntityLocalInterface, eventCB api.EntityEventCallback) *LPC {
validActorTypes := []model.UseCaseActorType{model.UseCaseActorTypeEnergyGuard}
validEntityTypes := []model.EntityTypeType{
Expand Down
2 changes: 1 addition & 1 deletion usecases/cs/lpp/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,5 @@ const (
// E.g. going into or out of the Failsafe state
//
// Use Case LPP, Scenario 3
DataUpdateHeartbeat api.EventType = "uclppserver-DataUpdateHeartbeat"
DataUpdateHeartbeat api.EventType = "cs-lpp-DataUpdateHeartbeat"
)
6 changes: 6 additions & 0 deletions usecases/cs/lpp/usecase.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ type LPP struct {

var _ ucapi.CsLPPInterface = (*LPP)(nil)

// Add support for the Limitation of Power Production (LPC) use case
// as a Controllable System actor
//
// Parameters:
// - localEntity: The local entity which should support the use case
// - eventCB: The callback to be called when an event is triggered (optional, can be nil)
func NewLPP(localEntity spineapi.EntityLocalInterface, eventCB api.EntityEventCallback) *LPP {
validActorTypes := []model.UseCaseActorType{model.UseCaseActorTypeEnergyGuard}
validEntityTypes := []model.EntityTypeType{
Expand Down
2 changes: 1 addition & 1 deletion usecases/eg/lpc/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,5 @@ const (
// E.g. going into or out of the Failsafe state
//
// Use Case LPC, Scenario 3
DataUpdateHeartbeat api.EventType = "cs-lpc-DataUpdateHeartbeat"
DataUpdateHeartbeat api.EventType = "eg-lpc-DataUpdateHeartbeat"
)
6 changes: 6 additions & 0 deletions usecases/eg/lpc/usecase.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ type LPC struct {

var _ ucapi.EgLPCInterface = (*LPC)(nil)

// Add support for the Limitation of Power Consumption (LPC) use case
// as a Energy Guard actor
//
// Parameters:
// - localEntity: The local entity which should support the use case
// - eventCB: The callback to be called when an event is triggered (optional, can be nil)
func NewLPC(localEntity spineapi.EntityLocalInterface, eventCB api.EntityEventCallback) *LPC {
validActorTypes := []model.UseCaseActorType{model.UseCaseActorTypeControllableSystem}
validEntityTypes := []model.EntityTypeType{
Expand Down
2 changes: 1 addition & 1 deletion usecases/eg/lpp/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,5 @@ const (
// E.g. going into or out of the Failsafe state
//
// Use Case LPP, Scenario 3
DataUpdateHeartbeat api.EventType = "cs-lpp-DataUpdateHeartbeat"
DataUpdateHeartbeat api.EventType = "eg-lpp-DataUpdateHeartbeat"
)
11 changes: 10 additions & 1 deletion usecases/eg/lpp/usecase.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ type LPP struct {

var _ ucapi.EgLPPInterface = (*LPP)(nil)

// Add support for the Limitation of Power Production (LPC) use case
// as a Energy Guard actor
//
// Parameters:
// - localEntity: The local entity which should support the use case
// - eventCB: The callback to be called when an event is triggered (optional, can be nil)
func NewLPP(localEntity spineapi.EntityLocalInterface, eventCB api.EntityEventCallback) *LPP {
validActorTypes := []model.UseCaseActorType{model.UseCaseActorTypeControllableSystem}
validEntityTypes := []model.EntityTypeType{
Expand Down Expand Up @@ -86,5 +92,8 @@ func (e *LPP) AddFeatures() {
}

func (e *LPP) UpdateUseCaseAvailability(available bool) {
e.LocalEntity.SetUseCaseAvailability(model.UseCaseActorTypeEnergyGuard, e.UseCaseName, available)
e.LocalEntity.SetUseCaseAvailability(model.UseCaseFilterType{
Actor: model.UseCaseActorTypeEnergyGuard,
UseCaseName: e.UseCaseName,
}, available)
}
10 changes: 9 additions & 1 deletion usecases/internal/loadcontrol.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ import (
// possible errors:
// - ErrDataNotAvailable if no such measurement is (yet) available
// - and others
//
// Notes:
// - If a limit of phase is not active, the value returned is set to the maximum permitted value (if available), otherwise the phase value is not returned
// - If at least one phase value is available, no error is returned
func LoadControlLimits(
localEntity spineapi.EntityLocalInterface,
remoteEntity spineapi.EntityRemoteInterface,
Expand Down Expand Up @@ -86,7 +90,7 @@ func LoadControlLimits(
// which is not the case for all elements for this EVSE setup
// but we have to ignore this case and continue with the next phase

// In addition Elli Conenct/Pro (Gen1) returns no or empty PermittedValueSet data
// In addition Elli Connect/Pro (Gen1) returns no or empty PermittedValueSet data
continue
}

Expand All @@ -105,6 +109,10 @@ func LoadControlLimits(
result = append(result, newLimit)
}

if len(result) == 0 {
return nil, api.ErrDataNotAvailable
}

return result, nil
}

Expand Down
Loading

0 comments on commit cec3695

Please sign in to comment.