Skip to content

Commit

Permalink
sysfs: implement SenseContinuous in ThermalSensor (google#353)
Browse files Browse the repository at this point in the history
Add a test for SenseContinuous
  • Loading branch information
davidsansome authored and maruel committed Dec 29, 2018
1 parent ef08175 commit e1a373f
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 7 deletions.
33 changes: 32 additions & 1 deletion cmd/thermal/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import (
)

func mainImpl() error {
dev := flag.String("dev", "", "Read only the device with this name. If not specified, read all devices found")
interval := flag.Duration("interval", 0, "Poll continuously with the given interval")
verbose := flag.Bool("v", false, "verbose mode")
flag.Parse()
if !*verbose {
Expand All @@ -28,11 +30,40 @@ func mainImpl() error {
if flag.NArg() != 0 {
return errors.New("unexpected argument, try -help")
}
if *interval != 0 && *dev == "" {
return errors.New("-dev is required when -interval is used")
}

if _, err := host.Init(); err != nil {
return err
}
for _, t := range sysfs.ThermalSensors {

// Find the named device if provided, otherwise use all devices.
var sensors []*sysfs.ThermalSensor
if *dev == "" {
sensors = sysfs.ThermalSensors
} else {
t, err := sysfs.ThermalSensorByName(*dev)
if err != nil {
return err
}
sensors = []*sysfs.ThermalSensor{t}
}

// Read continuously if an interval was provided.
if *interval != 0 {
t := sensors[0] // There is exactly 1 device, enforced above.
ch, err := t.SenseContinuous(*interval)
if err != nil {
return err
}
for {
e := <-ch
fmt.Printf("%s: %s: %s\n", t, t.Type(), e.Temperature)
}
}

for _, t := range sensors {
e := physic.Env{}
if err := t.Sense(&e); err != nil {
return err
Expand Down
39 changes: 36 additions & 3 deletions host/sysfs/thermal_sensor.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,22 @@ type ThermalSensor struct {
nameType string
f fileIO
precision physic.Temperature

done chan struct{}
}

func (t *ThermalSensor) String() string {
return t.name
}

// Halt implements conn.Resource. It is a noop.
// Halt stops a continuous sense that was started with SenseContinuous.
func (t *ThermalSensor) Halt() error {
t.mu.Lock()
defer t.mu.Unlock()
if t.done != nil {
close(t.done)
t.done = nil
}
return nil
}

Expand Down Expand Up @@ -126,8 +134,33 @@ func (t *ThermalSensor) Sense(e *physic.Env) error {

// SenseContinuous implements physic.SenseEnv.
func (t *ThermalSensor) SenseContinuous(interval time.Duration) (<-chan physic.Env, error) {
// TODO(maruel): Manually poll in a loop via time.NewTicker.
return nil, errors.New("sysfs-thermal: not implemented")
t.mu.Lock()
defer t.mu.Unlock()
if t.done != nil {
return nil, nil
}
done := make(chan struct{})
ret := make(chan physic.Env)
ticker := time.NewTicker(interval)

go func() {
defer ticker.Stop()
for {
select {
case <-done:
close(ret)
return
case <-ticker.C:
var e physic.Env
if err := t.Sense(&e); err == nil {
ret <- e
}
}
}
}()

t.done = done
return ret, nil
}

// Precision implements physic.SenseEnv.
Expand Down
42 changes: 39 additions & 3 deletions host/sysfs/thermal_sensor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,6 @@ func TestThermalSensor_fail(t *testing.T) {
if err := d.Sense(&e); err == nil || err.Error() != "sysfs-thermal: file I/O is inhibited" {
t.Fatal("should have failed")
}
if _, err := d.SenseContinuous(time.Second); err == nil || err.Error() != "sysfs-thermal: not implemented" {
t.Fatal(err)
}
}

func TestThermalSensor_Type_success(t *testing.T) {
Expand Down Expand Up @@ -281,6 +278,45 @@ func TestThermalSensor_Precision_MilliKelvin(t *testing.T) {
}
}

func TestThermalSensor_SenseContinuous_success(t *testing.T) {
defer resetThermal()
fileIOOpen = func(path string, flag int) (fileIO, error) {
if flag != os.O_RDONLY {
t.Fatal(flag)
}
switch path {
case "//\x00/temp":
return &fileRead{t: t, ops: [][]byte{
[]byte("42\n"),
[]byte("43\n"),
[]byte("44\n"),
[]byte("45\n"), // In case there's a read after the test finishes.
}}, nil
default:
t.Fatalf("unknown %q", path)
return nil, errors.New("unknown file")
}
}
d := ThermalSensor{name: "cpu", root: "//\000/", sensorFilename: "temp"}
ch, err := d.SenseContinuous(time.Nanosecond)
if err != nil {
t.Fatal(err)
}
defer d.Halt()
e := <-ch
if e.Temperature != 42*physic.Celsius+physic.ZeroCelsius {
t.Fatal(e.Temperature)
}
e = <-ch
if e.Temperature != 43*physic.Celsius+physic.ZeroCelsius {
t.Fatal(e.Temperature)
}
e = <-ch
if e.Temperature != 44*physic.Celsius+physic.ZeroCelsius {
t.Fatal(e.Temperature)
}
}

func TestThermalSensorDriver(t *testing.T) {
defer resetThermal()

Expand Down

0 comments on commit e1a373f

Please sign in to comment.