fermentord/pkg/temperature/ds18b20.go

112 lines
1.9 KiB
Go

package temperature
import (
"context"
"errors"
"io/ioutil"
"strconv"
"strings"
"sync"
"time"
"git.joco.dk/sng/fermentord/internal/metrics"
"github.com/rs/zerolog/log"
)
var (
ErrReadSensor = errors.New("Failed to read sensor temperature")
C chan *TemperatureReading
sensors []string
mutex *sync.Mutex
ticker *time.Ticker
)
func Initialize(readingInterval time.Duration) {
C = make(chan *TemperatureReading)
sensors = make([]string, 0)
mutex = &sync.Mutex{}
ticker = time.NewTicker(readingInterval)
}
func SetSensors(newSensors []string) {
mutex.Lock()
sensors = newSensors
mutex.Unlock()
}
func Serve(ctx context.Context, wg *sync.WaitGroup) {
defer wg.Done()
for {
select {
case <-ticker.C:
readSensors()
case <-ctx.Done():
ticker.Stop()
return
}
}
}
func readSensors() {
mutex.Lock()
defer mutex.Unlock()
for _, sensor := range sensors {
start := time.Now()
t, err := read(sensor)
dur := time.Since(start).Seconds()
if err != nil {
log.Error().
Err(err).
Str("sensor", sensor).
Msg("Error reading temperature sensor.")
}
metrics.TemperatureSensorReadingDegreesCelcius.
WithLabelValues("sensor", sensor).
Set(float64(t))
metrics.TemperatureSensorReadingDurationSeconds.
WithLabelValues("sensor", sensor).
Observe(dur)
C <- &TemperatureReading{
Time: time.Now(),
Sensor: sensor,
MilliDegrees: t,
}
}
}
// read returns the temperature of the specified sensor in millidegrees celcius.
func read(sensor string) (int64, error) {
path := "/sys/bus/w1/devices/" + sensor + "/w1_slave"
data, err := ioutil.ReadFile(path)
if err != nil {
return 0.0, err
}
raw := string(data)
if !strings.Contains(raw, " YES") {
return 0.0, ErrReadSensor
}
i := strings.LastIndex(raw, "t=")
if i == -1 {
return 0.0, ErrReadSensor
}
c, err := strconv.ParseInt(raw[i+2:len(raw)-1], 10, 64)
if err != nil {
return 0.0, err
}
return c, nil
}