Skip to content

Commit

Permalink
gpio(adaptors): fix so now gpiodev is used as default
Browse files Browse the repository at this point in the history
  • Loading branch information
gen2thomas committed Jan 3, 2025
1 parent c1a11a6 commit b578374
Show file tree
Hide file tree
Showing 55 changed files with 1,266 additions and 661 deletions.
22 changes: 8 additions & 14 deletions api/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -401,24 +401,18 @@ func TestRobotDeviceEvent(t *testing.T) {
Event("TestEvent")

go func() {
time.Sleep(time.Millisecond * 5)
time.Sleep(time.Millisecond * 10) // wait some time, so select below is ready
a.manager.Robot("Robot1").
Device("Device1").(gobot.Eventer).Publish(event, "event-data")
}()

done := false

for !done {
select {
case resp := <-respc:
reader := bufio.NewReader(resp.Body)
data, _ := reader.ReadString('\n')
assert.Equal(t, "data: \"event-data\"\n", data)
done = true
case <-time.After(200 * time.Millisecond):
t.Error("Not receiving data")
done = true
}
select {
case resp := <-respc:
reader := bufio.NewReader(resp.Body)
data, _ := reader.ReadString('\n')
assert.Equal(t, "data: \"event-data\"\n", data)
case <-time.After(50 * time.Millisecond):
t.Error("Not receiving data")
}

server.CloseClientConnections()
Expand Down
19 changes: 11 additions & 8 deletions drivers/aio/analog_sensor_driver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ func TestAnalogSensorRead_SetScaler(t *testing.T) {
got, err := d.Read()
// assert
require.NoError(t, err)
assert.InDelta(t, tc.want, got, 0.0)
assert.InDelta(t, tc.want, got, 1.0e-14)
})
}
}
Expand All @@ -157,7 +157,7 @@ func TestAnalogSensor_WithSensorCyclicRead(t *testing.T) {
semData := make(chan bool)
semDone := make(chan bool)
nextVal := make(chan int)
readTimeout := 1 * time.Second
readTimeout := time.Second
a.analogReadFunc = func() (int, error) {
val := 100
var err error
Expand All @@ -172,23 +172,26 @@ func TestAnalogSensor_WithSensorCyclicRead(t *testing.T) {
}
}

// act (start cyclic reading)
require.NoError(t, d.Start())

// arrange: expect raw value to be received
_ = d.Once(d.Event(Data), func(data interface{}) {
_ = d.Once(Data, func(data interface{}) { // we can't use d.Event(Data) here, because not registered yet
assert.Equal(t, 100, data.(int))
semData <- true
})

// arrange: expect scaled value to be received
_ = d.Once(d.Event(Value), func(value interface{}) {
_ = d.Once(Value, func(value interface{}) { // we can't use d.Event(Value) here, because not registered yet
assert.InDelta(t, 10000.0, value.(float64), 0.0)
<-semData // wait for data is finished
semDone <- true
nextVal <- -1 // arrange: error in read function
})

// wait some time to ensure the cyclic go routine is working
time.Sleep(15 * time.Millisecond)

// act (start cyclic reading)
require.NoError(t, d.Start())

// assert: both events within timeout
select {
case <-semDone:
Expand Down Expand Up @@ -227,7 +230,7 @@ func TestAnalogSensor_WithSensorCyclicRead(t *testing.T) {
require.Fail(t, "AnalogSensor Event for data should not published")
case <-semDone:
require.Fail(t, "AnalogSensor Event for value should not published")
case <-time.After(readTimeout):
case <-time.After(100 * time.Millisecond):
}
}

Expand Down
24 changes: 18 additions & 6 deletions drivers/aio/grove_temperature_sensor_driver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
package aio

import (
"fmt"
"strings"
"testing"
"time"
Expand Down Expand Up @@ -100,24 +99,37 @@ func TestGroveTemperatureSensor_publishesTemperatureInCelsius(t *testing.T) {
a := newAioTestAdaptor()
d := NewGroveTemperatureSensorDriver(a, "1", WithSensorCyclicRead(10*time.Millisecond))

// 584: 31.52208881030674, 585: 31.61532462352477
lastRawValue := 584
a.analogReadFunc = func() (int, error) {
return 585, nil
// ensure a changed value on each read, otherwise no event will be published
lastRawValue++
if lastRawValue > 585 {
lastRawValue = 584
}
return lastRawValue, nil
}

// act: start cyclic reading
require.NoError(t, d.Start())

// wait some time to ensure the cyclic go routine is working
time.Sleep(15 * time.Millisecond)

var eventValue float64
_ = d.Once(d.Event(Value), func(data interface{}) {
assert.Equal(t, "31.62", fmt.Sprintf("%.2f", data.(float64)))
eventValue = data.(float64)
sem <- true
})

// assert: value was published
// assert: value was published and is in expected delta
select {
case <-sem:
case <-time.After(1 * time.Second):
require.NoError(t, d.Halt())
case <-time.After(100 * time.Millisecond):
require.Fail(t, "Grove Temperature Sensor Event \"Value\" was not published")
}

assert.InDelta(t, 31.61532462352477, d.Temperature(), 0.0)
assert.InDelta(t, eventValue, d.Temperature(), 0.0)
assert.InDelta(t, 31.61532462352477, d.Temperature(), 31.61532462352477-31.52208881030674)
}
29 changes: 22 additions & 7 deletions drivers/aio/temperature_sensor_driver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package aio

import (
"errors"
"fmt"
"strings"
"testing"
"time"
Expand Down Expand Up @@ -123,7 +122,7 @@ func TestTemperatureSensorDriver_LinearScaler(t *testing.T) {
got, err := d.Read()
// assert
require.NoError(t, err)
assert.InDelta(t, tc.want, got, 0.0)
assert.InDelta(t, tc.want, got, 1.0e-14)
})
}
}
Expand All @@ -136,23 +135,39 @@ func TestTemperatureSensorWithSensorCyclicRead_PublishesTemperatureInCelsius(t *
ntc := TemperatureSensorNtcConf{TC0: 25, R0: 10000.0, B: 3975} // Ohm, R25=10k
d.SetNtcScaler(1023, 10000, false, ntc) // Ohm, reference value: 1023, series R: 10k

// 584: 31.52208881030674, 585: 31.61532462352477
lastRawValue := 585
a.analogReadFunc = func() (int, error) {
return 585, nil
// ensure a changed value on each read, otherwise no event will be published
lastRawValue++
if lastRawValue > 585 {
lastRawValue = 584
}
return lastRawValue, nil
}

// act: start cyclic reading
require.NoError(t, d.Start())

// wait some time to ensure the cyclic go routine is working
time.Sleep(15 * time.Millisecond)

var eventValue float64
_ = d.Once(d.Event(Value), func(data interface{}) {
assert.Equal(t, "31.62", fmt.Sprintf("%.2f", data.(float64)))
eventValue = data.(float64)
sem <- true
})

// assert: value was published and is in expected delta
select {
case <-sem:
case <-time.After(1 * time.Second):
require.Fail(t, " Temperature Sensor Event \"Data\" was not published")
require.NoError(t, d.Halt())
case <-time.After(100 * time.Millisecond):
require.Fail(t, "Grove Temperature Sensor Event \"Value\" was not published")
}

assert.InDelta(t, 31.61532462352477, d.Value(), 0.0)
assert.InDelta(t, eventValue, d.Temperature(), 0.0)
assert.InDelta(t, 31.61532462352477, d.Value(), 31.61532462352477-31.52208881030674)
}

func TestTemperatureSensorWithSensorCyclicRead_PublishesError(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion drivers/i2c/mpl115a2_driver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ func TestMPL115A2ReadData(t *testing.T) {
assert.Equal(t, uint8(0x12), a.written[3])
assert.Equal(t, uint8(0x00), a.written[4])
assert.Equal(t, uint8(0x00), a.written[5])
assert.InDelta(t, float32(96.585915), press, 0.0)
assert.InDelta(t, float32(96.585915), press, 1.0e-5)
assert.InDelta(t, float32(23.317757), temp, 0.0)
}

Expand Down
2 changes: 1 addition & 1 deletion drivers/i2c/sht2x_driver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ func TestSHT2xMeasurements(t *testing.T) {
_ = d.Start()
temp, err := d.Temperature()
require.NoError(t, err)
assert.InDelta(t, float32(18.809052), temp, 0.0)
assert.InDelta(t, float32(18.809052), temp, 1.0e-5)
hum, err := d.Humidity()
require.NoError(t, err)
assert.InDelta(t, float32(40.279907), hum, 0.0)
Expand Down
6 changes: 3 additions & 3 deletions platforms/adaptors/analogpinsadaptor.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"gobot.io/x/gobot/v2/system"
)

type analogPinTranslator func(pin string) (path string, r, w bool, bufLen uint16, err error)
type analogPinTranslator func(pin string) (path string, w bool, readBufLen uint16, err error)

// AnalogPinsAdaptor is a adaptor for analog pins, normally used for composition in platforms.
// It is also usable for general sysfs access.
Expand Down Expand Up @@ -83,11 +83,11 @@ func (a *AnalogPinsAdaptor) analogPin(id string) (gobot.AnalogPinner, error) {
pin := a.pins[id]

if pin == nil {
path, r, w, bufLen, err := a.translate(id)
path, w, readBufLen, err := a.translate(id)
if err != nil {
return nil, err
}
pin = a.sys.NewAnalogPin(path, r, w, bufLen)
pin = a.sys.NewAnalogPin(path, w, readBufLen)
a.pins[id] = pin
}

Expand Down
14 changes: 7 additions & 7 deletions platforms/adaptors/analogpinsadaptor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,23 +40,23 @@ func initTestAnalogPinsAdaptorWithMockedFilesystem(mockPaths []string) (*AnalogP
return a, fs
}

func testAnalogPinTranslator(id string) (string, bool, bool, uint16, error) {
func testAnalogPinTranslator(id string) (string, bool, uint16, error) {
switch id {
case "read":
return analogReadPath, true, false, 10, nil
return analogReadPath, false, 10, nil
case "write":
return analogWritePath, false, true, 11, nil
return analogWritePath, true, 0, nil
case "read/write":
return analogReadWritePath, true, true, 12, nil
return analogReadWritePath, true, 12, nil
case "read/write_string":
return analogReadWriteStringPath, true, true, 13, nil
return analogReadWriteStringPath, true, 13, nil
}

return "", false, false, 0, fmt.Errorf("'%s' is not a valid id of an analog pin", id)
return "", false, 0, fmt.Errorf("'%s' is not a valid id of an analog pin", id)
}

func TestAnalogPinsConnect(t *testing.T) {
translate := func(id string) (path string, r, w bool, bufLen uint16, err error) { return }
translate := func(id string) (path string, w bool, bufLen uint16, err error) { return }
a := NewAnalogPinsAdaptor(system.NewAccesser(), translate)
assert.Equal(t, (map[string]gobot.AnalogPinner)(nil), a.pins)

Expand Down
17 changes: 8 additions & 9 deletions platforms/adaptors/analogpintranslator.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,9 @@ import (
)

type AnalogPinDefinition struct {
Path string
R bool // readable
W bool // writable
BufLen uint16
Path string
W bool // writable
ReadBufLen uint16 // readable if buffer > 0
}

type AnalogPinDefinitions map[string]AnalogPinDefinition
Expand All @@ -26,20 +25,20 @@ func NewAnalogPinTranslator(sys *system.Accesser, pinDefinitions AnalogPinDefini
}

// Translate returns the sysfs path for the given id.
func (pt *AnalogPinTranslator) Translate(id string) (string, bool, bool, uint16, error) {
func (pt *AnalogPinTranslator) Translate(id string) (string, bool, uint16, error) {
pinInfo, ok := pt.pinDefinitions[id]
if !ok {
return "", false, false, 0, fmt.Errorf("'%s' is not a valid id for an analog pin", id)
return "", false, 0, fmt.Errorf("'%s' is not a valid id for an analog pin", id)
}

path := pinInfo.Path
info, err := pt.sys.Stat(path)
if err != nil {
return "", false, false, 0, fmt.Errorf("Error (%v) on access '%s'", err, path)
return "", false, 0, fmt.Errorf("Error (%v) on access '%s'", err, path)
}
if info.IsDir() {
return "", false, false, 0, fmt.Errorf("The item '%s' is a directory, which is not expected", path)
return "", false, 0, fmt.Errorf("The item '%s' is a directory, which is not expected", path)
}

return path, pinInfo.R, pinInfo.W, pinInfo.BufLen, nil
return path, pinInfo.W, pinInfo.ReadBufLen, nil
}
30 changes: 13 additions & 17 deletions platforms/adaptors/analogpintranslator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,31 +23,28 @@ func TestNewAnalogPinTranslator(t *testing.T) {

func TestAnalogPinTranslatorTranslate(t *testing.T) {
pinDefinitions := AnalogPinDefinitions{
"thermal_zone0": {Path: "/sys/class/thermal/thermal_zone0/temp", R: true, W: false, BufLen: 7},
"thermal_zone1": {Path: "/sys/class/thermal/thermal_zone1/temp", R: true, W: false, BufLen: 7},
"thermal_zone0": {Path: "/sys/class/thermal/thermal_zone0/temp", W: false, ReadBufLen: 7},
"thermal_zone1": {Path: "/sys/class/thermal/thermal_zone1/temp", W: false, ReadBufLen: 7},
}
mockedPaths := []string{
"/sys/class/thermal/thermal_zone0/temp",
"/sys/class/thermal/thermal_zone1/temp",
}
tests := map[string]struct {
id string
wantPath string
wantReadable bool
wantBufLen uint16
wantErr string
id string
wantPath string
wantBufLen uint16
wantErr string
}{
"translate_thermal_zone0": {
id: "thermal_zone0",
wantPath: "/sys/class/thermal/thermal_zone0/temp",
wantReadable: true,
wantBufLen: 7,
id: "thermal_zone0",
wantPath: "/sys/class/thermal/thermal_zone0/temp",
wantBufLen: 7,
},
"translate_thermal_zone1": {
id: "thermal_zone1",
wantPath: "/sys/class/thermal/thermal_zone1/temp",
wantReadable: true,
wantBufLen: 7,
id: "thermal_zone1",
wantPath: "/sys/class/thermal/thermal_zone1/temp",
wantBufLen: 7,
},
"unknown_id": {
id: "99",
Expand All @@ -61,15 +58,14 @@ func TestAnalogPinTranslatorTranslate(t *testing.T) {
_ = sys.UseMockFilesystem(mockedPaths)
pt := NewAnalogPinTranslator(sys, pinDefinitions)
// act
path, r, w, buf, err := pt.Translate(tc.id)
path, w, buf, err := pt.Translate(tc.id)
// assert
if tc.wantErr != "" {
require.EqualError(t, err, tc.wantErr)
} else {
require.NoError(t, err)
}
assert.Equal(t, tc.wantPath, path)
assert.Equal(t, tc.wantReadable, r)
assert.False(t, w)
assert.Equal(t, tc.wantBufLen, buf)
})
Expand Down
Loading

0 comments on commit b578374

Please sign in to comment.