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 }