From 4afe0717d1055d254298ca494c2f33f84cc55e9e Mon Sep 17 00:00:00 2001 From: David Sapir Date: Wed, 6 Nov 2024 13:35:37 +0200 Subject: [PATCH] Add HvacOperationModeType to usecase types --- usecases/api/ca_cdt.go | 13 +++---- usecases/api/types.go | 9 +++++ usecases/ca/cdt/events.go | 55 ++++++++++++++++++++++++++++ usecases/ca/cdt/public.go | 67 ++-------------------------------- usecases/ca/cdt/public_test.go | 9 +++-- usecases/ca/cdt/usecase.go | 6 +-- 6 files changed, 82 insertions(+), 77 deletions(-) diff --git a/usecases/api/ca_cdt.go b/usecases/api/ca_cdt.go index ee53d3a5..30a5143b 100644 --- a/usecases/api/ca_cdt.go +++ b/usecases/api/ca_cdt.go @@ -3,7 +3,6 @@ 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 { @@ -11,26 +10,26 @@ type CaCDTInterface interface { // 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 @@ -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 } diff --git a/usecases/api/types.go b/usecases/api/types.go index c2516e0e..76bf9ce3 100644 --- a/usecases/api/types.go +++ b/usecases/api/types.go @@ -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 diff --git a/usecases/ca/cdt/events.go b/usecases/ca/cdt/events.go index d1e73bdb..6c4c8148 100644 --- a/usecases/ca/cdt/events.go +++ b/usecases/ca/cdt/events.go @@ -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) + } + } } } diff --git a/usecases/ca/cdt/public.go b/usecases/ca/cdt/public.go index bd42b26a..eed37ae5 100644 --- a/usecases/ca/cdt/public.go +++ b/usecases/ca/cdt/public.go @@ -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" ) @@ -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: @@ -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 } diff --git a/usecases/ca/cdt/public_test.go b/usecases/ca/cdt/public_test.go index bfeb3268..17cccd9e 100644 --- a/usecases/ca/cdt/public_test.go +++ b/usecases/ca/cdt/public_test.go @@ -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" @@ -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 @@ -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) } diff --git a/usecases/ca/cdt/usecase.go b/usecases/ca/cdt/usecase.go index 8ff3fb72..7ad93226 100644 --- a/usecases/ca/cdt/usecase.go +++ b/usecases/ca/cdt/usecase.go @@ -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) @@ -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)