New mechanism
This commit is contained in:
@@ -1,62 +1,109 @@
|
||||
package temper
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/google/gousb"
|
||||
"encoding/hex"
|
||||
"os"
|
||||
"strconv"
|
||||
"sync"
|
||||
)
|
||||
|
||||
func GetTemperature() (float64, error) {
|
||||
ctx := gousb.NewContext()
|
||||
defer ctx.Close()
|
||||
|
||||
vid, pid := gousb.ID(0x0c45), gousb.ID(0x7401)
|
||||
devs, err := ctx.OpenDevices(func(desc *gousb.DeviceDesc) bool {
|
||||
return desc.Vendor == vid && desc.Product == pid
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if len(devs) == 0 {
|
||||
return 0, fmt.Errorf("no devices found matching VID %s and PID %s", vid, pid)
|
||||
}
|
||||
|
||||
devs[0].SetAutoDetach(true)
|
||||
|
||||
for _, d := range devs {
|
||||
defer d.Close()
|
||||
}
|
||||
|
||||
cfg, err := devs[0].Config(1)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer cfg.Close()
|
||||
|
||||
intf, err := cfg.Interface(1, 0)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer intf.Close()
|
||||
|
||||
epIn, err := intf.InEndpoint(0x82)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
_, err = devs[0].Control(
|
||||
0x21, 0x09, 0x0200, 0x01, []byte{0x01, 0x80, 0x33, 0x01, 0x00, 0x00, 0x00, 0x00},
|
||||
)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
buf := make([]byte, 8)
|
||||
if _, err = epIn.Read(buf); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return float64(buf[2]) + float64(buf[3])/256, nil
|
||||
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
|
||||
}
|
||||
|
Reference in New Issue
Block a user