-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Feat: Add CDT Support as CA (Configuration Appliance) Client Actor
This commit introduces CDT support as a CA (Configuration Appliance) client actor. It provides full support for the CDT use case, specifically Scenario 1. This includes the ability to retrieve setpoints, their constraints, and map them to their corresponding operation modes via HvacSetpointRelations. For the use case to fully function, support for the CDSF (Configuration of DHW System Function) use case is necessary. Specifically, we need to request HvacOperationModeDescriptionListDataType, which is used in conjunction with HvacSystemFunctionSetpointRelationListDataType to establish the mapping between operation modes and their setpoints, and to enable the ability to write setpoints. Note: Writing setpoints was tested and confirmed to work with Vaillant's HeatPump by requesting the HvacOperationModeDescriptionListDataType message and performing the mapping without the CDSF use case. Resources used (specifications): - EEBus UC Technical Specification Configuration of DHW Temperature - EEBus SPINE Technical Specification Resource Specification
- Loading branch information
1 parent
2a6167e
commit 26efd39
Showing
15 changed files
with
1,252 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
package client | ||
|
||
import ( | ||
"github.com/enbility/eebus-go/features/internal" | ||
spineapi "github.com/enbility/spine-go/api" | ||
"github.com/enbility/spine-go/model" | ||
) | ||
|
||
type Hvac struct { | ||
*Feature | ||
|
||
*internal.HvacCommon | ||
} | ||
|
||
// Get a new HVAC features helper | ||
// | ||
// - The feature on the local entity has to be of role client | ||
// - The feature on the remote entity has to be of role server | ||
func NewHvac( | ||
localEntity spineapi.EntityLocalInterface, | ||
remoteEntity spineapi.EntityRemoteInterface, | ||
) (*Hvac, error) { | ||
feature, err := NewFeature(model.FeatureTypeTypeHvac, localEntity, remoteEntity) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
hvac := &Hvac{ | ||
Feature: feature, | ||
HvacCommon: internal.NewRemoteHvac(feature.featureRemote), | ||
} | ||
|
||
return hvac, nil | ||
} | ||
|
||
// request FunctionTypeHvacSystemFunctionSetPointRelationListData from a remote device | ||
func (h *Hvac) RequestHvacSystemFunctionSetPointRelations( | ||
selector *model.HvacSystemFunctionSetpointRelationListDataSelectorsType, | ||
elements *model.HvacSystemFunctionSetpointRelationDataElementsType, | ||
) (*model.MsgCounterType, error) { | ||
return h.requestData(model.FunctionTypeHvacSystemFunctionSetPointRelationListData, selector, elements) | ||
} | ||
|
||
// request FunctionTypeHvacOperationModeDescriptionListData from a remote device | ||
func (h *Hvac) RequestHvacOperationModeDescriptions( | ||
selector *model.HvacOperationModeDescriptionListDataSelectorsType, | ||
elements *model.HvacOperationModeDescriptionDataElementsType, | ||
) (*model.MsgCounterType, error) { | ||
return h.requestData(model.FunctionTypeHvacOperationModeDescriptionListData, selector, elements) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
package client | ||
|
||
import ( | ||
"github.com/enbility/eebus-go/api" | ||
"github.com/enbility/eebus-go/features/internal" | ||
spineapi "github.com/enbility/spine-go/api" | ||
"github.com/enbility/spine-go/model" | ||
) | ||
|
||
type Setpoint struct { | ||
*Feature | ||
|
||
*internal.SetPointCommon | ||
} | ||
|
||
// Get a new SetPoint features helper | ||
// | ||
// - The feature on the local entity has to be of role client | ||
// - The feature on the remote entity has to be of role server | ||
func NewSetpoint( | ||
localEntity spineapi.EntityLocalInterface, | ||
remoteEntity spineapi.EntityRemoteInterface, | ||
) (*Setpoint, error) { | ||
feature, err := NewFeature(model.FeatureTypeTypeSetpoint, localEntity, remoteEntity) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
sp := &Setpoint{ | ||
Feature: feature, | ||
SetPointCommon: internal.NewRemoteSetPoint(feature.featureRemote), | ||
} | ||
|
||
return sp, nil | ||
} | ||
|
||
// request FunctionTypeSetpointDescriptionListData from a remote device | ||
func (s *Setpoint) RequestSetPointDescriptions( | ||
selector *model.SetpointDescriptionListDataSelectorsType, | ||
elements *model.SetpointDescriptionDataElementsType, | ||
) (*model.MsgCounterType, error) { | ||
return s.requestData(model.FunctionTypeSetpointDescriptionListData, selector, elements) | ||
} | ||
|
||
// request FunctionTypeSetpointConstraintsListData from a remote device | ||
func (s *Setpoint) RequestSetPointConstraints( | ||
selector *model.SetpointConstraintsListDataSelectorsType, | ||
elements *model.SetpointConstraintsDataElementsType, | ||
) (*model.MsgCounterType, error) { | ||
return s.requestData(model.FunctionTypeSetpointConstraintsListData, selector, elements) | ||
} | ||
|
||
// request FunctionTypeSetpointListData from a remote device | ||
func (s *Setpoint) RequestSetPoints( | ||
selector *model.SetpointListDataSelectorsType, | ||
elements *model.SetpointDataElementsType, | ||
) (*model.MsgCounterType, error) { | ||
return s.requestData(model.FunctionTypeSetpointListData, selector, elements) | ||
} | ||
|
||
// WriteSetPointListData writes the given setpoint data | ||
// | ||
// Parameters: | ||
// - data: the setpoint data to write | ||
// | ||
// Returns: | ||
// - the message counter of the sent message | ||
// - an error if the data could not be written | ||
func (s *Setpoint) WriteSetPointListData( | ||
data []model.SetpointDataType, | ||
) (*model.MsgCounterType, error) { | ||
if len(data) == 0 { | ||
return nil, api.ErrMissingData | ||
} | ||
|
||
cmd := model.CmdType{ | ||
SetpointListData: &model.SetpointListDataType{ | ||
SetpointData: data, | ||
}, | ||
} | ||
|
||
return s.remoteDevice.Sender().Write(s.featureLocal.Address(), s.featureRemote.Address(), cmd) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
package internal | ||
|
||
import ( | ||
"github.com/enbility/eebus-go/api" | ||
spineapi "github.com/enbility/spine-go/api" | ||
"github.com/enbility/spine-go/model" | ||
) | ||
|
||
type HvacCommon struct { | ||
featureLocal spineapi.FeatureLocalInterface | ||
featureRemote spineapi.FeatureRemoteInterface | ||
} | ||
|
||
// NewLocalHvac creates a new HvacCommon helper for local entities | ||
func NewLocalHvac(featureLocal spineapi.FeatureLocalInterface) *HvacCommon { | ||
return &HvacCommon{ | ||
featureLocal: featureLocal, | ||
} | ||
} | ||
|
||
// NewRemoteHvac creates a new HvacCommon helper for remote entities | ||
func NewRemoteHvac(featureRemote spineapi.FeatureRemoteInterface) *HvacCommon { | ||
return &HvacCommon{ | ||
featureRemote: featureRemote, | ||
} | ||
} | ||
|
||
// GetHvacOperationModeDescriptions returns the operation mode descriptions | ||
func (h *HvacCommon) GetHvacOperationModeDescriptions() ([]model.HvacOperationModeDescriptionDataType, error) { | ||
function := model.FunctionTypeHvacOperationModeDescriptionListData | ||
operationModeDescriptions := make([]model.HvacOperationModeDescriptionDataType, 0) | ||
|
||
data, err := featureDataCopyOfType[model.HvacOperationModeDescriptionListDataType](h.featureLocal, h.featureRemote, function) | ||
if err == nil || data != nil { | ||
operationModeDescriptions = append(operationModeDescriptions, data.HvacOperationModeDescriptionData...) | ||
} | ||
|
||
return operationModeDescriptions, nil | ||
} | ||
|
||
// GetHvacSystemFunctionSetpointRelations returns the operation mode relations for a given system function id | ||
func (h *HvacCommon) GetHvacSystemFunctionSetpointRelationsForSystemFunctionId( | ||
id model.HvacSystemFunctionIdType, | ||
) ([]model.HvacSystemFunctionSetpointRelationDataType, error) { | ||
function := model.FunctionTypeHvacSystemFunctionSetPointRelationListData | ||
filter := model.HvacSystemFunctionSetpointRelationDataType{ | ||
SystemFunctionId: &id, | ||
} | ||
|
||
data, err := featureDataCopyOfType[model.HvacSystemFunctionSetpointRelationListDataType](h.featureLocal, h.featureRemote, function) | ||
if err != nil || data == nil || data.HvacSystemFunctionSetpointRelationData == nil { | ||
return nil, api.ErrDataNotAvailable | ||
} | ||
|
||
result := searchFilterInList[model.HvacSystemFunctionSetpointRelationDataType](data.HvacSystemFunctionSetpointRelationData, filter) | ||
if len(result) == 0 { | ||
return nil, api.ErrDataNotAvailable | ||
} | ||
|
||
return result, nil | ||
} | ||
|
||
// GetHvacSystemFunctionDescriptions returns the system function descriptions for a given filter | ||
func (h *HvacCommon) GetHvacSystemFunctionDescriptionsForFilter( | ||
filter model.HvacSystemFunctionDescriptionDataType, | ||
) ([]model.HvacSystemFunctionDescriptionDataType, error) { | ||
function := model.FunctionTypeHvacSystemFunctionDescriptionListData | ||
|
||
data, err := featureDataCopyOfType[model.HvacSystemFunctionDescriptionListDataType](h.featureLocal, h.featureRemote, function) | ||
if err != nil || data == nil || data.HvacSystemFunctionDescriptionData == nil { | ||
return nil, api.ErrDataNotAvailable | ||
} | ||
|
||
result := searchFilterInList[model.HvacSystemFunctionDescriptionDataType](data.HvacSystemFunctionDescriptionData, filter) | ||
|
||
return result, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
package internal | ||
|
||
import ( | ||
"github.com/enbility/eebus-go/api" | ||
"github.com/enbility/ship-go/util" | ||
spineapi "github.com/enbility/spine-go/api" | ||
"github.com/enbility/spine-go/model" | ||
) | ||
|
||
type SetPointCommon struct { | ||
featureLocal spineapi.FeatureLocalInterface | ||
featureRemote spineapi.FeatureRemoteInterface | ||
} | ||
|
||
// NewLocalSetPoint creates a new SetPointCommon helper for local entities | ||
func NewLocalSetPoint(featureLocal spineapi.FeatureLocalInterface) *SetPointCommon { | ||
return &SetPointCommon{ | ||
featureLocal: featureLocal, | ||
} | ||
} | ||
|
||
// NewRemoteSetPoint creates a new SetPointCommon helper for remote entities | ||
func NewRemoteSetPoint(featureRemote spineapi.FeatureRemoteInterface) *SetPointCommon { | ||
return &SetPointCommon{ | ||
featureRemote: featureRemote, | ||
} | ||
} | ||
|
||
// GetSetpointDescriptions returns the setpoint descriptions | ||
func (s *SetPointCommon) GetSetpointDescriptions() ([]model.SetpointDescriptionDataType, error) { | ||
function := model.FunctionTypeSetpointDescriptionListData | ||
|
||
data, err := featureDataCopyOfType[model.SetpointDescriptionListDataType](s.featureLocal, s.featureRemote, function) | ||
if err != nil || data == nil || data.SetpointDescriptionData == nil { | ||
return nil, api.ErrDataNotAvailable | ||
} | ||
|
||
return data.SetpointDescriptionData, nil | ||
} | ||
|
||
// GetSetpointForId returns the setpoint data for a given setpoint ID | ||
func (s *SetPointCommon) GetSetpointForId( | ||
id model.SetpointIdType, | ||
) (*model.SetpointDataType, error) { | ||
filter := model.SetpointDataType{ | ||
SetpointId: &id, | ||
} | ||
|
||
result, err := s.GetSetpointDataForFilter(filter) | ||
if err != nil || len(result) == 0 { | ||
return nil, api.ErrDataNotAvailable | ||
} | ||
|
||
return util.Ptr(result[0]), nil | ||
} | ||
|
||
// GetSetpoints returns the setpoints | ||
func (s *SetPointCommon) GetSetpoints() []model.SetpointDataType { | ||
function := model.FunctionTypeSetpointListData | ||
|
||
data, err := featureDataCopyOfType[model.SetpointListDataType](s.featureLocal, s.featureRemote, function) | ||
if err != nil || data == nil || data.SetpointData == nil { | ||
return []model.SetpointDataType{} | ||
} | ||
|
||
return data.SetpointData | ||
} | ||
|
||
// GetSetpointDataForFilter returns the setpoint data for a given filter | ||
func (s *SetPointCommon) GetSetpointDataForFilter( | ||
filter model.SetpointDataType, | ||
) ([]model.SetpointDataType, error) { | ||
function := model.FunctionTypeSetpointListData | ||
|
||
data, err := featureDataCopyOfType[model.SetpointListDataType](s.featureLocal, s.featureRemote, function) | ||
if err != nil || data == nil || data.SetpointData == nil { | ||
return nil, api.ErrDataNotAvailable | ||
} | ||
|
||
result := searchFilterInList[model.SetpointDataType](data.SetpointData, filter) | ||
|
||
return result, nil | ||
} | ||
|
||
// GetSetpointConstraints returns the setpoints constraints. | ||
func (s *SetPointCommon) GetSetpointConstraints() []model.SetpointConstraintsDataType { | ||
function := model.FunctionTypeSetpointConstraintsListData | ||
|
||
data, err := featureDataCopyOfType[model.SetpointConstraintsListDataType](s.featureLocal, s.featureRemote, function) | ||
if err != nil || data == nil || data.SetpointConstraintsData == nil { | ||
return []model.SetpointConstraintsDataType{} | ||
} | ||
|
||
return data.SetpointConstraintsData | ||
} | ||
|
||
// GetSetpointConstraintsForId returns the setpoint constraints for a given setpoint ID | ||
func (s *SetPointCommon) GetSetpointConstraintsForId( | ||
id model.SetpointIdType, | ||
) (*model.SetpointConstraintsDataType, error) { | ||
filter := model.SetpointConstraintsDataType{ | ||
SetpointId: &id, | ||
} | ||
|
||
result, err := s.GetSetpointConstraintsForFilter(filter) | ||
if err != nil || len(result) == 0 { | ||
return nil, api.ErrDataNotAvailable | ||
} | ||
|
||
return util.Ptr(result[0]), nil | ||
} | ||
|
||
// GetSetpointConstraintsForFilter returns the setpoint constraints for a given filter | ||
func (s *SetPointCommon) GetSetpointConstraintsForFilter( | ||
filter model.SetpointConstraintsDataType, | ||
) ([]model.SetpointConstraintsDataType, error) { | ||
function := model.FunctionTypeSetpointConstraintsListData | ||
|
||
data, err := featureDataCopyOfType[model.SetpointConstraintsListDataType](s.featureLocal, s.featureRemote, function) | ||
if err != nil || data == nil || data.SetpointConstraintsData == nil { | ||
return nil, api.ErrDataNotAvailable | ||
} | ||
|
||
result := searchFilterInList[model.SetpointConstraintsDataType](data.SetpointConstraintsData, filter) | ||
|
||
return result, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.