120 lines
2 KiB
Go
120 lines
2 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"
|
||
|
)
|
||
|
|
||
|
type TemperatureReading struct {
|
||
|
Sensor string
|
||
|
Time time.Time
|
||
|
Value int64
|
||
|
}
|
||
|
|
||
|
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) {
|
||
|
wg.Add(1)
|
||
|
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,
|
||
|
Value: 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
|
||
|
}
|