Skip to content

Commit

Permalink
Add on/off register and additional AC modes (#31)
Browse files Browse the repository at this point in the history
1. Add on/off register and add'l AC modes

2. Add tests for AirConditioningMode.

3. Minor docstring fixes.

---------

Co-authored-by: Andrew Metcalf <[email protected]>
  • Loading branch information
gonzojive and andrew-stripe authored Aug 25, 2024
1 parent da34ec1 commit dd14533
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 10 deletions.
8 changes: 7 additions & 1 deletion cx34/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")

go_library(
name = "cx34",
Expand All @@ -25,3 +25,9 @@ go_library(
"@org_uber_go_multierr//:multierr",
],
)

go_test(
name = "cx34_test",
srcs = ["ctx34_test.go"],
embed = [":cx34"],
)
64 changes: 64 additions & 0 deletions cx34/ctx34_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package cx34

import "testing"

func TestAirConditioningMode(t *testing.T) {
testCases := []struct {
mode AirConditioningMode
wantIsCooling bool
wantIsHeating bool
wantString string
}{
{AirConditioningModeCooling, true, false, "Cooling"},
{AirConditioningModeHeating, false, true, "Heating"},
{AirConditioningModeDHW, false, false, "Domestic Hot Water"},
{AirConditioningModeCoolingAndDHW, true, false, "Cooling + Domestic Hot Water"},
{AirConditioningModeHeatingAndDHW, false, true, "Heating + Domestic Hot Water"},
{AirConditioningMode(42), false, false, "Unknown AirConditioningMode (42)"},
}

for _, tc := range testCases {
t.Run(tc.mode.String(), func(t *testing.T) {
if got := tc.mode.IsCooling(); got != tc.wantIsCooling {
t.Errorf("IsCooling(%v) = %v, want %v", tc.mode, got, tc.wantIsCooling)
}
if got := tc.mode.IsHeating(); got != tc.wantIsHeating {
t.Errorf("IsHeating(%v) = %v, want %v", tc.mode, got, tc.wantIsHeating)
}
if got := tc.mode.String(); got != tc.wantString {
t.Errorf("String(%v) = %q, want %q", tc.mode, got, tc.wantString)
}
})
}
}

func TestAirConditioningMode_parse(t *testing.T) {
testCases := []struct {
want AirConditioningMode
registerValue uint16
wantErr bool
}{
{AirConditioningModeCooling, 0, false},
{AirConditioningModeHeating, 1, false},
{AirConditioningModeDHW, 2, false},
{AirConditioningModeCoolingAndDHW, 3, false},
{AirConditioningModeHeatingAndDHW, 4, false},
{AirConditioningMode(42), 42, true},
}

for _, tc := range testCases {
t.Run(tc.want.String(), func(t *testing.T) {
got, err := parseAirConditioningMode(tc.registerValue)
if err != nil {
if !tc.wantErr {
t.Errorf("parseAirConditioningMode(%v) error = %v, wantErr = %v", tc.registerValue, err, tc.wantErr)
}
return
}

if got != tc.want {
t.Errorf("parseAirConditioningMode(%v) = %q, want %q", tc.registerValue, got, tc.want)
}
})
}
}
48 changes: 39 additions & 9 deletions cx34/cx34_registers.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,12 +159,12 @@ func (s *State) COP() (units.CoefficientOfPerformance, bool) {
return baseCOP, true
}

// DeltaT returns the outlet temperature minust he inlet temperature
// DeltaT returns the outlet temperature minus the inlet temperature.
func (s *State) DeltaT() units.Temperature {
return s.ACOutletWaterTemp() - s.ACInletWaterTemp()
}

// ACMode returns the outlet temperature minust he inlet temperature
// ACMode returns the current AirConditioningMode.
func (s *State) ACMode() AirConditioningMode {
raw := s.registerValues[ACMode]
mode, err := parseAirConditioningMode(raw)
Expand All @@ -175,37 +175,65 @@ func (s *State) ACMode() AirConditioningMode {
}

// AirConditioningMode specifies whether the heat pump is configured to heat,
// cool, heat+domestic hot water, or cool+domestic hot water.
// cool, domestic hot water, heat+domestic hot water, or cool+domestic hot water.
type AirConditioningMode uint8

// Valid AirConditioningMode values.
const (
// Cooling only.
AirConditioningModeCooling AirConditioningMode = 0
// Heating only.
AirConditioningModeHeating AirConditioningMode = 1
// Heat+DHW, Cool+DHW are options but I'm unsure of the values.
// Domestic hot water only.
AirConditioningModeDHW AirConditioningMode = 2
// Cooling + domestic hot water.
AirConditioningModeCoolingAndDHW AirConditioningMode = 3
// Heating + domestic hot water.
AirConditioningModeHeatingAndDHW AirConditioningMode = 4
)

var validACModes = map[AirConditioningMode]struct{}{
AirConditioningModeCooling: {},
AirConditioningModeHeating: {},
AirConditioningModeCooling: {},
AirConditioningModeHeating: {},
AirConditioningModeDHW: {},
AirConditioningModeCoolingAndDHW: {},
AirConditioningModeHeatingAndDHW: {},
}

func parseAirConditioningMode(val uint16) (AirConditioningMode, error) {
asEnum := AirConditioningMode(val)
if _, ok := validACModes[asEnum]; ok {
return asEnum, nil
}
return asEnum, fmt.Errorf("invalid ACMode value %d")
return asEnum, fmt.Errorf("invalid AirConditioningMode value, %d", val)
}

// IsCooling reports if the mode is cooling or cooling+domestic hot water.
func (m AirConditioningMode) IsCooling() bool {
return m == AirConditioningModeCooling
return m == AirConditioningModeCooling || m == AirConditioningModeCoolingAndDHW
}

// IsHeating reports if the mode is heating or heating+domestic hot water.
func (m AirConditioningMode) IsHeating() bool {
return m == AirConditioningModeHeating
return m == AirConditioningModeHeating || m == AirConditioningModeHeatingAndDHW
}

// String returns the string representation of the AirConditioningMode.
func (m AirConditioningMode) String() string {
switch m {
case AirConditioningModeCooling:
return "Cooling"
case AirConditioningModeHeating:
return "Heating"
case AirConditioningModeDHW:
return "Domestic Hot Water"
case AirConditioningModeCoolingAndDHW:
return "Cooling + Domestic Hot Water"
case AirConditioningModeHeatingAndDHW:
return "Heating + Domestic Hot Water"
default:
return fmt.Sprintf("Unknown AirConditioningMode (%d)", m)
}
}

/*
Expand Down Expand Up @@ -251,6 +279,7 @@ Table of registers with values that changed

// Known Register values.
const (
SwitchOnOff Register = 140 // 0 = off, 1 = on
ACMode Register = 141 // 0 = cool, 1 = heat
TargetACCoolingModeTemp Register = 142
TargetACHeatingModeTemp Register = 143
Expand Down Expand Up @@ -323,6 +352,7 @@ const (

// Source: https://www.chiltrix.com/control-options/Remote-Gateway-BACnet-Guide-rev2.pdf
var registerNames = map[Register]string{
SwitchOnOff: "SwitchOnOff",
ACMode: "ACMode",
TargetACCoolingModeTemp: "TargetACCoolingModeTemp",
TargetACHeatingModeTemp: "TargetACHeatingModeTemp",
Expand Down

0 comments on commit dd14533

Please sign in to comment.