mirror of
https://github.com/jpeletier/koolnova2mqtt.git
synced 2026-01-12 03:24:23 +00:00
first hass integration
This commit is contained in:
156
kn/bridge.go
156
kn/bridge.go
@@ -1,9 +1,9 @@
|
||||
package kn
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"koolnova2mqtt/watcher"
|
||||
"log"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
@@ -14,6 +14,7 @@ type Config struct {
|
||||
SlaveID byte
|
||||
Publish Publish
|
||||
TopicPrefix string
|
||||
HassPrefix string
|
||||
ReadRegister watcher.ReadRegister
|
||||
}
|
||||
|
||||
@@ -32,13 +33,10 @@ func getActiveZones(w Watcher) ([]*Zone, error) {
|
||||
ZoneNumber: n,
|
||||
Watcher: w,
|
||||
})
|
||||
isPresent, err := zone.IsPresent()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
isPresent := zone.IsPresent()
|
||||
if isPresent {
|
||||
zones = append(zones, zone)
|
||||
temp, _ := zone.GetCurrentTemperature()
|
||||
temp := zone.GetCurrentTemperature()
|
||||
fmt.Printf("Zone %d is present. Temperature %g ºC\n", zone.ZoneNumber, temp)
|
||||
}
|
||||
}
|
||||
@@ -89,91 +87,123 @@ func (b *Bridge) Start() {
|
||||
return
|
||||
}
|
||||
|
||||
getHVACMode := func() string {
|
||||
if !sys.GetSystemEnabled() {
|
||||
return HVAC_MODE_OFF
|
||||
}
|
||||
switch sys.GetSystemKNMode() {
|
||||
case MODE_AIR_COOLING, MODE_UNDERFLOOR_AIR_COOLING:
|
||||
return HVAC_MODE_COOL
|
||||
case MODE_AIR_HEATING, MODE_UNDERFLOOR_HEATING, MODE_UNDERFLOOR_AIR_HEATING:
|
||||
return HVAC_MODE_HEAT
|
||||
}
|
||||
return "unknown"
|
||||
}
|
||||
|
||||
getHoldMode := func() string {
|
||||
switch sys.GetSystemKNMode() {
|
||||
case MODE_AIR_COOLING, MODE_AIR_HEATING:
|
||||
return HOLD_MODE_FAN_ONLY
|
||||
case MODE_UNDERFLOOR_HEATING:
|
||||
return HOLD_MODE_UNDERFLOOR_ONLY
|
||||
case MODE_UNDERFLOOR_AIR_COOLING, MODE_UNDERFLOOR_AIR_HEATING:
|
||||
return HOLD_MODE_UNDERFLOOR_AND_FAN
|
||||
}
|
||||
return "unknown"
|
||||
}
|
||||
|
||||
zones, err := getActiveZones(b.zw)
|
||||
var hvacModes []string
|
||||
for k, _ := range KnModes.GetForwardMap() {
|
||||
hvacModes = append(hvacModes, k.(string))
|
||||
}
|
||||
|
||||
hvacModeTopic := b.getSysTopic("hvacMode")
|
||||
hvacModeTopicSet := hvacModeTopic + "/set"
|
||||
holdModeTopic := b.getSysTopic("holdMode")
|
||||
holdModeSetTopic := holdModeTopic + "/set"
|
||||
|
||||
for _, zone := range zones {
|
||||
zone := zone
|
||||
currentTempTopic := b.getZoneTopic(zone.ZoneNumber, "currentTemp")
|
||||
targetTempTopic := b.getZoneTopic(zone.ZoneNumber, "targetTemp")
|
||||
targetTempSetTopic := targetTempTopic + "/set"
|
||||
fanModeTopic := b.getZoneTopic(zone.ZoneNumber, "fanMode")
|
||||
fanModeSetTopic := fanModeTopic + "/set"
|
||||
|
||||
zone.OnCurrentTempChange = func(currentTemp float32) {
|
||||
b.Publish(b.getZoneTopic(zone.ZoneNumber, "currentTemp"), 0, false, fmt.Sprintf("%g", currentTemp))
|
||||
b.Publish(currentTempTopic, 0, true, fmt.Sprintf("%g", currentTemp))
|
||||
}
|
||||
zone.OnTargetTempChange = func(targetTemp float32) {
|
||||
b.Publish(b.getZoneTopic(zone.ZoneNumber, "targetTemp"), 0, false, fmt.Sprintf("%g", targetTemp))
|
||||
b.Publish(targetTempTopic, 0, true, fmt.Sprintf("%g", targetTemp))
|
||||
}
|
||||
zone.OnFanModeChange = func(fanMode FanMode) {
|
||||
b.Publish(b.getZoneTopic(zone.ZoneNumber, "fanMode"), 0, false, FanMode2Str(fanMode))
|
||||
b.Publish(fanModeTopic, 0, true, FanMode2Str(fanMode))
|
||||
}
|
||||
zone.OnHvacModeChange = func(hvacMode HvacMode) {
|
||||
b.Publish(b.getZoneTopic(zone.ZoneNumber, "hvacMode"), 0, false, HvacMode2Str(hvacMode))
|
||||
zone.OnKnModeChange = func(knMode KnMode) {
|
||||
|
||||
}
|
||||
|
||||
name := fmt.Sprintf("%s_zone%d", b.ModuleName, zone.ZoneNumber)
|
||||
config := map[string]interface{}{
|
||||
"name": name,
|
||||
"current_temperature_topic": currentTempTopic,
|
||||
"precision": 0.5,
|
||||
"temperature_state_topic": targetTempTopic,
|
||||
"temperature_command_topic": targetTempSetTopic,
|
||||
"temperature_unit": "C",
|
||||
"temp_step": 0.5,
|
||||
"unique_id": name,
|
||||
"min_temp": 15,
|
||||
"max_temp": 35,
|
||||
"modes": []string{HVAC_MODE_COOL, HVAC_MODE_HEAT, HVAC_MODE_OFF},
|
||||
"mode_state_topic": hvacModeTopic,
|
||||
"mode_command_topic": hvacModeTopicSet,
|
||||
"fan_modes": []string{"auto", "low", "medium", "high"},
|
||||
"fan_mode_state_topic": fanModeTopic,
|
||||
"fan_mode_command_topic": fanModeSetTopic,
|
||||
"hold_modes": []string{HOLD_MODE_UNDERFLOOR_ONLY, HOLD_MODE_FAN_ONLY, HOLD_MODE_UNDERFLOOR_AND_FAN},
|
||||
"hold_state_topic": holdModeTopic,
|
||||
"hold_command_topic": holdModeSetTopic,
|
||||
}
|
||||
|
||||
configJSON, _ := json.Marshal(config)
|
||||
// <discovery_prefix>/<component>/[<node_id>/]<object_id>/config
|
||||
b.Publish(fmt.Sprintf("%s/climate/%s/zone%d/config", b.HassPrefix, b.ModuleName, zone.ZoneNumber), 0, true, string(configJSON))
|
||||
}
|
||||
|
||||
sys.OnACAirflowChange = func(ac ACMachine) {
|
||||
airflow, err := sys.GetAirflow(ac)
|
||||
if err != nil {
|
||||
log.Printf("Error reading airflow of AC %d: %s", ac, err)
|
||||
return
|
||||
}
|
||||
b.Publish(b.getACTopic(ac, "airflow"), 0, false, strconv.Itoa(airflow))
|
||||
airflow := sys.GetAirflow(ac)
|
||||
b.Publish(b.getACTopic(ac, "airflow"), 0, true, strconv.Itoa(airflow))
|
||||
}
|
||||
sys.OnACTargetTempChange = func(ac ACMachine) {
|
||||
targetTemp, err := sys.GetMachineTargetTemp(ac)
|
||||
if err != nil {
|
||||
log.Printf("Error reading target temp of AC %d: %s", ac, err)
|
||||
return
|
||||
}
|
||||
b.Publish(b.getACTopic(ac, "targetTemp"), 0, false, fmt.Sprintf("%g", targetTemp))
|
||||
targetTemp := sys.GetMachineTargetTemp(ac)
|
||||
b.Publish(b.getACTopic(ac, "targetTemp"), 0, true, fmt.Sprintf("%g", targetTemp))
|
||||
}
|
||||
sys.OnACTargetFanModeChange = func(ac ACMachine) {
|
||||
targetAirflow, err := sys.GetTargetFanMode(ac)
|
||||
if err != nil {
|
||||
log.Printf("Error reading target airflow of AC %d: %s", ac, err)
|
||||
return
|
||||
}
|
||||
b.Publish(b.getACTopic(ac, "fanMode"), 0, false, FanMode2Str(targetAirflow))
|
||||
targetAirflow := sys.GetTargetFanMode(ac)
|
||||
b.Publish(b.getACTopic(ac, "fanMode"), 0, true, FanMode2Str(targetAirflow))
|
||||
}
|
||||
sys.OnEfficiencyChange = func() {
|
||||
efficiency, err := sys.GetEfficiency()
|
||||
if err != nil {
|
||||
log.Printf("Error reading efficiency value: %s", err)
|
||||
return
|
||||
}
|
||||
b.Publish(b.getSysTopic("efficiency"), 0, false, strconv.Itoa(efficiency))
|
||||
efficiency := sys.GetEfficiency()
|
||||
b.Publish(b.getSysTopic("efficiency"), 0, true, strconv.Itoa(efficiency))
|
||||
}
|
||||
sys.OnSystemEnabledChange = func() {
|
||||
enabled, err := sys.GetSystemEnabled()
|
||||
if err != nil {
|
||||
log.Printf("Error reading enabled value: %s", err)
|
||||
return
|
||||
}
|
||||
b.Publish(b.getSysTopic("enabled"), 0, false, fmt.Sprintf("%t", enabled))
|
||||
enabled := sys.GetSystemEnabled()
|
||||
b.Publish(b.getSysTopic("enabled"), 0, true, fmt.Sprintf("%t", enabled))
|
||||
b.Publish(hvacModeTopic, 0, true, getHVACMode())
|
||||
}
|
||||
sys.OnHvacModeChange = func() {
|
||||
mode, err := sys.GetSystemHVACMode()
|
||||
if err != nil {
|
||||
log.Printf("Error reading hvac mode: %s", err)
|
||||
return
|
||||
}
|
||||
b.Publish(b.getSysTopic("hvacMode"), 0, false, HvacMode2Str(mode))
|
||||
sys.OnKnModeChange = func() {
|
||||
b.Publish(hvacModeTopic, 0, true, getHVACMode())
|
||||
b.Publish(holdModeTopic, 0, true, getHoldMode())
|
||||
}
|
||||
|
||||
b.zw.TriggerCallbacks()
|
||||
b.sysw.TriggerCallbacks()
|
||||
|
||||
bauds, err := sys.GetBaudRate()
|
||||
if err != nil {
|
||||
log.Printf("Error reading configured serial baud rate: %s", err)
|
||||
}
|
||||
parity, err := sys.GetParity()
|
||||
if err != nil {
|
||||
log.Printf("Error reading configured serial parity: %s", err)
|
||||
}
|
||||
slaveID, err := sys.GetSlaveID()
|
||||
if err != nil {
|
||||
log.Printf("Error reading configured modbus slave ID: %s", err)
|
||||
}
|
||||
b.Publish(b.getSysTopic("serialBaud"), 0, false, strconv.Itoa(bauds))
|
||||
b.Publish(b.getSysTopic("serialParity"), 0, false, parity)
|
||||
b.Publish(b.getSysTopic("slaveId"), 0, false, strconv.Itoa(slaveID))
|
||||
b.Publish(b.getSysTopic("serialBaud"), 0, true, strconv.Itoa(sys.GetBaudRate()))
|
||||
b.Publish(b.getSysTopic("serialParity"), 0, true, sys.GetParity())
|
||||
b.Publish(b.getSysTopic("slaveId"), 0, true, strconv.Itoa(sys.GetSlaveID()))
|
||||
}
|
||||
|
||||
func (b *Bridge) Tick() {
|
||||
|
||||
@@ -17,7 +17,7 @@ const REG_SERIAL_CONFIG = 77
|
||||
const REG_SLAVE_ID = 78
|
||||
const REG_EFFICIENCY = 79
|
||||
const REG_SYSTEM_ENABLED = 81
|
||||
const REG_SYS_HVAC_MODE = 82
|
||||
const REG_SYS_KN_MODE = 82
|
||||
|
||||
const FIRST_ZONE_REGISTER = REG_ENABLED
|
||||
const TOTAL_ZONE_REGISTERS = NUM_ZONES * REG_PER_ZONE
|
||||
@@ -32,13 +32,13 @@ const FAN_MED FanMode = 2
|
||||
const FAN_HIGH FanMode = 3
|
||||
const FAN_AUTO FanMode = 4
|
||||
|
||||
type HvacMode byte
|
||||
type KnMode byte
|
||||
|
||||
const MODE_AIR_COOLING HvacMode = 0x01
|
||||
const MODE_AIR_HEATING HvacMode = 0x02
|
||||
const MODE_UNDERFLOOR_HEATING HvacMode = 0x04
|
||||
const MODE_UNDERFLOOR_AIR_COOLING HvacMode = 0x05
|
||||
const MODE_UNDERFLOOR_AIR_HEATING HvacMode = 0x06
|
||||
const MODE_AIR_COOLING KnMode = 0x01
|
||||
const MODE_AIR_HEATING KnMode = 0x02
|
||||
const MODE_UNDERFLOOR_HEATING KnMode = 0x04
|
||||
const MODE_UNDERFLOOR_AIR_COOLING KnMode = 0x05
|
||||
const MODE_UNDERFLOOR_AIR_HEATING KnMode = 0x06
|
||||
|
||||
var FanModes = bimap.New(map[interface{}]interface{}{
|
||||
"off": FAN_OFF,
|
||||
@@ -48,7 +48,7 @@ var FanModes = bimap.New(map[interface{}]interface{}{
|
||||
"auto": FAN_AUTO,
|
||||
})
|
||||
|
||||
var HvacModes = bimap.New(map[interface{}]interface{}{
|
||||
var KnModes = bimap.New(map[interface{}]interface{}{
|
||||
"air cooling": MODE_AIR_COOLING,
|
||||
"air heating": MODE_AIR_HEATING,
|
||||
"underfloor heating": MODE_UNDERFLOOR_HEATING,
|
||||
@@ -56,6 +56,14 @@ var HvacModes = bimap.New(map[interface{}]interface{}{
|
||||
"underfloor air heating": MODE_UNDERFLOOR_AIR_HEATING,
|
||||
})
|
||||
|
||||
const HOLD_MODE_UNDERFLOOR_ONLY = "underfloor only"
|
||||
const HOLD_MODE_FAN_ONLY = "fan only"
|
||||
const HOLD_MODE_UNDERFLOOR_AND_FAN = "underfloor and fan"
|
||||
|
||||
const HVAC_MODE_OFF = "off"
|
||||
const HVAC_MODE_COOL = "cool"
|
||||
const HVAC_MODE_HEAT = "heat"
|
||||
|
||||
type ACMachine int
|
||||
|
||||
const ACMachines = 4
|
||||
@@ -73,8 +81,8 @@ func FanMode2Str(fm FanMode) string {
|
||||
return st.(string)
|
||||
}
|
||||
|
||||
func HvacMode2Str(hm HvacMode) string {
|
||||
st, ok := HvacModes.GetInverse(hm)
|
||||
func KnMode2Str(hm KnMode) string {
|
||||
st, ok := KnModes.GetInverse(hm)
|
||||
if !ok {
|
||||
st = "unknown"
|
||||
}
|
||||
|
||||
106
kn/sys.go
106
kn/sys.go
@@ -13,7 +13,7 @@ type Sys struct {
|
||||
OnACTargetFanModeChange func(ac ACMachine)
|
||||
OnEfficiencyChange func()
|
||||
OnSystemEnabledChange func()
|
||||
OnHvacModeChange func()
|
||||
OnKnModeChange func()
|
||||
}
|
||||
|
||||
var ErrUnknownSerialConfig = errors.New("Uknown serial configuration")
|
||||
@@ -54,103 +54,73 @@ func NewSys(config *SysConfig) *Sys {
|
||||
}
|
||||
})
|
||||
|
||||
s.Watcher.RegisterCallback(REG_SYS_HVAC_MODE, func(address uint16) {
|
||||
if s.OnHvacModeChange != nil {
|
||||
s.OnHvacModeChange()
|
||||
s.Watcher.RegisterCallback(REG_SYS_KN_MODE, func(address uint16) {
|
||||
if s.OnKnModeChange != nil {
|
||||
s.OnKnModeChange()
|
||||
}
|
||||
})
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *Sys) ReadRegister(n int) (int, error) {
|
||||
r, err := s.Watcher.ReadRegister(uint16(n))
|
||||
if err != nil || len(r) != 2 {
|
||||
return 0, nil
|
||||
}
|
||||
return int(r[1]), nil
|
||||
func (s *Sys) ReadRegister(n int) int {
|
||||
r := s.Watcher.ReadRegister(uint16(n))
|
||||
return int(r[1])
|
||||
}
|
||||
|
||||
func (s *Sys) GetAirflow(ac ACMachine) (int, error) {
|
||||
r, err := s.ReadRegister(REG_AIRFLOW + int(ac) - 1)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return r, nil
|
||||
func (s *Sys) GetAirflow(ac ACMachine) int {
|
||||
r := s.ReadRegister(REG_AIRFLOW + int(ac) - 1)
|
||||
return r
|
||||
}
|
||||
|
||||
func (s *Sys) GetMachineTargetTemp(ac ACMachine) (float32, error) {
|
||||
r, err := s.ReadRegister(REG_AC_TARGET_TEMP + int(ac) - 1)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return reg2temp(uint16(r)), nil
|
||||
func (s *Sys) GetMachineTargetTemp(ac ACMachine) float32 {
|
||||
r := s.ReadRegister(REG_AC_TARGET_TEMP + int(ac) - 1)
|
||||
return reg2temp(uint16(r))
|
||||
}
|
||||
|
||||
func (s *Sys) GetTargetFanMode(ac ACMachine) (FanMode, error) {
|
||||
r, err := s.ReadRegister(REG_AC_TARGET_FAN_MODE + int(ac) - 1)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return FanMode(r), nil
|
||||
func (s *Sys) GetTargetFanMode(ac ACMachine) FanMode {
|
||||
r := s.ReadRegister(REG_AC_TARGET_FAN_MODE + int(ac) - 1)
|
||||
return FanMode(r)
|
||||
}
|
||||
|
||||
func (s *Sys) GetBaudRate() (int, error) {
|
||||
r, err := s.ReadRegister(REG_SERIAL_CONFIG)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
func (s *Sys) GetBaudRate() int {
|
||||
r := s.ReadRegister(REG_SERIAL_CONFIG)
|
||||
switch r {
|
||||
case 2, 6:
|
||||
return 9600, nil
|
||||
return 9600
|
||||
case 3, 7:
|
||||
return 19200, nil
|
||||
return 19200
|
||||
}
|
||||
return 0, ErrUnknownSerialConfig
|
||||
return 0
|
||||
}
|
||||
|
||||
func (s *Sys) GetParity() (string, error) {
|
||||
r, err := s.ReadRegister(REG_SERIAL_CONFIG)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
func (s *Sys) GetParity() string {
|
||||
r := s.ReadRegister(REG_SERIAL_CONFIG)
|
||||
switch r {
|
||||
case 2, 3:
|
||||
return "even", nil
|
||||
return "even"
|
||||
case 6, 7:
|
||||
return "none", nil
|
||||
return "none"
|
||||
}
|
||||
return "", ErrUnknownSerialConfig
|
||||
return "unknown"
|
||||
}
|
||||
|
||||
func (s *Sys) GetSlaveID() (int, error) {
|
||||
r, err := s.ReadRegister(REG_SLAVE_ID)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return r, nil
|
||||
func (s *Sys) GetSlaveID() int {
|
||||
r := s.ReadRegister(REG_SLAVE_ID)
|
||||
return r
|
||||
}
|
||||
|
||||
func (s *Sys) GetEfficiency() (int, error) {
|
||||
r, err := s.ReadRegister(REG_EFFICIENCY)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return r, nil
|
||||
func (s *Sys) GetEfficiency() int {
|
||||
r := s.ReadRegister(REG_EFFICIENCY)
|
||||
return r
|
||||
}
|
||||
|
||||
func (s *Sys) GetSystemEnabled() (bool, error) {
|
||||
r, err := s.ReadRegister(REG_SYSTEM_ENABLED)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return r != 0, nil
|
||||
func (s *Sys) GetSystemEnabled() bool {
|
||||
r := s.ReadRegister(REG_SYSTEM_ENABLED)
|
||||
return r != 0
|
||||
}
|
||||
|
||||
func (s *Sys) GetSystemHVACMode() (HvacMode, error) {
|
||||
r, err := s.ReadRegister(REG_SYS_HVAC_MODE)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return HvacMode(r), nil
|
||||
func (s *Sys) GetSystemKNMode() KnMode {
|
||||
r := s.ReadRegister(REG_SYS_KN_MODE)
|
||||
return KnMode(r)
|
||||
}
|
||||
|
||||
99
kn/zone.go
99
kn/zone.go
@@ -2,11 +2,10 @@ package kn
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"log"
|
||||
)
|
||||
|
||||
type Watcher interface {
|
||||
ReadRegister(address uint16) (value []byte, err error)
|
||||
ReadRegister(address uint16) (value []byte)
|
||||
RegisterCallback(address uint16, callback func(address uint16))
|
||||
}
|
||||
|
||||
@@ -20,7 +19,7 @@ type Zone struct {
|
||||
OnCurrentTempChange func(newTemp float32)
|
||||
OnTargetTempChange func(newTemp float32)
|
||||
OnFanModeChange func(newMode FanMode)
|
||||
OnHvacModeChange func(newMode HvacMode)
|
||||
OnKnModeChange func(newMode KnMode)
|
||||
}
|
||||
|
||||
func NewZone(config *ZoneConfig) *Zone {
|
||||
@@ -32,11 +31,7 @@ func NewZone(config *ZoneConfig) *Zone {
|
||||
return
|
||||
}
|
||||
|
||||
temp, err := z.GetCurrentTemperature()
|
||||
if err != nil {
|
||||
log.Printf("Cannot read current temperature: %s\n", err)
|
||||
return
|
||||
}
|
||||
temp := z.GetCurrentTemperature()
|
||||
z.OnCurrentTempChange(temp)
|
||||
})
|
||||
z.RegisterCallback(REG_TARGET_TEMP, func() {
|
||||
@@ -44,29 +39,17 @@ func NewZone(config *ZoneConfig) *Zone {
|
||||
return
|
||||
}
|
||||
|
||||
temp, err := z.GetTargetTemperature()
|
||||
if err != nil {
|
||||
log.Printf("Cannot read target temperature: %s\n", err)
|
||||
return
|
||||
}
|
||||
temp := z.GetTargetTemperature()
|
||||
z.OnTargetTempChange(temp)
|
||||
})
|
||||
z.RegisterCallback(REG_MODE, func() {
|
||||
fanMode, err := z.GetFanMode()
|
||||
if err != nil {
|
||||
log.Printf("Cannot read fan mode: %s\n", err)
|
||||
return
|
||||
}
|
||||
hvacMode, err := z.GetHvacMode()
|
||||
if err != nil {
|
||||
log.Printf("Cannot hvac mode: %s\n", err)
|
||||
return
|
||||
}
|
||||
fanMode := z.GetFanMode()
|
||||
hvacMode := z.GetHvacMode()
|
||||
if z.OnFanModeChange != nil {
|
||||
z.OnFanModeChange(fanMode)
|
||||
}
|
||||
if z.OnHvacModeChange != nil {
|
||||
z.OnHvacModeChange(hvacMode)
|
||||
if z.OnKnModeChange != nil {
|
||||
z.OnKnModeChange(hvacMode)
|
||||
}
|
||||
})
|
||||
return z
|
||||
@@ -78,64 +61,40 @@ func (z *Zone) RegisterCallback(num int, f func()) {
|
||||
})
|
||||
}
|
||||
|
||||
func (z *Zone) ReadRegister(num int) (uint16, error) {
|
||||
func (z *Zone) ReadRegister(num int) uint16 {
|
||||
|
||||
b, err := z.Watcher.ReadRegister(uint16(z.ZoneNumber*REG_PER_ZONE + num))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return binary.BigEndian.Uint16(b), nil
|
||||
b := z.Watcher.ReadRegister(uint16(z.ZoneNumber*REG_PER_ZONE + num))
|
||||
return binary.BigEndian.Uint16(b)
|
||||
}
|
||||
|
||||
func (z *Zone) IsOn() (bool, error) {
|
||||
r1, err := z.ReadRegister(REG_ENABLED)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return r1&0x1 != 0, nil
|
||||
func (z *Zone) IsOn() bool {
|
||||
r1 := z.ReadRegister(REG_ENABLED)
|
||||
return r1&0x1 != 0
|
||||
}
|
||||
|
||||
func (z *Zone) IsPresent() (bool, error) {
|
||||
r1, err := z.ReadRegister(REG_ENABLED)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return r1&0x2 != 0, nil
|
||||
func (z *Zone) IsPresent() bool {
|
||||
r1 := z.ReadRegister(REG_ENABLED)
|
||||
return r1&0x2 != 0
|
||||
}
|
||||
|
||||
func (z *Zone) GetCurrentTemperature() (float32, error) {
|
||||
r4, err := z.ReadRegister(REG_CURRENT_TEMP)
|
||||
if err != nil {
|
||||
return 0.0, err
|
||||
}
|
||||
|
||||
return reg2temp(r4), nil
|
||||
func (z *Zone) GetCurrentTemperature() float32 {
|
||||
r4 := z.ReadRegister(REG_CURRENT_TEMP)
|
||||
return reg2temp(r4)
|
||||
}
|
||||
|
||||
func (z *Zone) GetTargetTemperature() (float32, error) {
|
||||
r3, err := z.ReadRegister(REG_TARGET_TEMP)
|
||||
if err != nil {
|
||||
return 0.0, err
|
||||
}
|
||||
return reg2temp(r3), nil
|
||||
func (z *Zone) GetTargetTemperature() float32 {
|
||||
r3 := z.ReadRegister(REG_TARGET_TEMP)
|
||||
return reg2temp(r3)
|
||||
}
|
||||
|
||||
func (z *Zone) GetFanMode() (FanMode, error) {
|
||||
r2, err := z.ReadRegister(REG_MODE)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return (FanMode)(r2&0x00F0) >> 4, nil
|
||||
func (z *Zone) GetFanMode() FanMode {
|
||||
r2 := z.ReadRegister(REG_MODE)
|
||||
return (FanMode)(r2&0x00F0) >> 4
|
||||
}
|
||||
|
||||
func (z *Zone) GetHvacMode() (HvacMode, error) {
|
||||
r2, err := z.ReadRegister(REG_MODE)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return (HvacMode)(r2 & 0x000F), nil
|
||||
func (z *Zone) GetHvacMode() KnMode {
|
||||
r2 := z.ReadRegister(REG_MODE)
|
||||
return (KnMode)(r2 & 0x000F)
|
||||
}
|
||||
|
||||
func reg2temp(r uint16) float32 {
|
||||
|
||||
2
main.go
2
main.go
@@ -54,6 +54,7 @@ func main() {
|
||||
username := flag.String("username", "", "A username to authenticate to the MQTT server")
|
||||
password := flag.String("password", "", "Password to match username")
|
||||
prefix := flag.String("prefix", "koolnova2mqtt", "MQTT topic root where to publish/read topics")
|
||||
hassPrefix := flag.String("hassPrefix", "homeassistant", "Home assistant discovery prefix")
|
||||
modbusPort := flag.String("modbusPort", "/dev/ttyUSB0", "Serial port where modbus hardware is connected")
|
||||
modbusPortBaudRate := flag.Int("modbusRate", 9600, "Modbus port data rate")
|
||||
modbusDataBits := flag.Int("modbusDataBits", 8, "Modbus port data bits")
|
||||
@@ -112,6 +113,7 @@ func main() {
|
||||
SlaveID: byte(slaveID),
|
||||
Publish: publish,
|
||||
TopicPrefix: *prefix,
|
||||
HassPrefix: *hassPrefix,
|
||||
ReadRegister: registerReader,
|
||||
})
|
||||
bridges = append(bridges, bridge)
|
||||
|
||||
@@ -72,15 +72,15 @@ func (w *Watcher) Poll() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *Watcher) ReadRegister(address uint16) (value []byte, err error) {
|
||||
func (w *Watcher) ReadRegister(address uint16) (value []byte) {
|
||||
if address < w.Address || address > w.Address+uint16(w.Quantity) {
|
||||
return nil, ErrAddressOutOfRange
|
||||
panic(ErrAddressOutOfRange)
|
||||
}
|
||||
if w.state == nil {
|
||||
return nil, ErrUninitialized
|
||||
panic(ErrUninitialized)
|
||||
}
|
||||
registerOffset := int(address-w.Address) * w.RegisterSize
|
||||
return w.state[registerOffset : registerOffset+w.RegisterSize], nil
|
||||
return w.state[registerOffset : registerOffset+w.RegisterSize]
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user