Skip to content

Commit

Permalink
Add HvacOperationModeType to usecase types
Browse files Browse the repository at this point in the history
  • Loading branch information
David Sapir committed Nov 14, 2024
1 parent fe2b702 commit 4afe071
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 77 deletions.
13 changes: 6 additions & 7 deletions usecases/api/ca_cdt.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,33 @@ package api
import (
"github.com/enbility/eebus-go/api"
spineapi "github.com/enbility/spine-go/api"
"github.com/enbility/spine-go/model"
)

type CaCDTInterface interface {
api.UseCaseInterface

// Scenario 1

// Return the current setpoints data
// Return the setpoints.
//
// parameters:
// - entity: the entity to get the setpoints data from
//
// return values:
// - setpoints: A map of the setpoints for supported modes
// - setpoints: A list of setpoints
//
// possible errors:
// - ErrDataNotAvailable if no such limit is (yet) available
// - and others
Setpoints(entity spineapi.EntityRemoteInterface) ([]Setpoint, error)

// Return the constraints for the setpoints
// Return the constraints for the setpoints.
//
// parameters:
// - entity: the entity to get the setpoints constraints from
//
// return values:
// - setpointConstraints: A map of the constraints for supported modes
// - setpointConstraints: A list of setpoint constraints
//
// possible errors:
// - ErrDataNotAvailable if no such limit is (yet) available
Expand All @@ -42,6 +41,6 @@ type CaCDTInterface interface {
// parameters:
// - entity: the entity to write the setpoint to
// - mode: the mode to write the setpoint for
// - degC: the temperature setpoint value to write
WriteSetpoint(entity spineapi.EntityRemoteInterface, mode model.HvacOperationModeTypeType, degC float64) error
// - temperature: the temperature setpoint value to write
WriteSetpoint(entity spineapi.EntityRemoteInterface, mode HvacOperationModeType, temperature float64) error
}
9 changes: 9 additions & 0 deletions usecases/api/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,15 @@ const (
EVChargeStateTypeFinished EVChargeStateType = "finished"
)

type HvacOperationModeType string

const (
HvacOperationModeTypeAuto HvacOperationModeType = "auto"
HvacOperationModeTypeOn HvacOperationModeType = "on"
HvacOperationModeTypeOff HvacOperationModeType = "off"
HvacOperationModeTypeEco HvacOperationModeType = "eco"
)

// Defines a phase specific limit data set
type LoadLimitsPhase struct {
Phase model.ElectricalConnectionPhaseNameType // the phase
Expand Down
55 changes: 55 additions & 0 deletions usecases/ca/cdt/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,61 @@ func (e *CDT) HandleEvent(payload spineapi.EventPayload) {

case *model.SetpointListDataType:
e.EventCB(payload.Ski, payload.Device, payload.Entity, DataUpdateSetpoints)

case *model.HvacSystemFunctionSetpointRelationListDataType,
*model.HvacOperationModeDescriptionListDataType:
e.mapSetpointsToOperationModes(payload)
}
}

// mapSetpointsToOperationModes maps setpoints to operation modes.
func (e *CDT) mapSetpointsToOperationModes(payload spineapi.EventPayload) {
hvac, err := client.NewHvac(e.LocalEntity, payload.Entity)
if err != nil {
logging.Log().Debug(err)
return
}

// Get the DHW system function.
filter := model.HvacSystemFunctionDescriptionDataType{
SystemFunctionType: util.Ptr(model.HvacSystemFunctionTypeTypeDhw),
}
functions, _ := hvac.GetHvacSystemFunctionDescriptionsForFilter(filter)
if len(functions) != 1 {
logging.Log().Error("Shuold be exactly one DHW system function")
return
}

dhwFunctionId := *functions[0].SystemFunctionId

relations, _ := hvac.GetHvacSystemFunctionSetpointRelationsForSystemFunctionId(dhwFunctionId)
descriptions, _ := hvac.GetHvacOperationModeDescriptions()
if len(relations) == 0 || len(descriptions) == 0 {
return
}

modeForModeId := make(map[model.HvacOperationModeIdType]model.HvacOperationModeTypeType)
for _, description := range descriptions {
modeForModeId[*description.OperationModeId] = *description.OperationModeType
}

// Map the setpoints to their respective operation modes.
for _, relation := range relations {
if mode, found := modeForModeId[*relation.OperationModeId]; found {
if len(relation.SetpointId) == 0 {
// Only the 'Off' operation mode can have no setpoint associated with it.
if mode != model.HvacOperationModeTypeTypeOff {
logging.Log().Errorf("Operation mode '%s' has no setpoints", mode)
}
} else if len(relation.SetpointId) == 1 {
// Store the unique setpoint for the operation mode.
e.setpointIdForMode[mode] = relation.SetpointId[0]
} else if mode != model.HvacOperationModeTypeTypeAuto {
// Only the 'Auto' operation mode can have multiple setpoints (1 to 4).
// Since 'Auto' mode is not user-controllable, we do not store the setpoints.
logging.Log().Errorf("Operation mode '%s' has multiple setpoints", mode)
}
}
}
}

Expand Down
67 changes: 4 additions & 63 deletions usecases/ca/cdt/public.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"github.com/enbility/eebus-go/features/client"
usecasesapi "github.com/enbility/eebus-go/usecases/api"
"github.com/enbility/ship-go/logging"
"github.com/enbility/ship-go/util"
spineapi "github.com/enbility/spine-go/api"
"github.com/enbility/spine-go/model"
)
Expand Down Expand Up @@ -128,64 +127,6 @@ func (e *CDT) SetpointConstraints(entity spineapi.EntityRemoteInterface) ([]usec
return setpointConstraints, nil
}

