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

130 lines
3.2 KiB
Go

package main
import (
"errors"
"log"
"os"
"sync"
"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 invert is false, the pin will be high turned on, and low when turned off.
func SetPinState(pin rpio.Pin, on bool, invert bool) {
switch {
case on && !invert:
pin.High()
case on && invert:
pin.Low()
case !on && invert:
pin.High()
default:
pin.Low()
}
}
// GetPinState will return true if the pin is on.
// If invert is false, the pin will be on when high.
func GetPinState(pin rpio.Pin, invert bool) bool {
switch pin.Read() {
case rpio.High:
return !invert
default:
return invert
}
}
// RunThermostat monitors the temperature of the supplied sensor and does its best to keep it at the desired state.
func RunThermostat(sensor Sensor, sig chan os.Signal, wg *sync.WaitGroup) {
var s State
s.Changed = time.Now()
cpin := rpio.Pin(sensor.CoolGPIO)
cpin.Output()
hpin := rpio.Pin(sensor.HeatGPIO)
hpin.Output()
SetPinState(cpin, false, sensor.CoolInvert)
SetPinState(hpin, false, sensor.HeatInvert)
run := true
go func() {
<-sig
run = false
}()
for run {
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.HeatInvert):
SetPinState(hpin, false, sensor.HeatInvert)
log.Printf("%s Turned off heat", sensor.Alias)
s.Changed = time.Now()
case t > sensor.HighTemp && min > sensor.CoolMinutes:
SetPinState(cpin, true, sensor.CoolInvert)
log.Printf("%s Turned on cool", sensor.Alias)
s.Changed = time.Now()
case t > sensor.HighTemp:
break
case t < sensor.LowTemp && GetPinState(cpin, sensor.CoolInvert):
SetPinState(cpin, false, sensor.CoolInvert)
log.Printf("%s Turned off cool", sensor.Alias)
s.Changed = time.Now()
case t < sensor.LowTemp && min > sensor.HeatMinutes:
SetPinState(hpin, true, sensor.HeatInvert)
log.Printf("%s Turned on heat", sensor.Alias)
s.Changed = time.Now()
case t < sensor.LowTemp:
break
default: // Turn off both switches
SetPinState(cpin, false, sensor.CoolInvert)
SetPinState(hpin, false, sensor.HeatInvert)
}
s.Temp = t
//s.Cooling = GetPinState(cpin, sensor.CoolInvert)
//s.Heating = GetPinState(hpin, sensor.HeatInvert)
log.Printf("%s Temp: %.2f, Cooling: %t, Heating: %t, Duration: %.1f", sensor.Alias, s.Temp, s.Cooling, s.Heating, min)
}
SetPinState(cpin, false, sensor.CoolInvert)
SetPinState(hpin, false, sensor.HeatInvert)
wg.Done()
}