Skip to content
7 changes: 4 additions & 3 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"encoding/base64"
"encoding/json"
"flag"
"io/ioutil"
"os"
"path/filepath"
"time"

Expand Down Expand Up @@ -50,6 +50,7 @@ type PersistedConfig struct {
Disabled bool
ButtonDisabled bool
SolarDisabled bool
CoolDisabled bool
Auth string
Pin string
Target float64
Expand Down Expand Up @@ -146,14 +147,14 @@ func (c *Config) Save() error {
}
cfgFilename := filepath.Join(*c.dataDirectory, serverConfiguration)
Info("Writing config file to: %s\n%s", cfgFilename, string(buf))
err = ioutil.WriteFile(cfgFilename, buf, 0600)
err = os.WriteFile(cfgFilename, buf, 0600)
return err
}

// Read reads the config from the fileystem
func (c *Config) Read() error {
cfgFilename := filepath.Join(*c.dataDirectory, serverConfiguration)
cfg, err := ioutil.ReadFile(cfgFilename)
cfg, err := os.ReadFile(cfgFilename)
if err != nil {
Error("Unable to read configuration file: %s", err.Error())
return err
Expand Down
3 changes: 1 addition & 2 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package main
import (
"flag"
"fmt"
"io/ioutil"
"os"

"github.com/brutella/hc"
Expand All @@ -26,7 +25,7 @@ func main() {
Info("Args: %s", os.Args[1:])

// Write PID
err := ioutil.WriteFile(*config.pidfile, []byte(fmt.Sprintf("%d", os.Getpid())), 0644)
err := os.WriteFile(*config.pidfile, []byte(fmt.Sprintf("%d", os.Getpid())), 0644)
if err != nil {
Fatal("Could not write pid file: %s", err.Error())
}
Expand Down
21 changes: 11 additions & 10 deletions poolpump.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,11 @@ func (ppc *PoolPumpController) Update() error {
// (probably at night), running the pumps with solar on would help bring the water
// down to the target temperature.
func (ppc *PoolPumpController) shouldCool() bool {
if ppc.config.cfg.SolarDisabled {
if ppc.config.cfg.SolarDisabled || ppc.config.cfg.CoolDisabled {
return false
}
return ppc.pumpTemp.Temperature() > (ppc.config.cfg.Target+ppc.config.cfg.Tolerance) &&
ppc.pumpTemp.Temperature() > (ppc.roofTemp.Temperature()+ppc.config.cfg.DeltaT)
return ppc.runningTemp.Temperature() > (ppc.config.cfg.Target+(2*ppc.config.cfg.Tolerance)) &&
ppc.runningTemp.Temperature() > (ppc.roofTemp.Temperature()+ppc.config.cfg.DeltaT)
}

// A return value of 'True' indicates that the pool is too cool and the roof is hot, running
Expand All @@ -103,19 +103,20 @@ func (ppc *PoolPumpController) shouldWarm() bool {
return false
}

waterCold := ppc.pumpTemp.Temperature() < (ppc.config.cfg.Target - ppc.config.cfg.Tolerance)
roofHot := ppc.pumpTemp.Temperature() < (ppc.roofTemp.Temperature() - ppc.config.cfg.DeltaT)
waterCold := ppc.runningTemp.Temperature() < (ppc.config.cfg.Target - ppc.config.cfg.Tolerance)
roofHot := ppc.runningTemp.Temperature() < (ppc.roofTemp.Temperature() - ppc.config.cfg.DeltaT)
warm := waterCold && roofHot
if warm {
Info("ShouldWarm: %t waterCold(%t) roofHot(%t)", warm, waterCold, roofHot)
Info(ppc.Status())
Info("Temp(%0.3f) < %0.3f {Target(%0.3f) - Tolerance(%0.3f)} : WaterCold(%t)",
ppc.pumpTemp.Temperature(),
ppc.runningTemp.Temperature(),
ppc.config.cfg.Target-ppc.config.cfg.Tolerance,
ppc.config.cfg.Target,
ppc.config.cfg.Tolerance,
waterCold)
Info("Temp(%0.3f) < %0.3f {Roof(%0.3f) - DeltaT(%0.3f)} : RoofHot(%t)",
ppc.pumpTemp.Temperature(),
ppc.runningTemp.Temperature(),
ppc.roofTemp.Temperature()-ppc.config.cfg.DeltaT,
ppc.roofTemp.Temperature(),
ppc.config.cfg.DeltaT,
Expand Down Expand Up @@ -150,8 +151,8 @@ func (ppc *PoolPumpController) RunPumpsIfNeeded() {
return
}
Info("ShouldCool(%t) - ShouldWarm(%t)", ppc.shouldCool(), ppc.shouldWarm())
if ppc.pumpTemp.Temperature() < ppc.config.cfg.Target-ppc.config.cfg.DeltaT ||
ppc.pumpTemp.Temperature() > ppc.config.cfg.Target+ppc.config.cfg.Tolerance {
if ppc.runningTemp.Temperature() < ppc.config.cfg.Target-ppc.config.cfg.DeltaT ||
ppc.runningTemp.Temperature() > ppc.config.cfg.Target+(2*ppc.config.cfg.Tolerance) {
ppc.switches.SetState(MIXING, false, ppc.config.cfg.RunTime)
} else {
// Just push water through the panels
Expand All @@ -172,7 +173,7 @@ func (ppc *PoolPumpController) RunPumpsIfNeeded() {
return
}
// If there is no reason to turn on the pumps and it's not manual, turn off
if state > OFF && ppc.switches.GetStartTime().Add(time.Hour).Before(time.Now()) {
if state > OFF && ppc.switches.GetStartTime().Add(time.Minute*5).Before(time.Now()) {
ppc.switches.StopAll(false)
}
}
Expand Down
4 changes: 4 additions & 0 deletions server.go
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,9 @@ func (h *Handler) processForm(r *http.Request, c *Config) {
if processBoolUpdate(r, "solar_disabled", &c.cfg.SolarDisabled) {
foundone = true
}
if processBoolUpdate(r, "cool_disabled", &c.cfg.CoolDisabled) {
foundone = true
}
if processFloatUpdate(r, "daily_freq", &c.cfg.DailyFrequency) {
foundone = true
}
Expand Down Expand Up @@ -547,6 +550,7 @@ func (h *Handler) configHandler(w http.ResponseWriter, r *http.Request) {
html += h.configBoolRow("Disable all pumps", "disabled", c.cfg.Disabled)
html += h.configBoolRow("Disable button", "button_disabled", c.cfg.ButtonDisabled)
html += h.configBoolRow("Disable solar", "solar_disabled", c.cfg.SolarDisabled)
html += h.configBoolRow("Disable cooling", "cool_disabled", c.cfg.CoolDisabled)

html += "<input type=hidden name=posted value=true>\n"
html += "</table><input type=submit value=Save></font></font></form>\n"
Expand Down
22 changes: 5 additions & 17 deletions switches.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,10 +118,11 @@ func (p *Switches) bindHK() {
state := p.state
switch p.state {
case SWEEP:
case MIXING:
if on {
state = MIXING
} else {
}
case MIXING:
if !on {
state = SWEEP
}
case SOLAR:
Expand Down Expand Up @@ -182,11 +183,7 @@ func (p *Switches) setSwitches(pumpOn, sweepOn, solarOn, isManual bool, state St
turnOn(p.sweep, sweepOn)
turnOn(p.solar, solarOn) // deal with solar valve last because it takes time
if isManual {
if p.GetStartTime().After(p.GetStopTime()) {
p.manualOp = p.GetStartTime()
} else {
p.manualOp = p.GetStopTime()
}
p.manualOp = time.Now()
Comment thread
ebilling marked this conversation as resolved.
}
p.state = state
}
Expand Down Expand Up @@ -253,14 +250,5 @@ func DurationFromHours(hours float64, minHours float64) time.Duration {

// ManualState returns true if the pumps were started or stopped manually
func (p *Switches) ManualState(runtime float64) bool {
if time.Since(p.manualOp) > DurationFromHours(runtime, 2.0) {
return false
}
if p.manualOp.Equal(p.GetStartTime()) && p.GetStartTime().After(p.GetStopTime()) {
return true
}
if p.manualOp.Equal(p.GetStopTime()) && p.GetStopTime().After(p.GetStartTime()) {
return true
}
return false
return time.Since(p.manualOp) < DurationFromHours(runtime, 2.0)
}
4 changes: 2 additions & 2 deletions thermometer.go
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ func (t *GpioThermometer) Update() error {
stdd := t.history.Stddev()
avg := t.history.Average()
med := t.history.Median()
dev := stdd * 3
dev := stdd * 2

// Throw away bad results
if math.Abs(avg-h.Median()) > dev {
Expand All @@ -247,7 +247,7 @@ func (t *GpioThermometer) Update() error {
dev/MillisecondFloat)
return fmt.Errorf("could not update temperature successfully")
}
ohms := t.getOhms(time.Duration(int64(h.Median())))
ohms := t.getOhms(time.Duration(int64(avg)))
temp := t.getTemp(ohms)
Debug("Calculating temperature (%f) for %s: %f ohms, median %s", temp, t.name, ohms, time.Duration(int64(h.Median())))
t.accessory.TempSensor.CurrentTemperature.SetValue(temp)
Expand Down