Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
127 changes: 127 additions & 0 deletions features/client/hvac.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
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 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 FunctionTypeHvacSystemFunctionDescriptionListData from a remote device
func (h *Hvac) RequestHvacSystemFunctionDescriptions(
selector *model.HvacSystemFunctionDescriptionListDataSelectorsType,
elements *model.HvacSystemFunctionDescriptionDataElementsType,
) (*model.MsgCounterType, error) {
return h.requestData(model.FunctionTypeHvacSystemFunctionDescriptionListData, selector, elements)
}

// request FunctionTypeHvacSystemFunctionListData from a remote device
func (h *Hvac) RequestHvacSystemFunctions(
selector *model.HvacSystemFunctionListDataSelectorsType,
elements *model.HvacSystemFunctionDataElementsType,
) (*model.MsgCounterType, error) {
return h.requestData(model.FunctionTypeHvacSystemFunctionListData, 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)
}

// request FunctionTypeHvacSystemFunctionOperationModeRelationListData from a remote device
func (h *Hvac) RequestHvacSystemFunctionOperationModeRelations(
selector *model.HvacSystemFunctionOperationModeRelationListDataSelectorsType,
elements *model.HvacSystemFunctionOperationModeRelationDataElementsType,
) (*model.MsgCounterType, error) {
return h.requestData(model.FunctionTypeHvacSystemFunctionOperationModeRelationListData, selector, elements)
}

// 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 FunctionTypeHvacOverrunDescriptionListData from a remote device
func (h *Hvac) RequestHvacOverrunDescriptions(
selector *model.HvacOverrunDescriptionListDataSelectorsType,
elements *model.HvacOverrunDescriptionDataElementsType,
) (*model.MsgCounterType, error) {
return h.requestData(model.FunctionTypeHvacOverrunDescriptionListData, selector, elements)
}

// request FunctionTypeHvacOverrunListData from a remote device
func (h *Hvac) RequestHvacOverruns(
selector *model.HvacOverrunListDataSelectorsType,
elements *model.HvacOverrunDataElementsType,
) (*model.MsgCounterType, error) {
return h.requestData(model.FunctionTypeHvacOverrunListData, selector, elements)
}

// write the given HVAC overrun data to the remote device,
// e.g. to start or stop an overrun
func (h *Hvac) WriteHvacOverrunListData(
data []model.HvacOverrunDataType,
) (*model.MsgCounterType, error) {
if len(data) == 0 {
return nil, api.ErrMissingData
}

cmd := model.CmdType{
HvacOverrunListData: &model.HvacOverrunListDataType{
HvacOverrunData: data,
},
}

return h.remoteDevice.Sender().Write(h.featureLocal.Address(), h.featureRemote.Address(), cmd)
}

// write the given HVAC system function data to the remote device,
// e.g. to change the current operation mode of a system function
func (h *Hvac) WriteHvacSystemFunctionListData(
data []model.HvacSystemFunctionDataType,
) (*model.MsgCounterType, error) {
if len(data) == 0 {
return nil, api.ErrMissingData
}

cmd := model.CmdType{
HvacSystemFunctionListData: &model.HvacSystemFunctionListDataType{
HvacSystemFunctionData: data,
},
}

return h.remoteDevice.Sender().Write(h.featureLocal.Address(), h.featureRemote.Address(), cmd)
}
141 changes: 141 additions & 0 deletions features/client/hvac_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
package client

import (
"testing"

shipapi "github.com/enbility/ship-go/api"
spineapi "github.com/enbility/spine-go/api"
"github.com/enbility/spine-go/model"
"github.com/enbility/spine-go/util"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/suite"
)

func TestHvacSuite(t *testing.T) {
suite.Run(t, new(HvacSuite))
}

type HvacSuite struct {
suite.Suite

localEntity spineapi.EntityLocalInterface
remoteEntity spineapi.EntityRemoteInterface

hvac *Hvac
sentMessage []byte
}

var _ shipapi.ShipConnectionDataWriterInterface = (*HvacSuite)(nil)

func (s *HvacSuite) WriteShipMessageWithPayload(message []byte) {
s.sentMessage = message
}

