110 lines
2.3 KiB
Go
110 lines
2.3 KiB
Go
package temper
|
|
|
|
import (
|
|
"encoding/hex"
|
|
"os"
|
|
"strconv"
|
|
"sync"
|
|
)
|
|
|
|
type Temper struct {
|
|
descriptor string
|
|
reader *os.File
|
|
writer *os.File
|
|
lock sync.Mutex
|
|
}
|
|
|
|
type reading struct {
|
|
value float32
|
|
error error
|
|
}
|
|
|
|
// Open a new Temper Device
|
|
//
|
|
// It is the caller's responsibility to call Close()
|
|
// to prevent a file descriptor leak
|
|
func New(descriptor string) (*Temper, error) {
|
|
if _, statErr := os.Stat(descriptor); statErr != nil {
|
|
return &Temper{}, statErr
|
|
}
|
|
r, readErr := os.Open(descriptor)
|
|
if readErr != nil {
|
|
return &Temper{}, readErr
|
|
}
|
|
w, writeErr := os.OpenFile(descriptor,
|
|
os.O_APPEND|os.O_WRONLY, os.ModeDevice)
|
|
if writeErr != nil {
|
|
r.Close()
|
|
return &Temper{}, writeErr
|
|
}
|
|
t := Temper{reader: r, writer: w, descriptor: descriptor}
|
|
return &t, nil
|
|
}
|
|
|
|
func (t *Temper) Descriptor() string {
|
|
return t.descriptor
|
|
}
|
|
|
|
func (t *Temper) String() string {
|
|
return t.Descriptor()
|
|
}
|
|
|
|
// Close the file descriptors for the Temper Device
|
|
func (t *Temper) Close() error {
|
|
t.lock.Lock()
|
|
defer t.lock.Unlock()
|
|
rErr := t.reader.Close()
|
|
wErr := t.writer.Close()
|
|
if rErr != nil {
|
|
return rErr
|
|
}
|
|
return wErr
|
|
}
|
|
|
|
// Read the internal sensor temperature in Celcius
|
|
func (t *Temper) ReadC() (float32, error) {
|
|
t.lock.Lock()
|
|
defer t.lock.Unlock()
|
|
tempChan := make(chan reading)
|
|
go func() {
|
|
// prepare a buffer and get ready to read
|
|
// from the temper hid device
|
|
response := make([]byte, 8)
|
|
_, err := t.reader.Read(response)
|
|
if err != nil {
|
|
tempChan <- reading{0, err}
|
|
return
|
|
}
|
|
// interpret the bytes as hex
|
|
hexStr := hex.EncodeToString(response)
|
|
// extract the temperature fields from the string
|
|
temp := hexStr[4:8]
|
|
// convert the hex ints to an integer
|
|
tempInt, err := strconv.ParseInt(temp, 16, 64)
|
|
if err != nil {
|
|
tempChan <- reading{0, err}
|
|
return
|
|
}
|
|
// divide the result by 100 and send to chan
|
|
float := float32(tempInt) / 100
|
|
tempChan <- reading{error: nil, value: float}
|
|
}()
|
|
// send magic byte sequence to request a temperature reading
|
|
_, err := t.writer.Write([]byte{0, 1, 128, 51, 1, 0, 0, 0, 0})
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
read := <-tempChan
|
|
return read.value, read.error
|
|
}
|
|
|
|
// Read the internal sensor temperature in Fahrenheit
|
|
func (t *Temper) ReadF() (float32, error) {
|
|
c, err := t.ReadC()
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
f := c*9.0/5.0 + 32.0
|
|
return f, err
|
|
}
|