From c18663897365c614d61fde7fd16051146e318efc Mon Sep 17 00:00:00 2001 From: deadprogram Date: Tue, 20 Dec 2016 13:25:22 +0100 Subject: [PATCH] aio: separate analog drivers from gpio drivers Signed-off-by: deadprogram --- Makefile | 2 +- ci/travis.sh | 2 +- drivers/aio/LICENSE | 13 ++ drivers/aio/README.md | 21 ++++ drivers/aio/aio.go | 28 +++++ drivers/{gpio => aio}/analog_sensor_driver.go | 2 +- .../analog_sensor_driver_test.go | 10 +- drivers/aio/direct_pin_driver.go | 60 +++++++++ drivers/aio/direct_pin_driver_test.go | 51 ++++++++ drivers/aio/doc.go | 11 ++ drivers/aio/grove_drivers.go | 94 ++++++++++++++ drivers/aio/grove_drivers_test.go | 119 ++++++++++++++++++ .../grove_temperature_sensor_driver.go | 2 +- .../grove_temperature_sensor_driver_test.go | 10 +- drivers/aio/helpers_test.go | 32 +++++ drivers/gpio/README.md | 6 - drivers/gpio/direct_pin_driver.go | 14 --- drivers/gpio/direct_pin_driver_test.go | 20 +-- drivers/gpio/doc.go | 2 +- drivers/gpio/grove_drivers.go | 89 ------------- drivers/gpio/grove_drivers_test.go | 40 ------ examples/edison_grove_light_sensor.go | 4 +- examples/edison_grove_piezo_vibration.go | 6 +- examples/edison_grove_rotary_sensor.go | 6 +- examples/edison_grove_sound_sensor.go | 6 +- examples/edison_grove_temperature_sensor.go | 4 +- ...edison_led_brightness_with_analog_input.go | 5 +- 27 files changed, 461 insertions(+), 198 deletions(-) create mode 100644 drivers/aio/LICENSE create mode 100644 drivers/aio/README.md create mode 100644 drivers/aio/aio.go rename drivers/{gpio => aio}/analog_sensor_driver.go (99%) rename drivers/{gpio => aio}/analog_sensor_driver_test.go (89%) create mode 100644 drivers/aio/direct_pin_driver.go create mode 100644 drivers/aio/direct_pin_driver_test.go create mode 100644 drivers/aio/doc.go create mode 100644 drivers/aio/grove_drivers.go create mode 100644 drivers/aio/grove_drivers_test.go rename drivers/{gpio => aio}/grove_temperature_sensor_driver.go (99%) rename drivers/{gpio => aio}/grove_temperature_sensor_driver_test.go (86%) create mode 100644 drivers/aio/helpers_test.go diff --git a/Makefile b/Makefile index bb2e6d2c9..c4d14e4b2 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -PACKAGES := gobot gobot/api gobot/drivers/gpio gobot/drivers/i2c gobot/platforms/firmata/client gobot/platforms/intel-iot/edison gobot/platforms/intel-iot/joule gobot/platforms/parrot/ardrone gobot/platforms/parrot/bebop gobot/platforms/parrot/minidrone gobot/platforms/sphero/ollie gobot/platforms/sphero/bb8 gobot/sysfs $(shell ls ./platforms | sed -e 's/^/gobot\/platforms\//') +PACKAGES := gobot gobot/api gobot/drivers/gpio gobot/drivers/aio gobot/drivers/i2c gobot/platforms/firmata/client gobot/platforms/intel-iot/edison gobot/platforms/intel-iot/joule gobot/platforms/parrot/ardrone gobot/platforms/parrot/bebop gobot/platforms/parrot/minidrone gobot/platforms/sphero/ollie gobot/platforms/sphero/bb8 gobot/sysfs $(shell ls ./platforms | sed -e 's/^/gobot\/platforms\//') .PHONY: test cover robeaux examples test: diff --git a/ci/travis.sh b/ci/travis.sh index 59df84d8e..2b2d51f9a 100755 --- a/ci/travis.sh +++ b/ci/travis.sh @@ -1,5 +1,5 @@ #!/bin/bash -PACKAGES=('gobot' 'gobot/api' 'gobot/sysfs' 'gobot/drivers/gpio' 'gobot/drivers/i2c' 'gobot/platforms/firmata/client' 'gobot/platforms/intel-iot/edison' 'gobot/platforms/intel-iot/joule' 'gobot/platforms/parrot/ardrone' 'gobot/platforms/parrot/bebop' 'gobot/platforms/parrot/minidrone' 'gobot/platforms/sphero/ollie' 'gobot/platforms/sphero/bb8' $(ls ./platforms | sed -e 's/^/gobot\/platforms\//')) +PACKAGES=('gobot' 'gobot/api' 'gobot/sysfs' 'gobot/drivers/gpio' 'gobot/drivers/aio' 'gobot/drivers/i2c' 'gobot/platforms/firmata/client' 'gobot/platforms/intel-iot/edison' 'gobot/platforms/intel-iot/joule' 'gobot/platforms/parrot/ardrone' 'gobot/platforms/parrot/bebop' 'gobot/platforms/parrot/minidrone' 'gobot/platforms/sphero/ollie' 'gobot/platforms/sphero/bb8' $(ls ./platforms | sed -e 's/^/gobot\/platforms\//')) EXITCODE=0 echo "mode: set" > profile.cov diff --git a/drivers/aio/LICENSE b/drivers/aio/LICENSE new file mode 100644 index 000000000..6bd6ecf17 --- /dev/null +++ b/drivers/aio/LICENSE @@ -0,0 +1,13 @@ +Copyright (c) 2013-2016 The Hybrid Group + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/drivers/aio/README.md b/drivers/aio/README.md new file mode 100644 index 000000000..2f684f44f --- /dev/null +++ b/drivers/aio/README.md @@ -0,0 +1,21 @@ +# AIO + +This package provides drivers for [Analog Input/Output (AIO)]() devices. It is normally used by connecting an adaptor such as [firmata](https://gobot.io/x/gobot/platforms/firmata) that supports the needed interfaces for AIO devices. + +## Getting Started + +## Installing +``` +go get -d -u gobot.io/x/gobot/... +``` + +## Hardware Support +Gobot has a extensible system for connecting to hardware devices. The following AIO devices are currently supported: + - Analog Sensor + - Direct Pin + - Grove Light Sensor + - Grove Rotary Dial + - Grove Sound Sensor + - Grove Temperature Sensor + +More drivers are coming soon... diff --git a/drivers/aio/aio.go b/drivers/aio/aio.go new file mode 100644 index 000000000..7d340ccc4 --- /dev/null +++ b/drivers/aio/aio.go @@ -0,0 +1,28 @@ +package aio + +import ( + "errors" + + "gobot.io/x/gobot" +) + +var ( + // ErrAnalogReadUnsupported is error resulting when a driver attempts to use + // hardware capabilities which a connection does not support + ErrAnalogReadUnsupported = errors.New("AnalogRead is not supported by this platform") +) + +const ( + // Error event + Error = "error" + // Data event + Data = "data" + // Vibration event + Vibration = "vibration" +) + +// AnalogReader interface represents an Adaptor which has Analog capabilities +type AnalogReader interface { + gobot.Adaptor + AnalogRead(string) (val int, err error) +} diff --git a/drivers/gpio/analog_sensor_driver.go b/drivers/aio/analog_sensor_driver.go similarity index 99% rename from drivers/gpio/analog_sensor_driver.go rename to drivers/aio/analog_sensor_driver.go index 5b0fc4837..45729da95 100644 --- a/drivers/gpio/analog_sensor_driver.go +++ b/drivers/aio/analog_sensor_driver.go @@ -1,4 +1,4 @@ -package gpio +package aio import ( "time" diff --git a/drivers/gpio/analog_sensor_driver_test.go b/drivers/aio/analog_sensor_driver_test.go similarity index 89% rename from drivers/gpio/analog_sensor_driver_test.go rename to drivers/aio/analog_sensor_driver_test.go index 87681617b..b7042c69e 100644 --- a/drivers/gpio/analog_sensor_driver_test.go +++ b/drivers/aio/analog_sensor_driver_test.go @@ -1,4 +1,4 @@ -package gpio +package aio import ( "errors" @@ -12,12 +12,12 @@ import ( var _ gobot.Driver = (*AnalogSensorDriver)(nil) func TestAnalogSensorDriver(t *testing.T) { - d := NewAnalogSensorDriver(newGpioTestAdaptor(), "1") + d := NewAnalogSensorDriver(newAioTestAdaptor(), "1") gobottest.Refute(t, d.Connection(), nil) // default interval gobottest.Assert(t, d.interval, 10*time.Millisecond) - d = NewAnalogSensorDriver(newGpioTestAdaptor(), "42", 30*time.Second) + d = NewAnalogSensorDriver(newAioTestAdaptor(), "42", 30*time.Second) gobottest.Assert(t, d.Pin(), "42") gobottest.Assert(t, d.interval, 30*time.Second) @@ -34,7 +34,7 @@ func TestAnalogSensorDriver(t *testing.T) { func TestAnalogSensorDriverStart(t *testing.T) { sem := make(chan bool, 1) - d := NewAnalogSensorDriver(newGpioTestAdaptor(), "1") + d := NewAnalogSensorDriver(newAioTestAdaptor(), "1") gobottest.Assert(t, d.Start(), nil) @@ -94,7 +94,7 @@ func TestAnalogSensorDriverStart(t *testing.T) { } func TestAnalogSensorDriverHalt(t *testing.T) { - d := NewAnalogSensorDriver(newGpioTestAdaptor(), "1") + d := NewAnalogSensorDriver(newAioTestAdaptor(), "1") done := make(chan struct{}) go func() { <-d.halt diff --git a/drivers/aio/direct_pin_driver.go b/drivers/aio/direct_pin_driver.go new file mode 100644 index 000000000..83788b28e --- /dev/null +++ b/drivers/aio/direct_pin_driver.go @@ -0,0 +1,60 @@ +package aio + +import ( + "gobot.io/x/gobot" +) + +// DirectPinDriver represents a AIO pin +type DirectPinDriver struct { + name string + pin string + connection gobot.Connection + gobot.Commander +} + +// NewDirectPinDriver return a new DirectPinDriver given a Connection and pin. +// +// Adds the following API Command: +// "AnalogRead" - See DirectPinDriver.AnalogRead +func NewDirectPinDriver(a gobot.Connection, pin string) *DirectPinDriver { + d := &DirectPinDriver{ + name: "DirectPin", + connection: a, + pin: pin, + Commander: gobot.NewCommander(), + } + + d.AddCommand("AnalogRead", func(params map[string]interface{}) interface{} { + val, err := d.AnalogRead() + return map[string]interface{}{"val": val, "err": err} + }) + + return d +} + +// Name returns the DirectPinDrivers name +func (d *DirectPinDriver) Name() string { return d.name } + +// SetName sets the DirectPinDrivers name +func (d *DirectPinDriver) SetName(n string) { d.name = n } + +// Pin returns the DirectPinDrivers pin +func (d *DirectPinDriver) Pin() string { return d.pin } + +// Connection returns the DirectPinDrivers Connection +func (d *DirectPinDriver) Connection() gobot.Connection { return d.connection } + +// Start implements the Driver interface +func (d *DirectPinDriver) Start() (err error) { return } + +// Halt implements the Driver interface +func (d *DirectPinDriver) Halt() (err error) { return } + +// AnalogRead reads the current analog reading of the pin +func (d *DirectPinDriver) AnalogRead() (val int, err error) { + if reader, ok := d.Connection().(AnalogReader); ok { + return reader.AnalogRead(d.Pin()) + } + err = ErrAnalogReadUnsupported + return +} diff --git a/drivers/aio/direct_pin_driver_test.go b/drivers/aio/direct_pin_driver_test.go new file mode 100644 index 000000000..caef7f347 --- /dev/null +++ b/drivers/aio/direct_pin_driver_test.go @@ -0,0 +1,51 @@ +package aio + +import ( + "testing" + + "gobot.io/x/gobot" + "gobot.io/x/gobot/gobottest" +) + +var _ gobot.Driver = (*DirectPinDriver)(nil) + +func initTestDirectPinDriver(conn gobot.Connection) *DirectPinDriver { + testAdaptorAnalogRead = func() (val int, err error) { + val = 80 + return + } + return NewDirectPinDriver(conn, "1") +} + +func TestDirectPinDriver(t *testing.T) { + var ret map[string]interface{} + + d := initTestDirectPinDriver(newAioTestAdaptor()) + gobottest.Assert(t, d.Pin(), "1") + gobottest.Refute(t, d.Connection(), nil) + + ret = d.Command("AnalogRead")(nil).(map[string]interface{}) + + gobottest.Assert(t, ret["val"].(int), 80) + gobottest.Assert(t, ret["err"], nil) +} + +func TestDirectPinDriverStart(t *testing.T) { + d := initTestDirectPinDriver(newAioTestAdaptor()) + gobottest.Assert(t, d.Start(), nil) +} + +func TestDirectPinDriverHalt(t *testing.T) { + d := initTestDirectPinDriver(newAioTestAdaptor()) + gobottest.Assert(t, d.Halt(), nil) +} + +func TestDirectPinDriverAnalogRead(t *testing.T) { + d := initTestDirectPinDriver(newAioTestAdaptor()) + ret, err := d.AnalogRead() + gobottest.Assert(t, ret, 80) + + d = initTestDirectPinDriver(&aioTestBareAdaptor{}) + ret, err = d.AnalogRead() + gobottest.Assert(t, err, ErrAnalogReadUnsupported) +} diff --git a/drivers/aio/doc.go b/drivers/aio/doc.go new file mode 100644 index 000000000..a18c3dfee --- /dev/null +++ b/drivers/aio/doc.go @@ -0,0 +1,11 @@ +/* +Package aio provides Gobot drivers for Analog Input/Output devices. + +Installing: + + go get -d -u gobot.io/x/gobot/... + +For further information refer to gpio README: +https://gobot.io/x/gobot/blob/master/platforms/aio/README.md +*/ +package aio diff --git a/drivers/aio/grove_drivers.go b/drivers/aio/grove_drivers.go new file mode 100644 index 000000000..0d86ee6f1 --- /dev/null +++ b/drivers/aio/grove_drivers.go @@ -0,0 +1,94 @@ +package aio + +import ( + "time" +) + +// GroveRotaryDriver represents an analog rotary dial with a Grove connector +type GroveRotaryDriver struct { + *AnalogSensorDriver +} + +// NewGroveRotaryDriver returns a new GroveRotaryDriver with a polling interval of +// 10 Milliseconds given an AnalogReader and pin. +// +// Optionally accepts: +// time.Duration: Interval at which the AnalogSensor is polled for new information +// +// Adds the following API Commands: +// "Read" - See AnalogSensor.Read +func NewGroveRotaryDriver(a AnalogReader, pin string, v ...time.Duration) *GroveRotaryDriver { + return &GroveRotaryDriver{ + AnalogSensorDriver: NewAnalogSensorDriver(a, pin, v...), + } +} + +// GroveLightSensorDriver represents an analog light sensor +// with a Grove connector +type GroveLightSensorDriver struct { + *AnalogSensorDriver +} + +// NewGroveLightSensorDriver returns a new GroveLightSensorDriver with a polling interval of +// 10 Milliseconds given an AnalogReader and pin. +// +// Optionally accepts: +// time.Duration: Interval at which the AnalogSensor is polled for new information +// +// Adds the following API Commands: +// "Read" - See AnalogSensor.Read +func NewGroveLightSensorDriver(a AnalogReader, pin string, v ...time.Duration) *GroveLightSensorDriver { + return &GroveLightSensorDriver{ + AnalogSensorDriver: NewAnalogSensorDriver(a, pin, v...), + } +} + +// GrovePiezoVibrationSensorDriver represents an analog vibration sensor +// with a Grove connector +type GrovePiezoVibrationSensorDriver struct { + *AnalogSensorDriver +} + +// NewGrovePiezoVibrationSensorDriver returns a new GrovePiezoVibrationSensorDriver with a polling interval of +// 10 Milliseconds given an AnalogReader and pin. +// +// Optionally accepts: +// time.Duration: Interval at which the AnalogSensor is polled for new information +// +// Adds the following API Commands: +// "Read" - See AnalogSensor.Read +func NewGrovePiezoVibrationSensorDriver(a AnalogReader, pin string, v ...time.Duration) *GrovePiezoVibrationSensorDriver { + sensor := &GrovePiezoVibrationSensorDriver{ + AnalogSensorDriver: NewAnalogSensorDriver(a, pin, v...), + } + + sensor.AddEvent(Vibration) + + sensor.On(sensor.Event(Data), func(data interface{}) { + if data.(int) > 1000 { + sensor.Publish(sensor.Event(Vibration), data) + } + }) + + return sensor +} + +// GroveSoundSensorDriver represents a analog sound sensor +// with a Grove connector +type GroveSoundSensorDriver struct { + *AnalogSensorDriver +} + +// NewGroveSoundSensorDriver returns a new GroveSoundSensorDriver with a polling interval of +// 10 Milliseconds given an AnalogReader and pin. +// +// Optionally accepts: +// time.Duration: Interval at which the AnalogSensor is polled for new information +// +// Adds the following API Commands: +// "Read" - See AnalogSensor.Read +func NewGroveSoundSensorDriver(a AnalogReader, pin string, v ...time.Duration) *GroveSoundSensorDriver { + return &GroveSoundSensorDriver{ + AnalogSensorDriver: NewAnalogSensorDriver(a, pin, v...), + } +} diff --git a/drivers/aio/grove_drivers_test.go b/drivers/aio/grove_drivers_test.go new file mode 100644 index 000000000..11854dd69 --- /dev/null +++ b/drivers/aio/grove_drivers_test.go @@ -0,0 +1,119 @@ +package aio + +import ( + "errors" + "reflect" + "sync/atomic" + "testing" + "time" + + "gobot.io/x/gobot" + "gobot.io/x/gobot/gobottest" +) + +type DriverAndPinner interface { + gobot.Driver + gobot.Pinner +} + +type DriverAndEventer interface { + gobot.Driver + gobot.Eventer +} + +func TestDriverDefaults(t *testing.T) { + testAdaptor := newAioTestAdaptor() + pin := "456" + + drivers := []DriverAndPinner{ + NewGroveSoundSensorDriver(testAdaptor, pin), + NewGroveLightSensorDriver(testAdaptor, pin), + NewGrovePiezoVibrationSensorDriver(testAdaptor, pin), + NewGroveRotaryDriver(testAdaptor, pin), + } + + for _, driver := range drivers { + gobottest.Assert(t, driver.Connection(), testAdaptor) + gobottest.Assert(t, driver.Pin(), pin) + } +} + +func TestAnalogDriverHalt(t *testing.T) { + testAdaptor := newAioTestAdaptor() + pin := "456" + + drivers := []DriverAndEventer{ + NewGroveSoundSensorDriver(testAdaptor, pin), + NewGroveLightSensorDriver(testAdaptor, pin), + NewGrovePiezoVibrationSensorDriver(testAdaptor, pin), + NewGroveRotaryDriver(testAdaptor, pin), + } + + for _, driver := range drivers { + var callCount int32 + testAdaptorAnalogRead = func() (int, error) { + atomic.AddInt32(&callCount, 1) + return 42, nil + } + // Start the driver and allow for multiple digital reads + driver.Start() + time.Sleep(20 * time.Millisecond) + + driver.Halt() + lastCallCount := atomic.LoadInt32(&callCount) + // If driver was not halted, digital reads would still continue + time.Sleep(20 * time.Millisecond) + if atomic.LoadInt32(&callCount) != lastCallCount { + t.Errorf("AnalogRead was called after driver was halted") + } + } +} + +func TestDriverPublishesError(t *testing.T) { + testAdaptor := newAioTestAdaptor() + pin := "456" + + drivers := []DriverAndEventer{ + NewGroveSoundSensorDriver(testAdaptor, pin), + NewGroveLightSensorDriver(testAdaptor, pin), + NewGrovePiezoVibrationSensorDriver(testAdaptor, pin), + NewGroveRotaryDriver(testAdaptor, pin), + } + + for _, driver := range drivers { + sem := make(chan struct{}, 1) + // send error + returnErr := func() (val int, err error) { + err = errors.New("read error") + return + } + testAdaptorAnalogRead = returnErr + + gobottest.Assert(t, driver.Start(), nil) + + // expect error + driver.Once(driver.Event(Error), func(data interface{}) { + gobottest.Assert(t, data.(error).Error(), "read error") + close(sem) + }) + + select { + case <-sem: + case <-time.After(time.Second): + t.Errorf("%s Event \"Error\" was not published", getType(driver)) + } + + // Cleanup + driver.Halt() + } +} + +func getType(driver interface{}) string { + d := reflect.TypeOf(driver) + + if d.Kind() == reflect.Ptr { + return d.Elem().Name() + } + + return d.Name() +} diff --git a/drivers/gpio/grove_temperature_sensor_driver.go b/drivers/aio/grove_temperature_sensor_driver.go similarity index 99% rename from drivers/gpio/grove_temperature_sensor_driver.go rename to drivers/aio/grove_temperature_sensor_driver.go index d682b3158..445e5137c 100644 --- a/drivers/gpio/grove_temperature_sensor_driver.go +++ b/drivers/aio/grove_temperature_sensor_driver.go @@ -1,4 +1,4 @@ -package gpio +package aio import ( "math" diff --git a/drivers/gpio/grove_temperature_sensor_driver_test.go b/drivers/aio/grove_temperature_sensor_driver_test.go similarity index 86% rename from drivers/gpio/grove_temperature_sensor_driver_test.go rename to drivers/aio/grove_temperature_sensor_driver_test.go index 5b0644e43..d14b3315a 100644 --- a/drivers/gpio/grove_temperature_sensor_driver_test.go +++ b/drivers/aio/grove_temperature_sensor_driver_test.go @@ -1,4 +1,4 @@ -package gpio +package aio import ( "errors" @@ -13,7 +13,7 @@ import ( var _ gobot.Driver = (*GroveTemperatureSensorDriver)(nil) func TestGroveTemperatureSensorDriver(t *testing.T) { - testAdaptor := newGpioTestAdaptor() + testAdaptor := newAioTestAdaptor() d := NewGroveTemperatureSensorDriver(testAdaptor, "123") gobottest.Assert(t, d.Connection(), testAdaptor) gobottest.Assert(t, d.Pin(), "123") @@ -22,7 +22,7 @@ func TestGroveTemperatureSensorDriver(t *testing.T) { func TestGroveTempSensorPublishesTemperatureInCelsius(t *testing.T) { sem := make(chan bool, 1) - d := NewGroveTemperatureSensorDriver(newGpioTestAdaptor(), "1") + d := NewGroveTemperatureSensorDriver(newAioTestAdaptor(), "1") testAdaptorAnalogRead = func() (val int, err error) { val = 585 @@ -38,7 +38,7 @@ func TestGroveTempSensorPublishesTemperatureInCelsius(t *testing.T) { func TestGroveTempSensorPublishesError(t *testing.T) { sem := make(chan bool, 1) - d := NewGroveTemperatureSensorDriver(newGpioTestAdaptor(), "1") + d := NewGroveTemperatureSensorDriver(newAioTestAdaptor(), "1") // send error testAdaptorAnalogRead = func() (val int, err error) { @@ -62,7 +62,7 @@ func TestGroveTempSensorPublishesError(t *testing.T) { } func TestGroveTempSensorHalt(t *testing.T) { - d := NewGroveTemperatureSensorDriver(newGpioTestAdaptor(), "1") + d := NewGroveTemperatureSensorDriver(newAioTestAdaptor(), "1") done := make(chan struct{}) go func() { <-d.halt diff --git a/drivers/aio/helpers_test.go b/drivers/aio/helpers_test.go new file mode 100644 index 000000000..7b1d32ccd --- /dev/null +++ b/drivers/aio/helpers_test.go @@ -0,0 +1,32 @@ +package aio + +type aioTestBareAdaptor struct{} + +func (t *aioTestBareAdaptor) Connect() (err error) { return } +func (t *aioTestBareAdaptor) Finalize() (err error) { return } +func (t *aioTestBareAdaptor) Name() string { return "" } +func (t *aioTestBareAdaptor) SetName(n string) {} + +type aioTestAdaptor struct { + name string + port string +} + +var testAdaptorAnalogRead = func() (val int, err error) { + return 99, nil +} + +func (t *aioTestAdaptor) AnalogRead(string) (val int, err error) { + return testAdaptorAnalogRead() +} +func (t *aioTestAdaptor) Connect() (err error) { return } +func (t *aioTestAdaptor) Finalize() (err error) { return } +func (t *aioTestAdaptor) Name() string { return t.name } +func (t *aioTestAdaptor) SetName(n string) { t.name = n } +func (t *aioTestAdaptor) Port() string { return t.port } + +func newAioTestAdaptor() *aioTestAdaptor { + return &aioTestAdaptor{ + port: "/dev/null", + } +} diff --git a/drivers/gpio/README.md b/drivers/gpio/README.md index e8fb3268b..ac5311cd8 100644 --- a/drivers/gpio/README.md +++ b/drivers/gpio/README.md @@ -11,20 +11,14 @@ go get -d -u gobot.io/x/gobot/... ## Hardware Support Gobot has a extensible system for connecting to hardware devices. The following GPIO devices are currently supported: - - Analog Sensor - Button - Buzzer - Direct Pin - Grove Button - Grove Buzzer - Grove LED - - Grove Light Sensor - Grove Magnetic Switch - - Grove Piezo Vibration Sensor - Grove Relay - - Grove Rotary Dial - - Grove Sound Sensor - - Grove Temperature Sensor - Grove Touch Sensor - LED - Makey Button diff --git a/drivers/gpio/direct_pin_driver.go b/drivers/gpio/direct_pin_driver.go index 9a009ec0e..a3b379aec 100644 --- a/drivers/gpio/direct_pin_driver.go +++ b/drivers/gpio/direct_pin_driver.go @@ -19,7 +19,6 @@ type DirectPinDriver struct { // Adds the following API Commands: // "DigitalRead" - See DirectPinDriver.DigitalRead // "DigitalWrite" - See DirectPinDriver.DigitalWrite -// "AnalogRead" - See DirectPinDriver.AnalogRead // "AnalogWrite" - See DirectPinDriver.AnalogWrite // "PwmWrite" - See DirectPinDriver.PwmWrite // "ServoWrite" - See DirectPinDriver.ServoWrite @@ -39,10 +38,6 @@ func NewDirectPinDriver(a gobot.Connection, pin string) *DirectPinDriver { level, _ := strconv.Atoi(params["level"].(string)) return d.DigitalWrite(byte(level)) }) - d.AddCommand("AnalogRead", func(params map[string]interface{}) interface{} { - val, err := d.AnalogRead() - return map[string]interface{}{"val": val, "err": err} - }) d.AddCommand("PwmWrite", func(params map[string]interface{}) interface{} { level, _ := strconv.Atoi(params["level"].(string)) return d.PwmWrite(byte(level)) @@ -109,15 +104,6 @@ func (d *DirectPinDriver) DigitalWrite(level byte) (err error) { return } -// AnalogRead reads the current analog reading of the pin -func (d *DirectPinDriver) AnalogRead() (val int, err error) { - if reader, ok := d.Connection().(AnalogReader); ok { - return reader.AnalogRead(d.Pin()) - } - err = ErrAnalogReadUnsupported - return -} - // PwmWrite writes the 0-254 value to the specified pin func (d *DirectPinDriver) PwmWrite(level byte) (err error) { if writer, ok := d.Connection().(PwmWriter); ok { diff --git a/drivers/gpio/direct_pin_driver_test.go b/drivers/gpio/direct_pin_driver_test.go index b8ab9583b..b4fb595f0 100644 --- a/drivers/gpio/direct_pin_driver_test.go +++ b/drivers/gpio/direct_pin_driver_test.go @@ -18,10 +18,6 @@ func initTestDirectPinDriver(conn gobot.Connection) *DirectPinDriver { testAdaptorDigitalWrite = func() (err error) { return errors.New("write error") } - testAdaptorAnalogRead = func() (val int, err error) { - val = 80 - return - } testAdaptorPwmWrite = func() (err error) { return errors.New("write error") } @@ -47,11 +43,6 @@ func TestDirectPinDriver(t *testing.T) { err = d.Command("DigitalWrite")(map[string]interface{}{"level": "1"}) gobottest.Assert(t, err.(error), errors.New("write error")) - ret = d.Command("AnalogRead")(nil).(map[string]interface{}) - - gobottest.Assert(t, ret["val"].(int), 80) - gobottest.Assert(t, ret["err"], nil) - err = d.Command("PwmWrite")(map[string]interface{}{"level": "1"}) gobottest.Assert(t, err.(error), errors.New("write error")) @@ -103,16 +94,6 @@ func TestDirectPinDriverDigitalRead(t *testing.T) { gobottest.Assert(t, err, ErrDigitalReadUnsupported) } -func TestDirectPinDriverAnalogRead(t *testing.T) { - d := initTestDirectPinDriver(newGpioTestAdaptor()) - ret, err := d.AnalogRead() - gobottest.Assert(t, ret, 80) - - d = initTestDirectPinDriver(&gpioTestBareAdaptor{}) - ret, err = d.AnalogRead() - gobottest.Assert(t, err, ErrAnalogReadUnsupported) -} - func TestDirectPinDriverPwmWrite(t *testing.T) { d := initTestDirectPinDriver(newGpioTestAdaptor()) gobottest.Refute(t, d.PwmWrite(1), nil) @@ -120,6 +101,7 @@ func TestDirectPinDriverPwmWrite(t *testing.T) { d = initTestDirectPinDriver(&gpioTestBareAdaptor{}) gobottest.Assert(t, d.PwmWrite(1), ErrPwmWriteUnsupported) } + func TestDirectPinDriverDigitalWrie(t *testing.T) { d := initTestDirectPinDriver(newGpioTestAdaptor()) gobottest.Refute(t, d.ServoWrite(1), nil) diff --git a/drivers/gpio/doc.go b/drivers/gpio/doc.go index 441c9ed8c..a008a9220 100644 --- a/drivers/gpio/doc.go +++ b/drivers/gpio/doc.go @@ -3,7 +3,7 @@ Package gpio provides Gobot drivers for General Purpose Input/Output devices. Installing: - go get -d -u gobot.io/x/gobot/... && go install gobot.io/x/gobot/platforms/gpio + go get -d -u gobot.io/x/gobot/... For further information refer to gpio README: https://gobot.io/x/gobot/blob/master/platforms/gpio/README.md diff --git a/drivers/gpio/grove_drivers.go b/drivers/gpio/grove_drivers.go index 94c2d2c93..80f1ab377 100644 --- a/drivers/gpio/grove_drivers.go +++ b/drivers/gpio/grove_drivers.go @@ -21,25 +21,6 @@ func NewGroveRelayDriver(a DigitalWriter, pin string) *GroveRelayDriver { } } -// GroveRotaryDriver represents an analog rotary dial with a Grove connector -type GroveRotaryDriver struct { - *AnalogSensorDriver -} - -// NewGroveRotaryDriver returns a new GroveRotaryDriver with a polling interval of -// 10 Milliseconds given an AnalogReader and pin. -// -// Optionally accepts: -// time.Duration: Interval at which the AnalogSensor is polled for new information -// -// Adds the following API Commands: -// "Read" - See AnalogSensor.Read -func NewGroveRotaryDriver(a AnalogReader, pin string, v ...time.Duration) *GroveRotaryDriver { - return &GroveRotaryDriver{ - AnalogSensorDriver: NewAnalogSensorDriver(a, pin, v...), - } -} - // GroveLedDriver represents an LED with a Grove connector type GroveLedDriver struct { *LedDriver @@ -58,56 +39,6 @@ func NewGroveLedDriver(a DigitalWriter, pin string) *GroveLedDriver { } } -// GroveLightSensorDriver represents an analog light sensor -// with a Grove connector -type GroveLightSensorDriver struct { - *AnalogSensorDriver -} - -// NewGroveLightSensorDriver returns a new GroveLightSensorDriver with a polling interval of -// 10 Milliseconds given an AnalogReader and pin. -// -// Optionally accepts: -// time.Duration: Interval at which the AnalogSensor is polled for new information -// -// Adds the following API Commands: -// "Read" - See AnalogSensor.Read -func NewGroveLightSensorDriver(a AnalogReader, pin string, v ...time.Duration) *GroveLightSensorDriver { - return &GroveLightSensorDriver{ - AnalogSensorDriver: NewAnalogSensorDriver(a, pin, v...), - } -} - -// GrovePiezoVibrationSensorDriver represents an analog vibration sensor -// with a Grove connector -type GrovePiezoVibrationSensorDriver struct { - *AnalogSensorDriver -} - -// NewGrovePiezoVibrationSensorDriver returns a new GrovePiezoVibrationSensorDriver with a polling interval of -// 10 Milliseconds given an AnalogReader and pin. -// -// Optionally accepts: -// time.Duration: Interval at which the AnalogSensor is polled for new information -// -// Adds the following API Commands: -// "Read" - See AnalogSensor.Read -func NewGrovePiezoVibrationSensorDriver(a AnalogReader, pin string, v ...time.Duration) *GrovePiezoVibrationSensorDriver { - sensor := &GrovePiezoVibrationSensorDriver{ - AnalogSensorDriver: NewAnalogSensorDriver(a, pin, v...), - } - - sensor.AddEvent(Vibration) - - sensor.On(sensor.Event(Data), func(data interface{}) { - if data.(int) > 1000 { - sensor.Publish(sensor.Event(Vibration), data) - } - }) - - return sensor -} - // GroveBuzzerDriver represents a buzzer // with a Grove connector type GroveBuzzerDriver struct { @@ -138,26 +69,6 @@ func NewGroveButtonDriver(a DigitalReader, pin string, v ...time.Duration) *Grov } } -// GroveSoundSensorDriver represents a analog sound sensor -// with a Grove connector -type GroveSoundSensorDriver struct { - *AnalogSensorDriver -} - -// NewGroveSoundSensorDriver returns a new GroveSoundSensorDriver with a polling interval of -// 10 Milliseconds given an AnalogReader and pin. -// -// Optionally accepts: -// time.Duration: Interval at which the AnalogSensor is polled for new information -// -// Adds the following API Commands: -// "Read" - See AnalogSensor.Read -func NewGroveSoundSensorDriver(a AnalogReader, pin string, v ...time.Duration) *GroveSoundSensorDriver { - return &GroveSoundSensorDriver{ - AnalogSensorDriver: NewAnalogSensorDriver(a, pin, v...), - } -} - // GroveTouchDriver represents a touch button sensor // with a Grove connector type GroveTouchDriver struct { diff --git a/drivers/gpio/grove_drivers_test.go b/drivers/gpio/grove_drivers_test.go index 2ee418f9a..828912e2f 100644 --- a/drivers/gpio/grove_drivers_test.go +++ b/drivers/gpio/grove_drivers_test.go @@ -27,13 +27,9 @@ func TestDriverDefaults(t *testing.T) { drivers := []DriverAndPinner{ NewGroveTouchDriver(testAdaptor, pin), - NewGroveSoundSensorDriver(testAdaptor, pin), NewGroveButtonDriver(testAdaptor, pin), NewGroveBuzzerDriver(testAdaptor, pin), - NewGroveLightSensorDriver(testAdaptor, pin), - NewGrovePiezoVibrationSensorDriver(testAdaptor, pin), NewGroveLedDriver(testAdaptor, pin), - NewGroveRotaryDriver(testAdaptor, pin), NewGroveRelayDriver(testAdaptor, pin), NewGroveMagneticSwitchDriver(testAdaptor, pin), } @@ -76,48 +72,13 @@ func TestDigitalDriverHalt(t *testing.T) { } } -func TestAnalogDriverHalt(t *testing.T) { - testAdaptor := newGpioTestAdaptor() - pin := "456" - - drivers := []DriverAndEventer{ - NewGroveSoundSensorDriver(testAdaptor, pin), - NewGroveLightSensorDriver(testAdaptor, pin), - NewGrovePiezoVibrationSensorDriver(testAdaptor, pin), - NewGroveRotaryDriver(testAdaptor, pin), - } - - for _, driver := range drivers { - var callCount int32 - testAdaptorAnalogRead = func() (int, error) { - atomic.AddInt32(&callCount, 1) - return 42, nil - } - // Start the driver and allow for multiple digital reads - driver.Start() - time.Sleep(20 * time.Millisecond) - - driver.Halt() - lastCallCount := atomic.LoadInt32(&callCount) - // If driver was not halted, digital reads would still continue - time.Sleep(20 * time.Millisecond) - if atomic.LoadInt32(&callCount) != lastCallCount { - t.Errorf("AnalogRead was called after driver was halted") - } - } -} - func TestDriverPublishesError(t *testing.T) { testAdaptor := newGpioTestAdaptor() pin := "456" drivers := []DriverAndEventer{ NewGroveTouchDriver(testAdaptor, pin), - NewGroveSoundSensorDriver(testAdaptor, pin), NewGroveButtonDriver(testAdaptor, pin), - NewGroveLightSensorDriver(testAdaptor, pin), - NewGrovePiezoVibrationSensorDriver(testAdaptor, pin), - NewGroveRotaryDriver(testAdaptor, pin), NewGroveMagneticSwitchDriver(testAdaptor, pin), } @@ -128,7 +89,6 @@ func TestDriverPublishesError(t *testing.T) { err = errors.New("read error") return } - testAdaptorAnalogRead = returnErr testAdaptorDigitalRead = returnErr gobottest.Assert(t, driver.Start(), nil) diff --git a/examples/edison_grove_light_sensor.go b/examples/edison_grove_light_sensor.go index c4503e3ea..ee2d78db8 100644 --- a/examples/edison_grove_light_sensor.go +++ b/examples/edison_grove_light_sensor.go @@ -4,13 +4,13 @@ import ( "fmt" "gobot.io/x/gobot" - "gobot.io/x/gobot/drivers/gpio" + "gobot.io/x/gobot/drivers/aio" "gobot.io/x/gobot/platforms/intel-iot/edison" ) func main() { board := edison.NewAdaptor() - sensor := gpio.NewGroveLightSensorDriver(board, "0") + sensor := aio.NewGroveLightSensorDriver(board, "0") work := func() { sensor.On(sensor.Event("data"), func(data interface{}) { diff --git a/examples/edison_grove_piezo_vibration.go b/examples/edison_grove_piezo_vibration.go index d9977f578..c4616ea3b 100644 --- a/examples/edison_grove_piezo_vibration.go +++ b/examples/edison_grove_piezo_vibration.go @@ -4,16 +4,16 @@ import ( "fmt" "gobot.io/x/gobot" - "gobot.io/x/gobot/drivers/gpio" + "gobot.io/x/gobot/drivers/aio" "gobot.io/x/gobot/platforms/intel-iot/edison" ) func main() { board := edison.NewAdaptor() - sensor := gpio.NewGrovePiezoVibrationSensorDriver(board, "0") + sensor := aio.NewGrovePiezoVibrationSensorDriver(board, "0") work := func() { - sensor.On(gpio.Vibration, func(data interface{}) { + sensor.On(aio.Vibration, func(data interface{}) { fmt.Println("got one!") }) } diff --git a/examples/edison_grove_rotary_sensor.go b/examples/edison_grove_rotary_sensor.go index 90924d057..e9e89c5d0 100644 --- a/examples/edison_grove_rotary_sensor.go +++ b/examples/edison_grove_rotary_sensor.go @@ -4,16 +4,16 @@ import ( "fmt" "gobot.io/x/gobot" - "gobot.io/x/gobot/drivers/gpio" + "gobot.io/x/gobot/drivers/aio" "gobot.io/x/gobot/platforms/intel-iot/edison" ) func main() { board := edison.NewAdaptor() - sensor := gpio.NewGroveRotaryDriver(board, "0") + sensor := aio.NewGroveRotaryDriver(board, "0") work := func() { - sensor.On(gpio.Data, func(data interface{}) { + sensor.On(aio.Data, func(data interface{}) { fmt.Println("sensor", data) }) } diff --git a/examples/edison_grove_sound_sensor.go b/examples/edison_grove_sound_sensor.go index 19a1393e5..d6ac26532 100644 --- a/examples/edison_grove_sound_sensor.go +++ b/examples/edison_grove_sound_sensor.go @@ -4,16 +4,16 @@ import ( "fmt" "gobot.io/x/gobot" - "gobot.io/x/gobot/drivers/gpio" + "gobot.io/x/gobot/drivers/aio" "gobot.io/x/gobot/platforms/intel-iot/edison" ) func main() { board := edison.NewAdaptor() - sensor := gpio.NewGroveSoundSensorDriver(board, "0") + sensor := aio.NewGroveSoundSensorDriver(board, "0") work := func() { - sensor.On(gpio.Data, func(data interface{}) { + sensor.On(aio.Data, func(data interface{}) { fmt.Println("sensor", data) }) } diff --git a/examples/edison_grove_temperature_sensor.go b/examples/edison_grove_temperature_sensor.go index 41d051d46..73e87c007 100644 --- a/examples/edison_grove_temperature_sensor.go +++ b/examples/edison_grove_temperature_sensor.go @@ -5,13 +5,13 @@ import ( "time" "gobot.io/x/gobot" - "gobot.io/x/gobot/drivers/gpio" + "gobot.io/x/gobot/drivers/aio" "gobot.io/x/gobot/platforms/intel-iot/edison" ) func main() { board := edison.NewAdaptor() - sensor := gpio.NewGroveTemperatureSensorDriver(board, "0") + sensor := aio.NewGroveTemperatureSensorDriver(board, "0") work := func() { gobot.Every(500*time.Millisecond, func() { diff --git a/examples/edison_led_brightness_with_analog_input.go b/examples/edison_led_brightness_with_analog_input.go index 2446f0bd5..1f7db4910 100644 --- a/examples/edison_led_brightness_with_analog_input.go +++ b/examples/edison_led_brightness_with_analog_input.go @@ -4,17 +4,18 @@ import ( "fmt" "gobot.io/x/gobot" + "gobot.io/x/gobot/drivers/aio" "gobot.io/x/gobot/drivers/gpio" "gobot.io/x/gobot/platforms/intel-iot/edison" ) func main() { e := edison.NewAdaptor() - sensor := gpio.NewAnalogSensorDriver(e, "0") + sensor := aio.NewAnalogSensorDriver(e, "0") led := gpio.NewLedDriver(e, "3") work := func() { - sensor.On(gpio.Data, func(data interface{}) { + sensor.On(aio.Data, func(data interface{}) { brightness := uint8( gobot.ToScale(gobot.FromScale(float64(data.(int)), 0, 4096), 0, 255), )