func (s *HvacSuite) BeforeTest(suiteName, testName string) {
s.localEntity, s.remoteEntity = setupFeatures(
s.T(),
s,
[]featureFunctions{
{
featureType: model.FeatureTypeTypeHvac,
functions: []model.FunctionType{
model.FunctionTypeHvacSystemFunctionDescriptionListData,
model.FunctionTypeHvacSystemFunctionListData,
model.FunctionTypeHvacOperationModeDescriptionListData,
model.FunctionTypeHvacSystemFunctionOperationModeRelationListData,
model.FunctionTypeHvacSystemFunctionSetPointRelationListData,
model.FunctionTypeHvacOverrunDescriptionListData,
model.FunctionTypeHvacOverrunListData,
},
},
},
)

var err error
s.hvac, err = NewHvac(s.localEntity, nil)
assert.NotNil(s.T(), err)
assert.Nil(s.T(), s.hvac)

s.hvac, err = NewHvac(s.localEntity, s.remoteEntity)
assert.Nil(s.T(), err)
assert.NotNil(s.T(), s.hvac)
}

func (s *HvacSuite) Test_RequestHvacSystemFunctionDescriptions() {
counter, err := s.hvac.RequestHvacSystemFunctionDescriptions(nil, nil)
assert.Nil(s.T(), err)
assert.NotNil(s.T(), counter)
}

func (s *HvacSuite) Test_RequestHvacSystemFunctions() {
counter, err := s.hvac.RequestHvacSystemFunctions(nil, nil)
assert.Nil(s.T(), err)
assert.NotNil(s.T(), counter)
}

func (s *HvacSuite) Test_RequestHvacOperationModeDescriptions() {
counter, err := s.hvac.RequestHvacOperationModeDescriptions(nil, nil)
assert.Nil(s.T(), err)
assert.NotNil(s.T(), counter)
}

func (s *HvacSuite) Test_RequestHvacSystemFunctionOperationModeRelations() {
counter, err := s.hvac.RequestHvacSystemFunctionOperationModeRelations(nil, nil)
assert.Nil(s.T(), err)
assert.NotNil(s.T(), counter)
}

func (s *HvacSuite) Test_RequestHvacSystemFunctionSetpointRelations() {
counter, err := s.hvac.RequestHvacSystemFunctionSetpointRelations(nil, nil)
assert.Nil(s.T(), err)
assert.NotNil(s.T(), counter)
}

func (s *HvacSuite) Test_WriteHvacSystemFunctionListData() {
counter, err := s.hvac.WriteHvacSystemFunctionListData(nil)
assert.NotNil(s.T(), err)
assert.Nil(s.T(), counter)

data := []model.HvacSystemFunctionDataType{}
counter, err = s.hvac.WriteHvacSystemFunctionListData(data)
assert.NotNil(s.T(), err)
assert.Nil(s.T(), counter)

data = []model.HvacSystemFunctionDataType{
{
SystemFunctionId: util.Ptr(model.HvacSystemFunctionIdType(1)),
CurrentOperationModeId: util.Ptr(model.HvacOperationModeIdType(2)),
},
}
counter, err = s.hvac.WriteHvacSystemFunctionListData(data)
assert.Nil(s.T(), err)
assert.NotNil(s.T(), counter)
}

func (s *HvacSuite) Test_RequestHvacOverrunDescriptions() {
counter, err := s.hvac.RequestHvacOverrunDescriptions(nil, nil)
assert.Nil(s.T(), err)
assert.NotNil(s.T(), counter)
}

func (s *HvacSuite) Test_RequestHvacOverruns() {
counter, err := s.hvac.RequestHvacOverruns(nil, nil)
assert.Nil(s.T(), err)
assert.NotNil(s.T(), counter)
}

func (s *HvacSuite) Test_WriteHvacOverrunListData() {
counter, err := s.hvac.WriteHvacOverrunListData(nil)
assert.NotNil(s.T(), err)
assert.Nil(s.T(), counter)

data := []model.HvacOverrunDataType{
{
OverrunId: util.Ptr(model.HvacOverrunIdType(1)),
OverrunStatus: util.Ptr(model.HvacOverrunStatusTypeActive),
},
}
counter, err = s.hvac.WriteHvacOverrunListData(data)
assert.Nil(s.T(), err)
assert.NotNil(s.T(), counter)
}
84 changes: 84 additions & 0 deletions features/client/setpoint.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
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)
}

// write the given setpoint data to the remote device,
// returns the message counter of the sent message
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)
}

// IsSetpointListDataWritable reports whether the remote feature advertises the
// write operation for SetpointListData.
func (s *Setpoint) IsSetpointListDataWritable() bool {
operation, ok := s.featureRemote.Operations()[model.FunctionTypeSetpointListData]
return ok && operation != nil && operation.Write()
}
Loading