// mapSetpointsToOperationModes maps setpoints to their respective operation modes.
func (e *CDT) mapSetpointsToModes(entity spineapi.EntityRemoteInterface) error {
hvac, err := client.NewHvac(e.LocalEntity, entity)
if err != nil {
return err
}

// Get the DHW system functionId for the DHW system function.
filter := model.HvacSystemFunctionDescriptionDataType{
SystemFunctionType: util.Ptr(model.HvacSystemFunctionTypeTypeDhw),
}
functions, _ := hvac.GetHvacSystemFunctionDescriptionsForFilter(filter)
if len(functions) == 0 {
return api.ErrDataNotAvailable
}

functionId := *functions[0].SystemFunctionId

// Get the relations between operation modes and setpoints for the DHW system function.
relations, _ := hvac.GetHvacSystemFunctionSetpointRelationsForSystemFunctionId(functionId)
if len(relations) == 0 {
return api.ErrDataNotAvailable
}

// Get the operation mode descriptions for the operation modes in the relations.
descriptions, _ := hvac.GetHvacOperationModeDescriptions()
if len(descriptions) == 0 {
return api.ErrDataNotAvailable
}

// Create a mapping to get the operation mode descriptions by operation mode ID.
modeDescriptions := make(map[model.HvacOperationModeIdType]model.HvacOperationModeTypeType)
for _, description := range descriptions {
modeDescriptions[*description.OperationModeId] = *description.OperationModeType
}

// Map the setpoints to their respective operation modes.
for _, relation := range relations {
if mode, found := modeDescriptions[*relation.OperationModeId]; found {
if len(relation.SetpointId) == 0 {
// Only the 'Off' operation mode can have no setpoint associated with it.
if mode != model.HvacOperationModeTypeTypeOff {
logging.Log().Errorf("Operation mode '%s' has no setpoints", mode)
}
} else if len(relation.SetpointId) == 1 {
// Unique 1:1 mapping of operation mode to setpoint.
e.modes[mode] = relation.SetpointId[0]
} else {
if mode != model.HvacOperationModeTypeTypeAuto {
logging.Log().Errorf("Operation mode '%s' has multiple setpoints", mode)
}
}
}
}

return nil
}

