hybridgroup.gobot/platforms/adaptors/i2cbusadaptor.go

90 lines
2.1 KiB
Go

package adaptors
import (
"fmt"
"sync"
multierror "github.com/hashicorp/go-multierror"
"gobot.io/x/gobot/v2"
"gobot.io/x/gobot/v2/drivers/i2c"
"gobot.io/x/gobot/v2/system"
)
type i2cBusNumberValidator func(busNumber int) error
// I2cBusAdaptor is a adaptor for i2c bus, normally used for composition in platforms.
type I2cBusAdaptor struct {
sys *system.Accesser
validateNumber i2cBusNumberValidator
defaultBusNumber int
mutex sync.Mutex
buses map[int]gobot.I2cSystemDevicer
}
// NewI2cBusAdaptor provides the access to i2c buses of the board. The validator is used to check the bus number,
// which is given by user, to the abilities of the board.
func NewI2cBusAdaptor(sys *system.Accesser, v i2cBusNumberValidator, defaultBusNr int) *I2cBusAdaptor {
a := &I2cBusAdaptor{
sys: sys,
validateNumber: v,
defaultBusNumber: defaultBusNr,
}
return a
}
// Connect prepares the connection to i2c buses.
func (a *I2cBusAdaptor) Connect() error {
a.mutex.Lock()
defer a.mutex.Unlock()
a.buses = make(map[int]gobot.I2cSystemDevicer)
return nil
}
// Finalize closes all i2c buses.
func (a *I2cBusAdaptor) Finalize() error {
a.mutex.Lock()
defer a.mutex.Unlock()
var err error
for _, bus := range a.buses {
if bus != nil {
if e := bus.Close(); e != nil {
err = multierror.Append(err, e)
}
}
}
a.buses = nil
return err
}
// GetI2cConnection returns a connection to a device on a specified i2c bus
func (a *I2cBusAdaptor) GetI2cConnection(address int, busNum int) (i2c.Connection, error) {
a.mutex.Lock()
defer a.mutex.Unlock()
if a.buses == nil {
return nil, fmt.Errorf("not connected")
}
bus := a.buses[busNum]
if bus == nil {
err := a.validateNumber(busNum)
if err != nil {
return nil, err
}
bus, err = a.sys.NewI2cDevice(fmt.Sprintf("/dev/i2c-%d", busNum))
if err != nil {
return nil, err
}
a.buses[busNum] = bus
}
return i2c.NewConnection(bus, address), nil
}
// DefaultI2cBus returns the default i2c bus number for this platform.
func (a *I2cBusAdaptor) DefaultI2cBus() int {
return a.defaultBusNumber
}