Skip to content

Commit 888810e

Browse files
authored
adaptors(all): add debug option (#1181)
1 parent ee3e183 commit 888810e

37 files changed

+628
-122
lines changed

debug.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package gobot
2+
3+
import "fmt"
4+
5+
func Debuglnf(isDebug bool, format string, a ...interface{}) {
6+
if isDebug {
7+
msg := fmt.Sprintf(format, a...)
8+
fmt.Printf("<Debug>: %s\n", msg)
9+
}
10+
}

platforms/adaptors/analogpinsadaptor.go

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,35 +10,65 @@ import (
1010

1111
type analogPinTranslator func(pin string) (path string, w bool, readBufLen uint16, err error)
1212

13+
// analogPinsConfiguration contains all changeable attributes of the adaptor.
14+
type analogPinsConfiguration struct {
15+
debug bool
16+
}
17+
1318
// AnalogPinsAdaptor is a adaptor for analog pins, normally used for composition in platforms.
1419
// It is also usable for general sysfs access.
1520
type AnalogPinsAdaptor struct {
16-
sys *system.Accesser
17-
translate analogPinTranslator
18-
pins map[string]gobot.AnalogPinner
19-
mutex sync.Mutex
21+
sys *system.Accesser
22+
analogPinsCfg *analogPinsConfiguration
23+
translate analogPinTranslator
24+
pins map[string]gobot.AnalogPinner
25+
mutex sync.Mutex
2026
}
2127

2228
// NewAnalogPinsAdaptor provides the access to analog pins of the board. Usually sysfs system drivers are used.
2329
// The translator is used to adapt the pin header naming, which is given by user, to the internal file name
2430
// nomenclature. This varies by each platform.
25-
func NewAnalogPinsAdaptor(sys *system.Accesser, t analogPinTranslator) *AnalogPinsAdaptor {
31+
//
32+
// Options:
33+
//
34+
// "WithAnalogPinDebug"
35+
func NewAnalogPinsAdaptor(
36+
sys *system.Accesser,
37+
t analogPinTranslator,
38+
opts ...AnalogPinsOptionApplier,
39+
) *AnalogPinsAdaptor {
2640
a := AnalogPinsAdaptor{
27-
sys: sys,
28-
translate: t,
41+
sys: sys,
42+
analogPinsCfg: &analogPinsConfiguration{},
43+
translate: t,
44+
}
45+
46+
for _, o := range opts {
47+
o.apply(a.analogPinsCfg)
2948
}
3049

3150
sys.AddAnalogSupport()
3251

3352
return &a
3453
}
3554

55+
// WithAnalogPinDebug can be used to switch on debugging for analog pins implementation.
56+
func WithAnalogPinDebug() analogPinsDebugOption {
57+
return analogPinsDebugOption(true)
58+
}
59+
3660
// Connect prepare new connection to analog pins.
3761
func (a *AnalogPinsAdaptor) Connect() error {
3862
a.mutex.Lock()
3963
defer a.mutex.Unlock()
4064

65+
if a.pins != nil {
66+
return fmt.Errorf("analog pin adaptor already connected, please call Finalize() for re-connect")
67+
}
68+
4169
a.pins = make(map[string]gobot.AnalogPinner)
70+
a.debuglnf("connect the analog pins adaptor done")
71+
4272
return nil
4373
}
4474

@@ -47,7 +77,11 @@ func (a *AnalogPinsAdaptor) Finalize() error {
4777
a.mutex.Lock()
4878
defer a.mutex.Unlock()
4979

80+
// nothing to do at the moment, because the file access for each pin will be closed immediately after read/write
81+
5082
a.pins = nil
83+
a.debuglnf("finalize the analog pins adaptor done")
84+
5185
return nil
5286
}
5387

@@ -96,3 +130,7 @@ func (a *AnalogPinsAdaptor) analogPin(id string) (gobot.AnalogPinner, error) {
96130

97131
return pin, nil
98132
}
133+
134+
func (a *AnalogPinsAdaptor) debuglnf(format string, p ...interface{}) {
135+
gobot.Debuglnf(a.analogPinsCfg.debug, format, p...)
136+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package adaptors
2+
3+
// AnalogPinsOptionApplier is the interface for analog pins adaptor options. This provides the possibility for change
4+
// the platform behavior by the user when creating the platform, e.g. by "NewAdaptor()".
5+
// The interface needs to be implemented by each configurable option type.
6+
type AnalogPinsOptionApplier interface {
7+
apply(cfg *analogPinsConfiguration)
8+
}
9+
10+
// analogPinsDebugOption is the type to switch on analog pins related debug messages.
11+
type analogPinsDebugOption bool
12+
13+
func (o analogPinsDebugOption) String() string {
14+
return "switch on debugging for analog pins option"
15+
}
16+
17+
func (o analogPinsDebugOption) apply(cfg *analogPinsConfiguration) {
18+
cfg.debug = bool(o)
19+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package adaptors
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/assert"
7+
8+
"gobot.io/x/gobot/v2/system"
9+
)
10+
11+
func TestWithAnalogPinDebug(t *testing.T) {
12+
// This is a general test, that options are applied in constructor. Further tests for options
13+
// can also be done by call of "WithOption(val).apply(cfg)".
14+
// arrange & act
15+
a := NewAnalogPinsAdaptor(system.NewAccesser(), nil, WithAnalogPinDebug())
16+
// assert
17+
assert.True(t, a.analogPinsCfg.debug)
18+
}

platforms/adaptors/digitalpinsadaptor.go

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ func NewDigitalPinsAdaptor(
6161
return &a
6262
}
6363

64-
// WithDigitalPinDebug can be used to switch on debugging for SPI implementation.
64+
// WithDigitalPinDebug can be used to switch on debugging for digital pins implementation.
6565
func WithDigitalPinDebug() digitalPinsDebugOption {
6666
return digitalPinsDebugOption(true)
6767
}
@@ -163,15 +163,12 @@ func (a *DigitalPinsAdaptor) Connect() error {
163163
a.mutex.Lock()
164164
defer a.mutex.Unlock()
165165

166-
if a.digitalPinsCfg.debug {
167-
fmt.Println("connect the digital pins adaptor")
168-
}
169-
170166
if a.pins != nil {
171167
return fmt.Errorf("digital pin adaptor already connected, please call Finalize() for re-connect")
172168
}
173169

174170
a.pins = make(map[string]gobot.DigitalPinner)
171+
a.debuglnf("connect the digital pins adaptor done")
175172

176173
return nil
177174
}
@@ -181,19 +178,20 @@ func (a *DigitalPinsAdaptor) Finalize() error {
181178
a.mutex.Lock()
182179
defer a.mutex.Unlock()
183180

184-
if a.digitalPinsCfg.debug {
185-
fmt.Println("finalize the digital pins adaptor")
186-
}
181+
a.debuglnf("finalize the digital pins adaptor with %d pins...", len(a.pins))
187182

188183
var err error
189-
for _, pin := range a.pins {
184+
for id, pin := range a.pins {
190185
if pin != nil {
191-
if e := pin.Unexport(); e != nil {
186+
e := pin.Unexport()
187+
if e != nil {
192188
err = multierror.Append(err, e)
193189
}
190+
a.debuglnf("finalize the digital pin '%s' done with error: %v", id, e)
194191
}
195192
}
196193
a.pins = nil
194+
a.debuglnf("finalize the digital pins adaptor done with error: %v", err)
197195

198196
return err
199197
}
@@ -260,3 +258,7 @@ func (a *DigitalPinsAdaptor) digitalPin(
260258

261259
return pin, nil
262260
}
261+
262+
func (a *DigitalPinsAdaptor) debuglnf(format string, p ...interface{}) {
263+
gobot.Debuglnf(a.digitalPinsCfg.debug, format, p...)
264+
}

platforms/adaptors/digitalpinsadaptoroptions_test.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,21 @@ import (
1515
func TestDigitalPinsWithGpiosActiveLow(t *testing.T) {
1616
// This is a general test, that options are applied in constructor. Further tests for options
1717
// can also be done by call of "WithOption(val).apply(cfg)".
18-
// arrange & act, connect is mandatory to set options to the system
18+
// arrange & act
1919
a := NewDigitalPinsAdaptor(system.NewAccesser(), nil, WithGpiosActiveLow("1", "12", "33"))
20-
require.NoError(t, a.Connect())
2120
// assert
2221
assert.Len(t, a.digitalPinsCfg.pinOptions, 3)
2322
}
2423

24+
func TestWithDigitalPinDebug(t *testing.T) {
25+
// arrange
26+
cfg := &digitalPinsConfiguration{debug: false}
27+
// act
28+
WithDigitalPinDebug().apply(cfg)
29+
// assert
30+
assert.True(t, cfg.debug)
31+
}
32+
2533
func TestDigitalPinsWithDigitalPinInitializer(t *testing.T) {
2634
// arrange
2735
const (

platforms/adaptors/i2cbusadaptor.go

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,15 @@ import (
1313

1414
type i2cBusNumberValidator func(busNumber int) error
1515

16+
// i2cBusConfiguration contains all changeable attributes of the adaptor.
17+
type i2cBusConfiguration struct {
18+
debug bool
19+
}
20+
1621
// I2cBusAdaptor is a adaptor for i2c bus, normally used for composition in platforms.
1722
type I2cBusAdaptor struct {
1823
sys *system.Accesser
24+
i2cBusCfg *i2cBusConfiguration
1925
validateNumber i2cBusNumberValidator
2026
defaultBusNumber int
2127
mutex sync.Mutex
@@ -24,24 +30,49 @@ type I2cBusAdaptor struct {
2430

2531
// NewI2cBusAdaptor provides the access to i2c buses of the board. The validator is used to check the bus number,
2632
// which is given by user, to the abilities of the board.
27-
func NewI2cBusAdaptor(sys *system.Accesser, v i2cBusNumberValidator, defaultBusNr int) *I2cBusAdaptor {
33+
//
34+
// Options:
35+
//
36+
// "WithI2cDebug"
37+
func NewI2cBusAdaptor(
38+
sys *system.Accesser,
39+
v i2cBusNumberValidator,
40+
defaultBusNr int,
41+
opts ...I2CBusOptionApplier,
42+
) *I2cBusAdaptor {
2843
a := I2cBusAdaptor{
2944
sys: sys,
45+
i2cBusCfg: &i2cBusConfiguration{},
3046
validateNumber: v,
3147
defaultBusNumber: defaultBusNr,
3248
}
3349

50+
for _, o := range opts {
51+
o.apply(a.i2cBusCfg)
52+
}
53+
3454
sys.AddI2CSupport()
3555

3656
return &a
3757
}
3858

59+
// WithI2cDebug can be used to switch on debugging for I2C implementation.
60+
func WithI2cDebug() i2cBusDebugOption {
61+
return i2cBusDebugOption(true)
62+
}
63+
3964
// Connect prepares the connection to i2c buses.
4065
func (a *I2cBusAdaptor) Connect() error {
4166
a.mutex.Lock()
4267
defer a.mutex.Unlock()
4368

69+
if a.buses != nil {
70+
return fmt.Errorf("I2C bus adaptor already connected, please call Finalize() for re-connect")
71+
}
72+
4473
a.buses = make(map[int]gobot.I2cSystemDevicer)
74+
a.debuglnf("connect the I2C bus adaptor done")
75+
4576
return nil
4677
}
4778

@@ -50,15 +81,21 @@ func (a *I2cBusAdaptor) Finalize() error {
5081
a.mutex.Lock()
5182
defer a.mutex.Unlock()
5283

84+
a.debuglnf("finalize the I2C bus adaptor for %d buses...", len(a.buses))
85+
5386
var err error
54-
for _, bus := range a.buses {
87+
for busNum, bus := range a.buses {
5588
if bus != nil {
56-
if e := bus.Close(); e != nil {
89+
e := bus.Close()
90+
if e != nil {
5791
err = multierror.Append(err, e)
5892
}
93+
a.debuglnf("I2C bus %d closed with error: %v", busNum, e)
5994
}
6095
}
6196
a.buses = nil
97+
a.debuglnf("finalize the I2C bus adaptor done with error: %v", err)
98+
6299
return err
63100
}
64101

@@ -90,3 +127,7 @@ func (a *I2cBusAdaptor) GetI2cConnection(address int, busNum int) (i2c.Connectio
90127
func (a *I2cBusAdaptor) DefaultI2cBus() int {
91128
return a.defaultBusNumber
92129
}
130+
131+
func (a *I2cBusAdaptor) debuglnf(format string, p ...interface{}) {
132+
gobot.Debuglnf(a.i2cBusCfg.debug, format, p...)
133+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package adaptors
2+
3+
// I2CBusOptionApplier is the interface for I2C bus adaptors options. This provides the possibility for change the
4+
// platform behavior by the user when creating the platform, e.g. by "NewAdaptor()".
5+
// The interface needs to be implemented by each configurable option type.
6+
type I2CBusOptionApplier interface {
7+
apply(cfg *i2cBusConfiguration)
8+
}
9+
10+
// i2cBusDebugOption is the type to switch on I2C related debug messages.
11+
type i2cBusDebugOption bool
12+
13+
func (o i2cBusDebugOption) String() string {
14+
return "switch on debugging for I2C option"
15+
}
16+
17+
func (o i2cBusDebugOption) apply(cfg *i2cBusConfiguration) {
18+
cfg.debug = bool(o)
19+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package adaptors
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/assert"
7+
8+
"gobot.io/x/gobot/v2/system"
9+
)
10+
11+
func TestWithI2cDebug(t *testing.T) {
12+
// This is a general test, that options are applied in constructor. Further tests for options
13+
// can also be done by call of "WithOption(val).apply(cfg)".
14+
// arrange & act
15+
a := NewI2cBusAdaptor(system.NewAccesser(), nil, 0, WithI2cDebug())
16+
// assert
17+
assert.True(t, a.i2cBusCfg.debug)
18+
}

0 commit comments

Comments
 (0)