// WriteSetpoint sets the temperature setpoint for a specific operation mode.
//
// Possible errors:
Expand All @@ -194,21 +135,21 @@ func (e *CDT) mapSetpointsToModes(entity spineapi.EntityRemoteInterface) error {
// - Other errors: Any other errors encountered during the process.
func (e *CDT) WriteSetpoint(
entity spineapi.EntityRemoteInterface,
mode model.HvacOperationModeTypeType,
mode usecasesapi.HvacOperationModeType,
temperature float64,
) error {
if mode == model.HvacOperationModeTypeTypeAuto {
if model.HvacOperationModeTypeType(mode) == model.HvacOperationModeTypeTypeAuto {
// 'Auto' mode is controlled by a timetable, meaning the current setpoint
// for the HVAC system function changes according to the timetable.
// Only the 'Off', 'On', and 'Eco' modes can be directly controlled by a setpoint.
return nil
}

if len(e.modes) == 0 && e.mapSetpointsToModes(entity) != nil {
if len(e.setpointIdForMode) == 0 {
return api.ErrDataNotAvailable
}

setpointId, found := e.modes[mode]
setpointId, found := e.setpointIdForMode[model.HvacOperationModeTypeType(mode)]
if !found {
return api.ErrDataNotAvailable
}
Expand Down
9 changes: 5 additions & 4 deletions usecases/ca/cdt/public_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cdt

import (
"github.com/enbility/eebus-go/usecases/api"
"github.com/enbility/ship-go/util"
"github.com/enbility/spine-go/model"
"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -137,7 +138,7 @@ func (s *CaCDTSuite) Test_SetpointConstraints() {
// Test_WriteSetpoint verifies the functionality of writing a setpoint to a remote entity.
func (s *CaCDTSuite) Test_WriteSetpoint() {
// Test case: No setpoints available for mock remote entity
err := s.sut.WriteSetpoint(s.mockRemoteEntity, model.HvacOperationModeTypeTypeOn, 35.0)
err := s.sut.WriteSetpoint(s.mockRemoteEntity, api.HvacOperationModeTypeOn, 35.0)
assert.NotNil(s.T(), err)

// Create a setpoint
Expand Down Expand Up @@ -169,15 +170,15 @@ func (s *CaCDTSuite) Test_WriteSetpoint() {
assert.Nil(s.T(), fErr)

// Test case: No mapping of operation modes to setpoints available
err = s.sut.WriteSetpoint(s.cdtEntity, model.HvacOperationModeTypeTypeOn, 35.0)
err = s.sut.WriteSetpoint(s.cdtEntity, api.HvacOperationModeTypeOn, 35.0)
assert.NotNil(s.T(), err)

// Create a mapping of operation modes to setpoints
s.sut.modes = map[model.HvacOperationModeTypeType]model.SetpointIdType{
s.sut.setpointIdForMode = map[model.HvacOperationModeTypeType]model.SetpointIdType{
model.HvacOperationModeTypeTypeOn: 1,
}

// Test case: Setpoint and operation mode mapping available - the write should succeed
err = s.sut.WriteSetpoint(s.cdtEntity, model.HvacOperationModeTypeTypeOn, 35.0)
err = s.sut.WriteSetpoint(s.cdtEntity, api.HvacOperationModeTypeOn, 35.0)
assert.Nil(s.T(), err)
}
6 changes: 3 additions & 3 deletions usecases/ca/cdt/usecase.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
type CDT struct {
*usecase.UseCaseBase

modes map[model.HvacOperationModeTypeType]model.SetpointIdType
setpointIdForMode map[model.HvacOperationModeTypeType]model.SetpointIdType
}

var _ ucapi.CaCDTInterface = (*CDT)(nil)
Expand Down Expand Up @@ -53,8 +53,8 @@ func NewCDT(
)

uc := &CDT{
UseCaseBase: usecase,
modes: make(map[model.HvacOperationModeTypeType]model.SetpointIdType),
UseCaseBase: usecase,
setpointIdForMode: make(map[model.HvacOperationModeTypeType]model.SetpointIdType),
}

_ = spine.Events.Subscribe(uc)
Expand Down

0 comments on commit 4afe071

Please sign in to comment.