forked from tburke/go-TEMPer
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathTemper.go
147 lines (117 loc) · 3.62 KB
/
Temper.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
package main
/*
* by Machete3000 (c) 2016 github.com/Machete3000
* based on kylelemons/gousb/lsusb/main.go Copyright 2013 Google Inc.
* based on Temper.go by Thomas Burke (c) 2015 ([email protected])
* based on pcsensor.c by Juan Carlos Perez (c) 2011 ([email protected])
* based on Temper.c by Robert Kavaler (c) 2009 (relavak.com)
*/
import (
"flag"
"log"
"fmt"
"github.com/truveris/gousb/usb"
"github.com/truveris/gousb/usbid"
)
var (
debug = flag.Int("debug", 0, "libusb debug level (0..3)")
)
func temperature() (float64, error) {
ctx := usb.NewContext()
defer ctx.Close()
devs, err := ctx.ListDevices(func(desc *usb.Descriptor) bool {
return desc.Vendor == 0x0c45 && desc.Product == 0x7401
})
defer func() {
for _, d := range devs {
d.Close()
}
}()
if err != nil {
log.Printf("ListDevices failed");
return 0.0, err
}
if len(devs) == 0 {
return 0.0, fmt.Errorf("No thermometers found.")
}
dev := devs[0]
if err = dev.DetachKernelDriver(0); err != nil {
// Keep going...
}
if err = dev.SetConfig(1); err != nil {
return 0.0, err
}
ep, err := dev.OpenEndpoint(1, 1, 0, 0x82)
if err != nil {
return 0.0, err
}
if _, err = dev.Control(0x21, 0x09, 0x0200, 0x01, []byte{0x01, 0x80, 0x33, 0x01, 0x00, 0x00, 0x00, 0x00}); err != nil {
return 0.0, err
}
buf := make([]byte, 8)
if _, err = ep.Read(buf); err != nil {
return 0.0, err
}
return float64(buf[2]) + float64(buf[3])/256, nil
}
func listDevices() {
flag.Parse()
// Only one context should be needed for an application. It should always be closed.
ctx := usb.NewContext()
defer ctx.Close()
// Debugging can be turned on; this shows some of the inner workings of the libusb package.
ctx.Debug(*debug)
// ListDevices is used to find the devices to open.
devs, err := ctx.ListDevices(func(desc *usb.Descriptor) bool {
// The usbid package can be used to print out human readable information.
fmt.Printf("%03d.%03d %s:%s %s\n", desc.Bus, desc.Address, desc.Vendor, desc.Product, usbid.Describe(desc))
fmt.Printf(" Protocol: %s\n", usbid.Classify(desc))
// The configurations can be examined from the Descriptor, though they can only
// be set once the device is opened. All configuration references must be closed,
// to free up the memory in libusb.
for _, cfg := range desc.Configs {
// This loop just uses more of the built-in and usbid pretty printing to list
// the USB devices.
fmt.Printf(" %s:\n", cfg)
for _, alt := range cfg.Interfaces {
fmt.Printf(" --------------\n")
for _, iface := range alt.Setups {
fmt.Printf(" %s\n", iface)
fmt.Printf(" %s\n", usbid.Classify(iface))
for _, end := range iface.Endpoints {
fmt.Printf(" %s\n", end)
}
}
}
fmt.Printf(" --------------\n")
}
// After inspecting the descriptor, return true or false depending on whether
// the device is "interesting" or not. Any descriptor for which true is returned
// opens a Device which is retuned in a slice (and must be subsequently closed).
return false
})
// All Devices returned from ListDevices must be closed.
defer func() {
for _, d := range devs {
d.Close()
}
}()
// ListDevices can occaionally fail, so be sure to check its return value.
if err != nil {
log.Fatalf("list: %s", err)
}
for _, dev := range devs {
// Once the device has been selected from ListDevices, it is opened
// and can be interacted with.
_ = dev
}
}
func main() {
//listDevices()
c, err := temperature()
if err == nil {
log.Printf("Temperature: %.2fF %.2fC\n", 9.0/5.0*c+32, c)
} else {
log.Fatalf("Failed: %s", err)
}
}