1
0
Fork 0
mirror of https://github.com/shouptech/tempgopher.git synced 2026-02-03 08:39:43 +00:00
tempgopher/run.go

107 lines
2.6 KiB
Go

package main
import (
"errors"
"log"
"time"
"github.com/stianeikeland/go-rpio"
"github.com/yryz/ds18b20"
)
// State represents the current state of the thermostat
type State struct {
Temp float64
Cooling bool
Heating bool
Changed time.Time
}
// ReadTemperature will return the current temperature (in degrees celsius) of a specific sensor.
func ReadTemperature(id string) (float64, error) {
sensors, err := ds18b20.Sensors()
if err != nil {
return 0.0, err
}
for _, sensor := range sensors {
if sensor != id {
continue
}
return ds18b20.Temperature(sensor)
}
return 0.0, errors.New("Sensor not found")
}
// SetPinState is used to turn a pin on or off.
// If pullup is true, the pin will be pulled up when turned on, and pulled down when turned off.
func SetPinState(pin rpio.Pin, on bool, pullup bool) {
switch {
case on && pullup:
pin.PullUp()
case on && !pullup:
pin.PullDown()
case !on && !pullup:
pin.PullUp()
default:
pin.PullDown()
}
}
// GetPinState will return true if the pin is on.
// If pullup is true, the pin will be on when pulled up.
func GetPinState(pin rpio.Pin, pullup bool) bool {
switch pin.Read() {
case rpio.High:
return pullup
default:
return !pullup
}
}
// RunThermostat monitors the temperature of the supplied sensor and does its best to keep it at the desired state.
func RunThermostat(sensor Sensor) {
var s State
s.Changed = time.Now()
cpin := rpio.Pin(sensor.CoolGPIO)
cpin.Output()
hpin := rpio.Pin(sensor.HeatGPIO)
hpin.Output()
for {
t, err := ReadTemperature(sensor.ID)
if err != nil {
log.Panicln(err)
}
min := time.Since(s.Changed).Minutes()
switch {
case t > sensor.HighTemp && t < sensor.HighTemp:
log.Panic("Invalid state! Temperature is too high AND too low!")
case t > sensor.HighTemp && GetPinState(hpin, sensor.HeatPullup):
SetPinState(hpin, false, sensor.HeatPullup)
case t > sensor.HighTemp && min > sensor.CoolMinutes:
SetPinState(cpin, true, sensor.CoolPullup)
case t > sensor.HighTemp:
break
case t < sensor.LowTemp && GetPinState(cpin, sensor.CoolPullup):
SetPinState(cpin, false, sensor.CoolPullup)
case t < sensor.LowTemp && min > sensor.HeatMinutes:
SetPinState(hpin, true, sensor.HeatPullup)
case t < sensor.LowTemp:
break
default: // Turn off both switches
SetPinState(cpin, false, sensor.CoolPullup)
SetPinState(hpin, false, sensor.HeatPullup)
}
s.Temp = t
s.Cooling = GetPinState(cpin, sensor.CoolPullup)
s.Heating = GetPinState(hpin, sensor.HeatPullup)
log.Printf("Temp: %.2f, Cooling: %t, Heating: %t, Changed: %s", s.Temp, s.Cooling, s.Heating, s.Changed)
}
}