diff --git a/zonewatcher/constants.go b/kn/constants.go similarity index 98% rename from zonewatcher/constants.go rename to kn/constants.go index 558843b..5ab2fce 100644 --- a/zonewatcher/constants.go +++ b/kn/constants.go @@ -1,4 +1,4 @@ -package zonewatcher +package kn import "koolnova2mqtt/bimap" diff --git a/kn/zone.go b/kn/zone.go new file mode 100644 index 0000000..9c94e05 --- /dev/null +++ b/kn/zone.go @@ -0,0 +1,139 @@ +package kn + +import ( + "encoding/binary" + "log" +) + +type Watcher interface { + ReadRegister(address uint16) (value []byte, err error) + RegisterCallback(address uint16, callback func(address uint16)) +} + +type ZoneConfig struct { + ZoneNumber int + Watcher Watcher +} + +type Zone struct { + ZoneConfig + OnCurrentTempChange func(newTemp float32) + OnTargetTempChange func(newTemp float32) + OnFanModeChange func(newMode FanMode) + OnHvacModeChange func(newMode HvacMode) +} + +func NewZone(config *ZoneConfig) *Zone { + z := &Zone{ + ZoneConfig: *config, + } + z.RegisterCallback(REG_CURRENT_TEMP, func() { + if z.OnCurrentTempChange == nil { + return + } + + temp, err := z.GetCurrentTemperature() + if err != nil { + log.Printf("Cannot read current temperature: %s\n", err) + return + } + z.OnCurrentTempChange(temp) + }) + z.RegisterCallback(REG_TARGET_TEMP, func() { + if z.OnTargetTempChange == nil { + return + } + + temp, err := z.GetTargetTemperature() + if err != nil { + log.Printf("Cannot read target temperature: %s\n", err) + return + } + 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 + } + if z.OnFanModeChange != nil { + z.OnFanModeChange(fanMode) + } + if z.OnHvacModeChange != nil { + z.OnHvacModeChange(hvacMode) + } + }) + return z +} + +func (z *Zone) RegisterCallback(num int, f func()) { + z.Watcher.RegisterCallback(uint16(z.ZoneNumber*REG_PER_ZONE+num), func(address uint16) { + f() + }) +} + +func (z *Zone) ReadRegister(num int) (uint16, error) { + + b, err := z.Watcher.ReadRegister(uint16(z.ZoneNumber*REG_PER_ZONE + num)) + if err != nil { + return 0, err + } + return binary.BigEndian.Uint16(b), nil +} + +func (z *Zone) IsOn() (bool, error) { + r1, err := z.ReadRegister(REG_ENABLED) + if err != nil { + return false, err + } + + return r1&uint16(0x1) != 0, nil +} + +func (z *Zone) IsPresent() (bool, error) { + r1, err := z.ReadRegister(REG_ENABLED) + if err != nil { + return false, err + } + + return r1&uint16(0x2) != 0, nil +} + +func (z *Zone) GetCurrentTemperature() (float32, error) { + r4, err := z.ReadRegister(REG_CURRENT_TEMP) + if err != nil { + return 0.0, err + } + + return float32(r4) / 2.0, nil +} + +func (z *Zone) GetTargetTemperature() (float32, error) { + r3, err := z.ReadRegister(REG_TARGET_TEMP) + if err != nil { + return 0.0, err + } + return float32(r3) / 2.0, nil +} + +func (z *Zone) GetFanMode() (FanMode, error) { + r2, err := z.ReadRegister(REG_MODE) + if err != nil { + return 0, err + } + return (FanMode)(r2 & 0x00F0), nil +} + +func (z *Zone) GetHvacMode() (HvacMode, error) { + r2, err := z.ReadRegister(REG_MODE) + if err != nil { + return 0, err + } + return (HvacMode)(r2 & 0x000F), nil +} diff --git a/main.go b/main.go index 57b414d..c2cc9c9 100644 --- a/main.go +++ b/main.go @@ -4,8 +4,8 @@ import ( "crypto/tls" "flag" "fmt" + "koolnova2mqtt/kn" "koolnova2mqtt/watcher" - "koolnova2mqtt/zonewatcher" "log" "os" "os/signal" @@ -27,13 +27,13 @@ func buildReader(handler *modbus.RTUClientHandler, client modbus.Client) watcher } } -func getActiveZones(w zonewatcher.Watcher) ([]*zonewatcher.ZoneWatcher, error) { - var zones []*zonewatcher.ZoneWatcher +func getActiveZones(w kn.Watcher) ([]*kn.Zone, error) { + var zones []*kn.Zone for n := 0; n < NUM_ZONES; n++ { - zone := zonewatcher.New(&zonewatcher.Config{ - Zone: n, - Watcher: w, + zone := kn.NewZone(&kn.ZoneConfig{ + ZoneNumber: n, + Watcher: w, }) isPresent, err := zone.IsPresent() if err != nil { @@ -42,7 +42,7 @@ func getActiveZones(w zonewatcher.Watcher) ([]*zonewatcher.ZoneWatcher, error) { if isPresent { zones = append(zones, zone) temp, _ := zone.GetCurrentTemperature() - fmt.Printf("Zone %d is present. Temperature %g ºC\n", zone.Zone, temp) + fmt.Printf("Zone %d is present. Temperature %g ºC\n", zone.ZoneNumber, temp) } } return zones, nil @@ -125,24 +125,24 @@ func main() { for _, zone := range zones { zone := zone zone.OnCurrentTempChange = func(currentTemp float32) { - mqttClient.Publish(getTopic(zone.Zone, "currentTemperature"), 0, false, fmt.Sprintf("%g", currentTemp)) + mqttClient.Publish(getTopic(zone.ZoneNumber, "currentTemperature"), 0, false, fmt.Sprintf("%g", currentTemp)) } zone.OnTargetTempChange = func(targetTemp float32) { - mqttClient.Publish(getTopic(zone.Zone, "targetTemperature"), 0, false, fmt.Sprintf("%g", targetTemp)) + mqttClient.Publish(getTopic(zone.ZoneNumber, "targetTemperature"), 0, false, fmt.Sprintf("%g", targetTemp)) } - zone.OnFanModeChange = func(fanMode zonewatcher.FanMode) { - fanModeStr, found := zonewatcher.FanModes.GetInverse(fanMode) + zone.OnFanModeChange = func(fanMode kn.FanMode) { + fanModeStr, found := kn.FanModes.GetInverse(fanMode) if !found { log.Printf("Unknown fan mode %d", fanMode) } - mqttClient.Publish(getTopic(zone.Zone, "fanMode"), 0, false, fanModeStr) + mqttClient.Publish(getTopic(zone.ZoneNumber, "fanMode"), 0, false, fanModeStr) } - zone.OnHvacModeChange = func(hvacMode zonewatcher.HvacMode) { - hvacModeStr, found := zonewatcher.HvacModes.GetInverse(hvacMode) + zone.OnHvacModeChange = func(hvacMode kn.HvacMode) { + hvacModeStr, found := kn.HvacModes.GetInverse(hvacMode) if !found { log.Printf("Unknown hvac mode %d", hvacMode) } - mqttClient.Publish(getTopic(zone.Zone, "hvacMode"), 0, false, hvacModeStr) + mqttClient.Publish(getTopic(zone.ZoneNumber, "hvacMode"), 0, false, hvacModeStr) } } diff --git a/zonewatcher/zonewatcher.go b/zonewatcher/zonewatcher.go deleted file mode 100644 index 4277348..0000000 --- a/zonewatcher/zonewatcher.go +++ /dev/null @@ -1,139 +0,0 @@ -package zonewatcher - -import ( - "encoding/binary" - "log" -) - -type Watcher interface { - ReadRegister(address uint16) (value []byte, err error) - RegisterCallback(address uint16, callback func(address uint16)) -} - -type Config struct { - Zone int - Watcher Watcher -} - -type ZoneWatcher struct { - Config - OnCurrentTempChange func(newTemp float32) - OnTargetTempChange func(newTemp float32) - OnFanModeChange func(newMode FanMode) - OnHvacModeChange func(newMode HvacMode) -} - -func New(config *Config) *ZoneWatcher { - zw := &ZoneWatcher{ - Config: *config, - } - zw.RegisterCallback(REG_CURRENT_TEMP, func() { - if zw.OnCurrentTempChange == nil { - return - } - - temp, err := zw.GetCurrentTemperature() - if err != nil { - log.Printf("Cannot read current temperature: %s\n", err) - return - } - zw.OnCurrentTempChange(temp) - }) - zw.RegisterCallback(REG_TARGET_TEMP, func() { - if zw.OnTargetTempChange == nil { - return - } - - temp, err := zw.GetTargetTemperature() - if err != nil { - log.Printf("Cannot read target temperature: %s\n", err) - return - } - zw.OnTargetTempChange(temp) - }) - zw.RegisterCallback(REG_MODE, func() { - fanMode, err := zw.GetFanMode() - if err != nil { - log.Printf("Cannot read fan mode: %s\n", err) - return - } - hvacMode, err := zw.GetHvacMode() - if err != nil { - log.Printf("Cannot hvac mode: %s\n", err) - return - } - if zw.OnFanModeChange != nil { - zw.OnFanModeChange(fanMode) - } - if zw.OnHvacModeChange != nil { - zw.OnHvacModeChange(hvacMode) - } - }) - return zw -} - -func (zw *ZoneWatcher) RegisterCallback(num int, f func()) { - zw.Watcher.RegisterCallback(uint16(zw.Zone*REG_PER_ZONE+num), func(address uint16) { - f() - }) -} - -func (zw *ZoneWatcher) ReadRegister(num int) (uint16, error) { - - b, err := zw.Watcher.ReadRegister(uint16(zw.Zone*REG_PER_ZONE + num)) - if err != nil { - return 0, err - } - return binary.BigEndian.Uint16(b), nil -} - -func (zw *ZoneWatcher) IsOn() (bool, error) { - r1, err := zw.ReadRegister(REG_ENABLED) - if err != nil { - return false, err - } - - return r1&uint16(0x1) != 0, nil -} - -func (zw *ZoneWatcher) IsPresent() (bool, error) { - r1, err := zw.ReadRegister(REG_ENABLED) - if err != nil { - return false, err - } - - return r1&uint16(0x2) != 0, nil -} - -func (zw *ZoneWatcher) GetCurrentTemperature() (float32, error) { - r4, err := zw.ReadRegister(REG_CURRENT_TEMP) - if err != nil { - return 0.0, err - } - - return float32(r4) / 2.0, nil -} - -func (zw *ZoneWatcher) GetTargetTemperature() (float32, error) { - r3, err := zw.ReadRegister(REG_TARGET_TEMP) - if err != nil { - return 0.0, err - } - return float32(r3) / 2.0, nil -} - -func (zw *ZoneWatcher) GetFanMode() (FanMode, error) { - r2, err := zw.ReadRegister(REG_MODE) - if err != nil { - return 0, err - } - return (FanMode)(r2 & 0x00F0), nil -} - -func (zw *ZoneWatcher) GetHvacMode() (HvacMode, error) { - r2, err := zw.ReadRegister(REG_MODE) - if err != nil { - return 0, err - } - return (HvacMode)(r2 & 0x000F), nil -}